PH_HEPEVT_Interface.cxx

00001 #include <vector>
00002 #include <cmath>
00003 #include "PhotosBranch.h"
00004 #include "PhotosParticle.h"
00005 #include "PH_HEPEVT_Interface.h"
00006 #include "Log.h"
00007 using namespace std;
00008 
00009 namespace Photospp
00010 {
00011 
00012 vector<PhotosParticle*> PH_HEPEVT_Interface::m_particle_list;
00013 int PH_HEPEVT_Interface::ME_channel=0;
00014 int PH_HEPEVT_Interface::decay_idx=0;
00015 
00016 void PH_HEPEVT_Interface::clear(){
00017 
00018   m_particle_list.clear();
00019 
00020   ph_hepevt_.nevhep=0; 
00021   ph_hepevt_.nhep=0;
00022   
00023 
00024   /**  for(int i=0; i < NMXHEP; i++){
00025 
00026     ph_hepevt_.isthep[i]=0;
00027     ph_hepevt_.idhep[i]=0;
00028     
00029     for(int j=0; j<2; j++){
00030       ph_hepevt_.jmohep[i][j]=0;
00031       ph_hepevt_.jdahep[i][j]=0;
00032     }
00033     
00034     for(int j=0; j<5; j++)
00035       ph_hepevt_.phep[i][j]=0;
00036     
00037     for(int j=0; j<4; j++)
00038       ph_hepevt_.vhep[i][j]=0;
00039   
00040       ph_phoqed_.qedrad[i]=0;
00041   
00042       }**/
00043 }
00044 
00045 void PH_HEPEVT_Interface::add_particle(int i,PhotosParticle * particle,
00046                                        int first_mother, int last_mother,
00047                                        int first_daughter, int last_daughter){
00048 
00049   if(i>0)
00050     i--; //account for fortran indicies begining at 1
00051   else
00052     Log::Warning()<<"Index given to PH_HEPEVT_Interface::add_particle "
00053                   <<"is too low (it must be > 0)."<<endl;
00054 
00055   //add to our internal list of pointer/index pairs
00056   m_particle_list.push_back(particle);
00057 
00058   //now set the element of PH_HEPEVT
00059   ph_hepevt_.nevhep=0; //dummy
00060   ph_hepevt_.nhep=ph_hepevt_.nhep++;
00061   ph_hepevt_.isthep[i]=particle->getStatus();
00062   ph_hepevt_.idhep[i]=particle->getPdgID();
00063 
00064   ph_hepevt_.jmohep[i][0]=first_mother;
00065   ph_hepevt_.jmohep[i][1]=last_mother;
00066 
00067   ph_hepevt_.jdahep[i][0]=first_daughter;
00068   ph_hepevt_.jdahep[i][1]=last_daughter;
00069 
00070   ph_hepevt_.phep[i][0]=particle->getPx();
00071   ph_hepevt_.phep[i][1]=particle->getPy();
00072   ph_hepevt_.phep[i][2]=particle->getPz();
00073   ph_hepevt_.phep[i][3]=particle->getE();
00074   
00075   // if massFrom4Vector=true (default) - get sqrt(e^2-p^2)
00076   // otherwise - get mass from event record
00077   if(!Photos::massFrom4Vector) ph_hepevt_.phep[i][4]=particle->getMass();
00078   else                         ph_hepevt_.phep[i][4]=particle->getVirtuality();
00079 
00080   int pdgid = abs(particle->getPdgID());
00081 
00082   // if 'forceMass' for this PDGID was used - overwrite mass
00083   if(Photos::forceMassList)
00084   {
00085     for(unsigned int j=0;j<Photos::forceMassList->size();j++)
00086     {
00087       if(pdgid == abs(Photos::forceMassList->at(j)->first))
00088       {
00089         double mass = Photos::forceMassList->at(j)->second;
00090         
00091         // when 'forceMass' is used the mass provided is larger than 0.0
00092         // when 'forceMassFromEventRecord' is used mass is -1.0
00093         // in this case - get mass from event record
00094         if(mass<0.0) mass = particle->getMass();
00095         ph_hepevt_.phep[i][4] = mass;
00096       }
00097     }
00098   }
00099 
00100   ph_hepevt_.vhep[i][0]=0;
00101   ph_hepevt_.vhep[i][1]=0;
00102   ph_hepevt_.vhep[i][2]=0;
00103   ph_hepevt_.vhep[i][3]=0;
00104 
00105   ph_phoqed_.qedrad[i]=1;
00106 
00107 }
00108 
00109 int PH_HEPEVT_Interface::set(PhotosBranch *branch)
00110 {
00111         PH_HEPEVT_Interface::clear();
00112         int idx=1;
00113 
00114         //get mothers
00115         vector<PhotosParticle *> mothers = branch->getMothers();
00116         int nmothers=mothers.size();
00117 
00118         //check if mid-particle exist
00119         decay_idx=0;
00120         PhotosParticle *decay_particle = branch->getDecayingParticle();
00121         if(decay_particle) decay_idx=nmothers+1;
00122 
00123         //get daughters
00124         vector<PhotosParticle *> daughters = branch->getDaughters();
00125         int ndaughters=daughters.size();
00126 
00127         for(int i=0;i<nmothers;i++)
00128         {
00129                 if(decay_idx)
00130                         add_particle(idx++,mothers.at(i),
00131                                      0,0, //mothers
00132                                      decay_idx,decay_idx); //daughters
00133                 else
00134                         add_particle(idx++,mothers.at(i),
00135                                      0,0, //mothers
00136                                      nmothers+1,nmothers+ndaughters); //daughters
00137         }
00138 
00139         if(decay_particle)
00140                 add_particle(idx++,decay_particle,
00141                              1,nmothers, //mothers
00142                              nmothers+2,nmothers+1+ndaughters); //daughters
00143 
00144         for(int i=0;i<ndaughters;i++)
00145         {
00146                 if(decay_idx)
00147                         add_particle(idx++,daughters.at(i),
00148                                      decay_idx,decay_idx, //mothers
00149                                      0,0); //daughters
00150                 else
00151                         add_particle(idx++,daughters.at(i),
00152                                      1,nmothers, //mothers
00153                                      0,0); //daughters
00154         }
00155         //Log::RedirectOutput( phodmp_ , Log::Debug(1000) );
00156         Log::Debug(1000,false)<<"PH_HEPEVT returning: "<<( (decay_idx) ? decay_idx : 1 )<<" from "<<idx-1<<" particles."<<endl;
00157         return (decay_idx) ? decay_idx : 1;
00158 }
00159 
00160 void PH_HEPEVT_Interface::get(){
00161 
00162   int index = 0;
00163 
00164   //if no photons have been added to the event record, do nothing.
00165   if(ph_hepevt_.nhep == (int) m_particle_list.size())
00166     return;
00167 
00168   //phodmp_();
00169 
00170   int  particle_count  = m_particle_list.size();
00171   int  daughters_start = ph_hepevt_.jmohep[ph_hepevt_.nhep-1][0];
00172   int  photons         = ph_hepevt_.nhep - m_particle_list.size();
00173   bool isPhotonCreated = (photons>0);
00174   
00175   std::vector<PhotosParticle*> photon_list; // list of added photons
00176                                             // which need kinematical treatment
00177                                             // in special case
00178 
00179   // we decipher daughters_start from  last entry 
00180   // that is last daughter in  ph_hepevt_
00181   // another option of this functionality may be 
00182   // ph_hepevt_.jdahep[ ph_hepevt_.jmohep[ph_hepevt_.nhep-1][0]-1][0];
00183   // Update daughters_start if there are two mothers
00184   // NOTE: daughters_start is index for C++ arrays, while ph_hepevt_.jmohep
00185   //       contains indices for Fortran arrays.
00186   if(ph_hepevt_.jmohep[ph_hepevt_.nhep-1][1]>0)
00187     daughters_start = ph_hepevt_.jmohep[ph_hepevt_.nhep-1][1];
00188   
00189   index = particle_count;
00190 
00191   // Add extra photons
00192   for(;photons>0; photons--, index++){
00193     
00194     if(ph_hepevt_.idhep[index]!=PhotosParticle::GAMMA)
00195       Log::Fatal("PH_HEPEVT_Interface::get(): Extra particle added to the PH_HEPEVT common block in not a photon!",6);
00196     
00197     //create a new particle
00198     PhotosParticle * new_photon;
00199     new_photon = m_particle_list.at(0)->createNewParticle(ph_hepevt_.idhep[index],
00200                                                           ph_hepevt_.isthep[index],
00201                                                           ph_hepevt_.phep[index][4],
00202                                                           ph_hepevt_.phep[index][0],
00203                                                           ph_hepevt_.phep[index][1],
00204                                                           ph_hepevt_.phep[index][2],
00205                                                           ph_hepevt_.phep[index][3]);
00206     
00207     //add into the event record
00208     //get mother particle of photon
00209     PhotosParticle * mother =  m_particle_list.at(ph_hepevt_.jmohep[index][0]-1);
00210     mother->addDaughter(new_photon);
00211     
00212     //add to list of photons
00213     photon_list.push_back(new_photon);
00214   }
00215 
00216   // Before we update particles, we check for special cases
00217   // At this step, particles are yet unmodified
00218   // but photons are already in the event record
00219   bool special=false;
00220   PhotosParticle *p1 = NULL;
00221   PhotosParticle *p2 = NULL;
00222 
00223   if( isPhotonCreated )
00224   {
00225     std::vector<PhotosParticle*> daughters;
00226 
00227     // in the following we create list of   daughters,
00228     // later  we calculate bool special which is true only if all
00229     // daughters self-decay
00230     // at peresent warning for  mixed self-decay and not self decay 
00231     // daughters is not printed.
00232 
00233     for(int i=daughters_start;i<particle_count;i++)
00234     {
00235       PhotosParticle *p = m_particle_list.at(i);
00236 
00237       daughters.push_back(p);
00238     }
00239 
00240     // Check if this is a special case
00241     special = true;
00242     
00243     if(daughters.size()==0) special = false;
00244     
00245     // special = false if there is a stable particle on the list
00246     //                 or there is a particle without self-decay
00247     for(unsigned int i=0;i<daughters.size();i++)
00248     {
00249       if(daughters[i]->getStatus()==1)
00250       {
00251         special = false;
00252         break;
00253       }
00254       
00255       // NOTE: We can use 'getDaughters' here, because vertices
00256       //       of daughters are not being modified by Photos right now
00257       //       (so there will be no caching)
00258       std::vector<PhotosParticle*> daughters2 = daughters[i]->getDaughters();
00259       
00260       if(daughters2.size()!=1 || 
00261          daughters2[0]->getPdgID() != daughters[i]->getPdgID() )
00262       {
00263         special = false;
00264         break;
00265       }
00266     }
00267 
00268     if( special )
00269     {
00270       double px1=0.0, py1=0.0, pz1=0.0, e1=0.0;
00271       double px2=0.0, py2=0.0, pz2=0.0, e2=0.0;
00272 
00273       // get sum of 4-momenta of unmodified particles
00274       for(unsigned int i=0;i<daughters.size();i++)
00275       {
00276         // ignore photons
00277         if(daughters[i]->getPdgID()==22) continue;
00278 
00279         px1+=daughters[i]->getPx();
00280         py1+=daughters[i]->getPy();
00281         pz1+=daughters[i]->getPz();
00282         e1 +=daughters[i]->getE();
00283       }
00284 
00285       // get sum of 4-momenta of particles in self-decay vertices
00286       for(unsigned int i=0;i<daughters.size();i++)
00287       {
00288         // ignore photons
00289         if(daughters[i]->getPdgID()==22) continue;
00290 
00291         // since 'allDaughtersSelfDecay()' is true
00292         // each of these particles has exactly one daughter
00293         px2 += daughters[i]->getDaughters().at(0)->getPx();
00294         py2 += daughters[i]->getDaughters().at(0)->getPy();
00295         pz2 += daughters[i]->getDaughters().at(0)->getPz();
00296         e2  += daughters[i]->getDaughters().at(0)->getE();
00297       }
00298 
00299       //cout<<"ORIG: "<<px1<<" "<<py1<<" "<<pz1<<" "<<e1<<endl;
00300       //cout<<"SELF: "<<px2<<" "<<py2<<" "<<pz2<<" "<<e2<<endl;
00301 
00302       p1 = m_particle_list.at(0)->createNewParticle(0,-1,0.0,px1,py1,pz1,e1);
00303       p2 = m_particle_list.at(0)->createNewParticle(0,-2,0.0,px2,py2,pz2,e2);
00304 
00305       // Finaly, boost photons to appropriate frame
00306       for(unsigned int i=0;i<photon_list.size();i++)
00307       {
00308         PhotosParticle *boosted = photon_list[i]->createNewParticle( 22, 1,
00309                                     0.0,
00310                                     photon_list[i]->getPx(),
00311                                     photon_list[i]->getPy(),
00312                                     photon_list[i]->getPz(),
00313                                     photon_list[i]->getE()   );
00314                 
00315         boosted->boostToRestFrame(p1);
00316         boosted->boostFromRestFrame(p2);
00317         
00318         photon_list[i]->createSelfDecayVertex(boosted);
00319         
00320         delete boosted;
00321       }
00322 
00323       Log::Warning()<<"Hidden interaction, all daughters self decay."
00324           <<"Potentially over simplified solution applied."<<endl;
00325     }
00326   }
00327 
00328   //otherwise loop over particles which are already in the
00329   //event record and modify their 4 momentum
00330   //4.03.2012: Fix to prevent kinematical trap in vertex of simultaneous:
00331   //           z-collinear and non-conservation pf E,p for dauthters of grandmothers
00332   for(index=daughters_start; index < particle_count && index < (int) m_particle_list.size(); index++){
00333 
00334     PhotosParticle * particle = m_particle_list.at(index);
00335 
00336     if(ph_hepevt_.idhep[index]!=particle->getPdgID())
00337       Log::Fatal("PH_HEPEVT_Interface::get(): Something is wrong with the PH_HEPEVT common block",5);
00338 
00339     // If photons were added - for each daughter create a history entry
00340     if(isPhotonCreated && Photos::isCreateHistoryEntries)
00341     {
00342       particle->createHistoryEntry();
00343     }
00344     
00345     //check to see if this particle's 4-momentum has been modified
00346     bool   update=false;
00347 
00348     // don't update particle if difference lower than THRESHOLD * particle energy (default threshold = 10e-8)
00349     double threshold = NO_BOOST_THRESHOLD*ph_hepevt_.phep[index][3];
00350     if( fabs(ph_hepevt_.phep[index][0]-particle->getPx()) > threshold ||
00351         fabs(ph_hepevt_.phep[index][1]-particle->getPy()) > threshold ||
00352         fabs(ph_hepevt_.phep[index][2]-particle->getPz()) > threshold ||
00353         fabs(ph_hepevt_.phep[index][3]-particle->getE())  > threshold    ) update=true;
00354 
00355     if(update)
00356     {
00357 
00358       //modify this particle's momentum and it's daughters momentum
00359       //Steps 1., 2. and 3. must be executed in order.
00360 
00361       //1. boost the particles daughters into it's (old) rest frame
00362       particle->boostDaughtersToRestFrame(particle);
00363 
00364       //2. change this particles 4 momentum
00365       particle->setPx(ph_hepevt_.phep[index][0]);
00366       particle->setPy(ph_hepevt_.phep[index][1]);
00367       particle->setPz(ph_hepevt_.phep[index][2]);
00368       particle->setE(ph_hepevt_.phep[index][3]);
00369 
00370       //3. boost the particles daughters back into the lab frame
00371       particle->boostDaughtersFromRestFrame(particle);
00372 
00373       if(special && particle->getDaughters().size()>0){
00374 
00375       // Algorithm for special case:
00376       // a. get self-daughter of 'particle'
00377       PhotosParticle *particled = particle->getDaughters().at(0);
00378 
00379       // b. boost 'particled' daughters to rest frame
00380       particled->boostDaughtersToRestFrame(particled);
00381 
00382       // c. copy four momentum of 'particle' into four momentum of
00383       //    its self-daughter 'particled'
00384 
00385       particled->setPx( particle->getPx() );
00386       particled->setPy( particle->getPy() );
00387       particled->setPz( particle->getPz() );
00388       particled->setE ( particle->getE()  );
00389 
00390       // d. boost self daughter to rest-frame of <e1>
00391       //    boost self daughter from rest-frame of <e2>
00392 
00393       particled->boostToRestFrame(p1);
00394       particled->boostFromRestFrame(p2);
00395 
00396       // e. boost the 'particled' daughters back into the lab frame
00397       particled->boostDaughtersFromRestFrame(particled);
00398       }
00399 
00400     }
00401   }
00402   
00403   // cleanup
00404   if(p1) delete p1;
00405   if(p2) delete p2;
00406 }
00407 
00408 void PH_HEPEVT_Interface::prepare()
00409 {
00410         check_ME_channel();
00411 }
00412 
00413 void PH_HEPEVT_Interface::complete()
00414 {
00415 
00416 }
00417 
00418 void PH_HEPEVT_Interface::check_ME_channel()
00419 {
00420         ME_channel=0;
00421 
00422 // Check mothers:
00423 
00424         if(decay_idx==2)                              return; // Only one mother present
00425         if(ph_hepevt_.idhep[0]*ph_hepevt_.idhep[1]>0) return; // Mothers have same sign
00426 
00427         Log::Debug(900)<<"ME_channel: Mothers PDG:  "<<ph_hepevt_.idhep[0]<<" "<<ph_hepevt_.idhep[1]<<endl;
00428         if(decay_idx)
00429                 Log::Debug(900,false)<<"            Intermediate: "<<ph_hepevt_.idhep[decay_idx-1]<<endl;
00430 
00431         int              firstDaughter=3;
00432         if(decay_idx==0) firstDaughter=2; // if no intermediate particle - daughters start at idx 2
00433 
00434         // Are mothers in range +/- 1-6; +/- 11-16?
00435         int mother1 = abs(ph_hepevt_.idhep[0]);
00436         int mother2 = abs(ph_hepevt_.idhep[1]);
00437         if( mother1<1 || (mother1>6 && mother1<11) || mother1>16 ) return;
00438         if( mother2<1 || (mother2>6 && mother2<11) || mother2>16 ) return;
00439 
00440 //Check daughters
00441 
00442         // Z: check for pairs 11 -11 ; 13 -13 ; 15 -15
00443         // -------------------------------------------
00444         int firstPDG =0;
00445         int secondPDG=0;
00446         for(int i=firstDaughter; i<ph_hepevt_.nhep;i++)
00447         {
00448                 int pdg = abs(ph_hepevt_.idhep[i]);
00449                 if(pdg==11 || pdg==13 || pdg==15)
00450                 {
00451                         if(firstPDG==0) firstPDG=ph_hepevt_.idhep[i];
00452                         else
00453                         {
00454                                 secondPDG=ph_hepevt_.idhep[i];
00455                                 // Just in case two pairs are genereted - verify that we have a pair with oposite signs
00456                                 if(firstPDG*secondPDG>0) secondPDG=0;
00457                                 break;
00458                         }
00459                 }
00460         }
00461 
00462         if( ME_channel==0 && firstPDG!=0 && secondPDG!=0 &&
00463             firstPDG==-secondPDG ) ME_channel=1;
00464 
00465         // W: check for pairs 11 -12; -11 12; 13 -14; -13 14; 15 -16; -15 16
00466         // -----------------------------------------------------------------
00467         firstPDG =0;
00468         secondPDG=0;
00469         for(int i=firstDaughter; i<ph_hepevt_.nhep;i++)
00470         {
00471                 int pdg = abs(ph_hepevt_.idhep[i]);
00472                 if(pdg>=11 && pdg<=16)
00473                 {
00474                         if(firstPDG==0) firstPDG=ph_hepevt_.idhep[i];
00475                         else
00476                         {
00477                                 secondPDG=ph_hepevt_.idhep[i];
00478                                 // Just in case two pairs are genereted - verify that we have a pair with oposite signs
00479                                 if(firstPDG*secondPDG>0) secondPDG=0;
00480                                 break;
00481                         }
00482                 }
00483         }
00484 
00485         firstPDG =abs(firstPDG);
00486         secondPDG=abs(secondPDG);
00487 
00488         if(  ME_channel==0 && firstPDG!=0 && secondPDG!=0 &&
00489            ( ( firstPDG==11 && secondPDG==12 ) || (firstPDG == 12 && secondPDG == 11) ||
00490              ( firstPDG==13 && secondPDG==14 ) || (firstPDG == 14 && secondPDG == 13) ||
00491              ( firstPDG==15 && secondPDG==16 ) || (firstPDG == 16 && secondPDG == 15)
00492            )
00493           ) ME_channel=2;
00494 
00495         Log::Debug(901)<<"ME_channel: Found ME_channel: "<<ME_channel<<endl;
00496 
00497 // Check intermediate particle (if exists):
00498 
00499         // Verify that intermediate particle PDG matches ME_channel found
00500         if(ME_channel>0 && decay_idx)
00501         {
00502                 int pdg=ph_hepevt_.idhep[decay_idx-1];
00503 
00504                 if(ME_channel==1 && !(pdg==22 || pdg==23) ) ME_channel=0; //gamma/Z
00505                 if(ME_channel==2 && !(pdg==24 || pdg==-24)) ME_channel=0; //W+/W-
00506 
00507                 if(ME_channel==0)
00508                         Log::Debug(901,false)<<"            but set to 0: wrong intermediate particle: "<<pdg<<endl;
00509         }
00510 
00511 // Check flags
00512 
00513         switch(ME_channel)
00514         {
00515                 case  0: break; // Ok - no channel found
00516                 case  1: if(!Photos::meCorrectionWtForZ) ME_channel=0; break;
00517                 case  2: if(!Photos::meCorrectionWtForW) ME_channel=0; break;
00518                 default: Log::Error()<<"Unimplemented ME channel: "<<ME_channel<<endl; break;
00519         }
00520         Log::Debug(902)<<"ME_channel: Finally, after flag check, ME_channel is: "<<ME_channel<<endl;
00521 }
00522 
00523 // Call from fortran: 'CALL ME_CHANNEL(X)'
00524 extern "C" void me_channel_(int *x)
00525 {
00526         *x=PH_HEPEVT_Interface::ME_channel;
00527 }
00528 // Call from fortran: 'CALL ME_SCALAR(X)'
00529 // transmits flag if NLO correction for scalar is on/off
00530 extern "C" void me_scalar_(int *x)
00531 {
00532   *x=(int) Photos::meCorrectionWtForScalar;
00533 }
00534 
00535 } // namespace Photospp
Generated on Sun Oct 20 20:23:56 2013 for C++InterfacetoPHOTOS by  doxygen 1.6.3