00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "gismo/GParticle.h"
00011
00012 #include "DecayEntry.h"
00013 #include "gismo/PDT.h"
00014 #include "gismo/Units.h"
00015 #include "facilities/error.h"
00016 #include "Random.h"
00017 #include <algorithm>
00018 #include <strstream>
00019 inline static double sqr(double x){return x*x;}
00020
00021 GParticle::GParticle(const PData * data, float mass)
00022 : pData(data)
00023 , m_parent(0)
00024 , m_first_child(0)
00025 , m_next_sibling(0)
00026 , _time(0)
00027 {
00028 setMass(mass);
00029 }
00030
00031 GParticle::GParticle(long id,float mass)
00032 : m_parent(0)
00033 , m_first_child(0)
00034 , m_next_sibling(0)
00035 , _time(0)
00036 {
00037 pData = _thePDT->lookUp(id);
00038 if (pData == 0)
00039 FATAL("cannot create particle!");
00040 setMass(mass);
00041 }
00042
00043 GParticle::GParticle(const char* name, float mass)
00044 : m_parent(0)
00045 , m_first_child(0)
00046 , m_next_sibling(0)
00047 , _time(0)
00048 {
00049 pData = _thePDT->lookUp(name);
00050 if (pData == 0)
00051 FATAL("cannot create particle!");
00052 setMass(mass);
00053 }
00054
00055 GParticle::GParticle(const GParticle& p)
00056 : HepLorentzVector((HepLorentzVector&)p)
00057 , pData(p.pData)
00058 , m_parent(&p)
00059 , m_first_child(0)
00060 , m_next_sibling(0)
00061 , _mass(p._mass)
00062 , _r(p._r)
00063 , _time(p._time)
00064 {}
00065
00066
00067 void GParticle::setMass(float mass)
00068 {
00069 _mass = mass<0 ? Random::breitWigner(pData->mass(), pData->width(),
00070 pData->widthCut())
00071 : mass ;
00072 setE(_mass);
00073 }
00074
00075
00076 GParticle&
00077 GParticle::setMomentum(const Vector & p)
00078 {
00079 setVect(p);
00080 setE(sqrt(vect().mag2() + _mass*_mass));
00081 return *this;
00082 }
00083
00084
00085 GParticle&
00086 GParticle::setEnergy(float e)
00087 {
00088 e = std::max(e,_mass);
00089 float scale = sqrt((e*e - _mass*_mass)/vect().mag2());
00090 setE( e );
00091 setVect(vect()*scale);
00092 return *this;
00093 }
00094
00095
00096 float GParticle::GenerateTimeOfDecay()
00097 {
00098 return (pData->lifeTime() > 0 && pData->lifeTime()< 1e8)
00099 ? Random::exponential(pData->lifeTime())
00100 : pData->lifeTime();
00101 }
00102
00103 GParticle::~GParticle()
00104 {
00105 removeChildren();
00106 }
00107
00108 void GParticle::setParent(GParticle* p){m_parent = p;}
00109
00110 void GParticle::decayOnce()
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 {
00123 const DecayEntry* de = pData->decayInfo();
00124 if (de == 0) return;
00125
00126 int anti = pData->idCode() < 0;
00127
00128
00129
00130 float r = Random::flat(pData->sumBR());
00131 while ((r -= de->branchingFraction)>0 && de->next != 0) de=de->next;
00132
00133
00134 if (de->numChildren > 0) {
00135
00136 float Q = -1.0;
00137 for(unsigned ntries = 0; ntries < MAX_TRIES; ntries++) {
00138 Q = mass();
00139
00140 for( int i=0; i < de->numChildren; i++ ){
00141
00142 PData *childData = de->children[i];
00143 if( anti ) childData = childData->antiParticle;
00144 GParticle* child = addChild(childData);
00145
00146 Q -= child->mass();
00147 }
00148
00149
00150 if (Q < 0.){
00151 std::ostrstream serr;
00152 serr<< "Decay kinematically forbidden:" <<de->name()<<'\n';
00153 serr<< "trying again\n";
00154 WARNING(serr.str());
00155 removeChildren();;
00156 }
00157 else
00158 {
00159 break;
00160 }
00161 }
00162 if (Q<0.)FATAL( "Failed, aborting...");
00163 }
00164
00165
00166 Vector beta(px()/e(),py()/e(),pz()/e());
00167 Vector oldMomentum( momentum() );
00168 setMomentum(Vector(0,0,0));
00169
00170
00171 if (! de->decay( this)) {
00172
00173 WARNING("*** Error in decay\n");
00174 removeChildren();
00175 return;
00176 }
00177
00178
00179
00180 if (beta.mag()!=0.) boost(beta);
00181 setMomentum( oldMomentum );
00182
00183 }
00184
00185 void
00186 GParticle::removeChildren()
00187 {
00188 GParticle* next_child = m_first_child;
00189 while( next_child) {
00190 GParticle* tc = next_child->m_next_sibling;
00191 delete next_child;
00192 next_child = tc;
00193 }
00194 m_first_child = 0;
00195 }
00196
00197 GParticle*
00198 GParticle::addChild(GParticle * child)
00199
00200 {
00201 if( ! m_first_child) m_first_child = child;
00202 else {
00203 GParticle* this_child = m_first_child;
00204 while(this_child-> m_next_sibling !=0 ) this_child= this_child->m_next_sibling;
00205 this_child->m_next_sibling = child;
00206 }
00207 child->setParent(this);
00208 child->setPosition(_r);
00209 child->setT(_time);
00210 return child;
00211 }
00212
00213 GParticle *
00214 GParticle::addChild(const PData* childData, float mass)
00215 {
00216 return addChild(new GParticle(childData, mass));
00217 }
00218 int
00219 GParticle::numChildren()const
00220 {
00221 int n = 0;
00222 GParticle* the_child = m_first_child;
00223 while(the_child != 0){
00224 n++; the_child = the_child->m_next_sibling;
00225 }
00226 return n;
00227
00228 }
00229
00230 const GParticle*
00231 GParticle::parent()const{return m_parent;}
00232
00233 GParticle*
00234 GParticle::child(int n)const
00235 {
00236 GParticle* the_child = m_first_child;
00237 while(n-- && the_child !=0 ) the_child = the_child->m_next_sibling;
00238 return the_child;
00239 }
00240
00241
00242 void
00243 GParticle::boost(const Vector& b)
00244 {
00245 HepLorentzVector::boost(b);
00246
00247 for(int i=0; i<numChildren(); i++)
00248 child(i)->boost(b);
00249 }
00250
00251
00252 static int level;
00253 void GParticle::printAll(std::ostream& cout) const
00254 {
00255 if( !parent() ) level=0;
00256 printOn(cout);
00257 level++;
00258 for(int i=0; i<numChildren(); i++)
00259 child(i)->printAll(cout);
00260 level--;
00261 }
00262 void GParticle::printOn(std::ostream& cout) const
00263 {
00264 cout << '\n';
00265 for(int i=0;i<level;i++)
00266 cout << " ";
00267 cout << name() << ' ';
00268 cout << *(HepLorentzVector*)this;
00269 cout << " at: " << _r;
00270 }
00271
00272 void
00273 GParticle::scatterBy(double theta, double phi)
00274 {
00275 double sinthe = sin(theta),
00276 sinps2=sqr(px())+sqr(py()),
00277 magnitude = sinps2 + sqr(pz());
00278 if( magnitude==0 ) return;
00279 sinps2 /=magnitude;
00280 magnitude = sqrt(magnitude);
00281 double cosTheta = cos(theta);
00282
00283
00284
00285 if (sinps2 < 1.0e-20)
00286 {
00287
00288 if(pz() < 0.) cosTheta = -cosTheta;
00289 setVect(Vector(sinthe*cos(phi), sinthe*sin(phi), cosTheta ));
00290 }
00291 else
00292 {
00293
00294 float a=px()/magnitude,
00295 b=py()/magnitude,
00296 c=pz()/magnitude,
00297 sinpsi=sqrt(sinps2),
00298 us=sinthe*cos(phi),
00299 vs=sinthe*sin(phi),
00300 sindel=b/sinpsi,
00301 cosdel=a/sinpsi;
00302 setVect(Vector(c*cosdel*us - sindel*vs + a*cosTheta ,
00303 c*sindel*us + cosdel*vs + b*cosTheta ,
00304 -sinpsi*us + c*cosTheta ));
00305 }
00306 setVect(vect()*magnitude);
00307 }
00308
00309 PDT* GParticle::_thePDT = PDT::createDefault();
00310 const unsigned GParticle::MAX_TRIES=100;
00311
00312 HepBoolean GParticle::hasPostionInfo() const{return true;}
00313 float GParticle::timeOfDecay()const{return -1;}
00314