Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

GParticle.cxx

Go to the documentation of this file.
00001 // $Id: GParticle.cxx,v 1.4 2000/05/05 04:38:33 burnett Exp $
00002 //
00003 // This file is part of Gismo 2
00004 //
00005 //
00006 // This is the implementation of the GParticle class.
00007 // and Random::theGenerator
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 // copy constructor -- do not copy children, make original "parent"
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 // set the mass: this is private, only done from constructor with momentum zero
00067 void GParticle::setMass(float mass)
00068 {  // negative is flag to generate with breitWigner
00069         _mass = mass<0 ? Random::breitWigner(pData->mass(), pData->width(),
00070                                                         pData->widthCut())
00071                                          : mass ;
00072         setE(_mass);
00073 }
00074 
00075 // set the mometum, adjusting the energy
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 // set the energy, scaling the momentum to preserve the mass
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 // Summary -------------------------------------------------------------
00112 //
00113 //    Decay the particle, creating daughters and attaching them
00114 //
00115 // Parameters
00116 //
00117 //   none
00118 //
00119 // Remarks
00120 //
00121 // End -----------------------------------------------------------------
00122 {
00123     const DecayEntry* de = pData->decayInfo();
00124     if (de == 0) return;
00125 
00126     int anti = pData->idCode() < 0;
00127 
00128     // choose the decay
00129 
00130     float r = Random::flat(pData->sumBR());
00131     while ((r -= de->branchingFraction)>0 && de->next != 0) de=de->next;
00132 
00133     // create the secondary particles at rest for the decayer
00134     if (de->numChildren > 0)    {
00135 
00136         float Q = -1.0; // the failure code
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); // this is virtual to allow addition of
00145                                                         // supclass
00146                 Q -= child->mass();
00147             }
00148 
00149             // check that it is possible: maybe need to recreate?
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     // boost to rest frame: first save current velocity;
00166     Vector beta(px()/e(),py()/e(),pz()/e());
00167     Vector oldMomentum( momentum() );  //save original (possible round-off when restore)
00168     setMomentum(Vector(0,0,0));
00169 
00170     // apply matrix elements, etc.
00171     if (! de->decay( this))     {
00172         // cannot decay: must reverse
00173         WARNING("*** Error in decay\n");
00174         removeChildren();
00175         return;
00176     }
00177 
00178     // boost secondaries from rest frame to lab frame
00179 
00180     if (beta.mag()!=0.) boost(beta);
00181     setMomentum( oldMomentum );  //restore
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 // used by a client to set a single "child"
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 // this is virtual, so that a sub class will add its own kind
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);    // this is virtual!
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     //   if sinps2 is small, no rotation is needed
00284 
00285     if (sinps2 < 1.0e-20)
00286     {
00287         //small polar angle case
00288         if(pz() < 0.) cosTheta = -cosTheta;
00289         setVect(Vector(sinthe*cos(phi), sinthe*sin(phi), cosTheta ));
00290     }
00291     else
00292     {
00293         //large polar angle case
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();  // pdt used to create particles
00310 const unsigned GParticle::MAX_TRIES=100;
00311 //don't really want these
00312 HepBoolean GParticle::hasPostionInfo() const{return true;}
00313 float GParticle::timeOfDecay()const{return -1;}
00314 

Generated at Wed Nov 21 12:20:25 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000