CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/GeneratorInterface/ExternalDecays/src/TauolaInterface.cc

Go to the documentation of this file.
00001 
00002 #include <iostream>
00003 
00004 #include "GeneratorInterface/Pythia6Interface/interface/Pythia6Service.h"
00005 
00006 #include "GeneratorInterface/ExternalDecays/interface/TauolaInterface.h"
00007 #include "GeneratorInterface/ExternalDecays/interface/TauolaWrapper.h"
00008 
00009 #include "FWCore/ServiceRegistry/interface/Service.h"
00010 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00011 
00012 #include "HepMC/GenEvent.h"
00013 #include "HepMC/IO_HEPEVT.h"
00014 #include "HepMC/HEPEVT_Wrapper.h"
00015 
00016 #include "SimGeneral/HepPDTRecord/interface/ParticleDataTable.h"
00017 
00018 #include "GeneratorInterface/ExternalDecays/interface/DecayRandomEngine.h"
00019 
00020 using namespace gen;
00021 using namespace edm;
00022 using namespace std;
00023 
00024 extern "C" {
00025 
00026   void ranmar_( float *rvec, int *lenv )
00027   {
00028 
00029       for(int i = 0; i < *lenv; i++)
00030          *rvec++ = decayRandomEngine->flat();
00031 
00032       return;
00033 
00034   }
00035   
00036   void rmarin_( int*, int*, int* )
00037   {
00038 
00039      return;
00040 
00041   }
00042 
00043 }
00044 
00045 //
00046 //   General Note: While there're no explicit calls or otherwise "links" to Pythia6 anywhere,
00047 //   we're using Pythia6Service here because we run pretauola rather than "core" tauola;
00048 //   pretauola is an extension on top of tauola, which is tied to Pythia6 via several routines;
00049 //   most heavily use one is PYR - we can't avoid it (other Pythia6-tied routines we avoid)
00050 //
00051 
00052 TauolaInterface::TauolaInterface( const ParameterSet& pset )
00053    : fIsInitialized(false)
00054 {
00055    fPy6Service = new Pythia6Service;
00056 
00057    fPolarization = pset.getParameter<bool>("UseTauolaPolarization") ? 1 : 0 ;
00058 
00059    // set Tauola defaults
00060    //
00061    ki_taumod_.pjak1 = -1;
00062    ki_taumod_.pjak2 = -1;
00063    ki_taumod_.mdtau = -1;
00064    
00065    // read tau decay mode switches
00066    //
00067    ParameterSet cards = pset.getParameter< ParameterSet >("InputCards");
00068    ki_taumod_.pjak1 = cards.getParameter< int >( "pjak1" );
00069    ki_taumod_.pjak2 = cards.getParameter< int >( "pjak2" );
00070    ki_taumod_.mdtau = cards.getParameter< int >( "mdtau" );
00071    
00072 } 
00073 
00074 TauolaInterface::~TauolaInterface()
00075 {
00076    delete fPy6Service;
00077 }
00078 
00079 void TauolaInterface::init( const edm::EventSetup& es )
00080 {
00081    
00082    if ( fIsInitialized ) return; // do init only once
00083    
00084    if ( ki_taumod_.mdtau <= -1 ) // actually, need to throw exception !
00085       return ;
00086    
00087    fPDGs.push_back( 15 ) ;
00088    es.getData( fPDGTable ) ;
00089 
00090         cout << "----------------------------------------------" << endl;
00091         cout << "Initializing Tauola" << endl;
00092         if ( fPolarization == 0 )
00093         {
00094            cout << "Tauola: Polarization disabled" << endl;
00095         } 
00096         else if ( fPolarization == 1 )
00097         {
00098            cout << "Tauola: Polarization enabled" << endl;
00099         }
00100 
00101 // FIXME !!!
00102 // This is a temporary hack - we're re-using master generator's seed to init RANMAR
00103 // FIXME !!!
00104 //   This is now off because ranmar has been overriden (see code above) to use pyr_(...)
00105 //   - this way we're using guaranteed initialized rndm generator... BUT !!! in the long
00106 //   run we may want a separate random stream for tauola...
00107 
00108 //   Service<RandomNumberGenerator> rng;
00109 //   int seed = rng->mySeed() ;
00110 //   int ntot=0, ntot2=0;
00111 //   rmarin_( &seed, &ntot, &ntot2 );
00112 
00113    int mode = -2;
00114    taurep_( &mode ) ;
00115    mode = -1;
00116    // tauola_( &mode, &fPolarization );
00117    // tauola_srs_( &mode, &fPolarization );
00118    //
00119    // We're using the call(...) method here because it'll make sure that Py6 
00120    // is initialized, and that's done only once, and will grab exatly that instance
00121    //
00122    fPy6Service->call( tauola_srs_, &mode, &fPolarization ); 
00123    
00124    fIsInitialized = true;
00125    
00126    return;
00127 }
00128 
00129 HepMC::GenEvent* TauolaInterface::decay( HepMC::GenEvent* evt )
00130 {
00131    
00132    // event record convertor
00133    //
00134    HepMC::IO_HEPEVT conv;
00135    
00136    if ( !fIsInitialized ) return conv.read_next_event();
00137    
00138    // We are using random numbers, we are fetched through Pythia6Service
00139    // (through ranmar_ below) -> so grab the instance during decay()
00140 
00141    Pythia6Service::InstanceWrapper pythia6InstanceGuard( fPy6Service );
00142 
00143    // fill up HEPEVT common block
00144    //
00145    // IDEALLY, this should be the way to go
00146    // BUT !!! this utility fills it up in the "reshuffled" order,
00147    // and later on Tauola chocks on it 
00148    //
00149    // Needs to be sorted out, eith in HepMC, or in Tauola, or both !!!
00150    // 
00151    // At present, this thing blindly relies on the assumption that
00152    // HEPEVT is always there - which wont be the case with Py8 or Hwg++
00153    //
00154    //HepMC::IO_HEPEVT conv;
00155    //conv.write_event( evt ) ;
00156    
00157    int numPartBeforeTauola = HepMC::HEPEVT_Wrapper::number_entries();
00158    // HepMC::HEPEVT_Wrapper::print_hepevt();
00159    
00160    int mode = 0;
00161    // tauola_( &mode, &fPolarization );
00162    fPy6Service->call( tauola_srs_, &mode, &fPolarization );
00163    
00164    int numPartAfterTauola = HepMC::HEPEVT_Wrapper::number_entries();
00165    // HepMC::HEPEVT_Wrapper::print_hepevt();
00166    
00167    // before we do the conversion, we need to deal with decay vertexes
00168    // since Tauola knows nothing about lifetimes, all decay vertexes are set to 0. 
00169    // nees to set them properly, knowing lifetime !
00170    // here we do it on HEPEVT record, also for consistency, although it's probably
00171    // even easier to deal with HepMC::GenEvent record  
00172    
00173    // find 1st "non-doc" tau
00174    //
00175    bool foundTau = false;
00176    for ( int ip=1; ip<=numPartAfterTauola; ip++ )
00177    {
00178       if ( std::abs( HepMC::HEPEVT_Wrapper::id( ip ) ) == 15
00179            && HepMC::HEPEVT_Wrapper::status( ip ) != 3 )
00180       {
00181          foundTau = true;
00182          break;
00183       }
00184    }
00185    
00186    if ( !foundTau )
00187    {
00188       // no tau found
00189       // just give up here
00190       //
00191       return conv.read_next_event();
00192    }
00193    
00194    std::vector<int> PrntIndx;
00195    
00196    for ( int ip=numPartAfterTauola; ip>numPartBeforeTauola; ip-- ) // Fortran indexing !
00197    {
00198       
00199       // first of all, find out how many generations in decay chain
00200       //
00201       PrntIndx.clear();
00202       int Prnt = HepMC::HEPEVT_Wrapper::first_parent(ip);
00203       ip -= (HepMC::HEPEVT_Wrapper::number_children(Prnt)-1); // such that we don't go the same part again
00204       PrntIndx.push_back( Prnt );
00205       while ( abs( HepMC::HEPEVT_Wrapper::id(Prnt) ) != 15 ) // shortcut; need to loop over fPDGs...
00206       {
00207          int Prnt1 = HepMC::HEPEVT_Wrapper::first_parent( Prnt );
00208          Prnt = Prnt1;
00209          // such that the tau always appear at the start of the list
00210          PrntIndx.insert( PrntIndx.begin(), Prnt );
00211          ip -= HepMC::HEPEVT_Wrapper::number_children(Prnt); // such that we don't go the same part again
00212       }
00213       for ( size_t iprt=0; iprt<PrntIndx.size(); iprt++ )
00214       {  
00215           int Indx = PrntIndx[iprt];
00216           int PartID = HepMC::HEPEVT_Wrapper::id( Indx );
00217           const HepPDT::ParticleData* 
00218              PData = fPDGTable->particle(HepPDT::ParticleID(abs(PartID))) ;
00219          //
00220          // prob = exp(-t/lifetime) ==> t = -lifetime * log(prob)
00221          //
00222          float prob = 0.;
00223          int length=1;
00224          ranmar_(&prob,&length);
00225          double lifetime = PData->lifetime().value();
00226          //
00227          // in case of Py6, this would be copied into V(5,i)
00228          // for HEPEVT, need to check...
00229          //
00230          double ct = -lifetime * std::log(prob);
00231          //
00232          double ee = HepMC::HEPEVT_Wrapper::e( Indx );
00233          double px = HepMC::HEPEVT_Wrapper::px( Indx );
00234          double py = HepMC::HEPEVT_Wrapper::py( Indx );
00235          double pz = HepMC::HEPEVT_Wrapper::pz( Indx );
00236          // double pp = std::sqrt( px*px + py*py + pz*pz );
00237          double mass = HepMC::HEPEVT_Wrapper::m( Indx );
00238          //
00239          // this is in py6 terms:
00240          //  VDCY(J)=V(IP,J)+V(IP,5)*P(IP,J)/P(IP,5)
00241          //
00242          double VxDec = HepMC::HEPEVT_Wrapper::x( Indx );
00243          VxDec += ct * (px/mass);
00244          double VyDec = HepMC::HEPEVT_Wrapper::y( Indx );
00245          VyDec += ct * (py/mass);
00246          double VzDec = HepMC::HEPEVT_Wrapper::z( Indx );
00247          VzDec += ct * (pz/mass);
00248          double VtDec = HepMC::HEPEVT_Wrapper::t( Indx );
00249          VtDec += ct * (ee/mass);
00250          for ( int idau=HepMC::HEPEVT_Wrapper::first_child( Indx );
00251                    idau<=HepMC::HEPEVT_Wrapper::last_child( Indx ); idau++ )
00252          {
00253             HepMC::HEPEVT_Wrapper::set_position( idau, VxDec, VyDec, VzDec, VtDec );
00254          }
00255       }
00256    }
00257    
00258    return conv.read_next_event();
00259       
00260 }
00261 
00262 void TauolaInterface::statistics()
00263 {
00264    int mode = 1;
00265    // tauola_( &mode, &fPolarization ) ;
00266    // tauola_srs_( &mode, &fPolarization ) ;
00267    fPy6Service->call( tauola_srs_, &mode, &fPolarization );
00268    return;
00269 }
00270 
00271 
00272 /* this is the code for the new Tauola++ 
00273 
00274 #include <iostream>
00275 
00276 #include "GeneratorInterface/ExternalDecays/interface/TauolaInterface.h"
00277 
00278 #include "Tauola.h"
00279 #include "TauolaHepMCEvent.h"
00280 #include "Log.h"
00281 
00282 #include "FWCore/ServiceRegistry/interface/Service.h"
00283 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00284 
00285 #include "HepMC/GenEvent.h"
00286 #include "HepMC/IO_HEPEVT.h"
00287 #include "HepMC/HEPEVT_Wrapper.h"
00288 
00289 #include "SimGeneral/HepPDTRecord/interface/ParticleDataTable.h"
00290 
00291 using namespace gen;
00292 using namespace edm;
00293 using namespace std;
00294 
00295 CLHEP::HepRandomEngine* tauolaRandomEngine;
00296 
00297 extern "C" {
00298 
00299   void ranmar_( float *rvec, int *lenv )
00300   {
00301 
00302       for(int i = 0; i < *lenv; i++)
00303          *rvec++ = tauolaRandomEngine->flat();
00304 
00305       return;
00306 
00307   }
00308   
00309   void rmarin_( int*, int*, int* )
00310   {
00311 
00312      return;
00313 
00314   }
00315 
00316 }
00317 
00318 TauolaInterface::TauolaInterface( const ParameterSet& pset )
00319    : fIsInitialized(false)
00320 {
00321 
00322    Tauola::setDecayingParticle(15);
00323    Tauola::setRadiation(false);
00324 
00325    // polarization switch 
00326    //
00327    // fPolarization = pset.getParameter<bool>("UseTauolaPolarization") ? 1 : 0 ;
00328    fPolarization = pset.getParameter<bool>("UseTauolaPolarization");
00329    
00330    // read tau decay mode switches
00331    //
00332    ParameterSet cards = pset.getParameter< ParameterSet >("InputCards");
00333    Tauola::setSameParticleDecayMode( cards.getParameter< int >( "pjak1" ) ) ;
00334    Tauola::setOppositeParticleDecayMode( cards.getParameter< int >( "pjak2" ) ) ;
00335 
00336    Tauola::setTauLifetime(0.0);
00337    Tauola::spin_correlation.setAll(fPolarization);
00338 
00339    // some more options, copied over from an example 
00340    // - maybe will use later...
00341    //
00342    //Tauola::setEtaK0sPi(0,0,0); // switches to decay eta K0_S and pi0 1/0 on/off. 
00343    //
00344 
00345 } 
00346 
00347 TauolaInterface::~TauolaInterface()
00348 {
00349 }
00350 
00351 void TauolaInterface::init( const edm::EventSetup& es )
00352 {
00353    
00354    if ( fIsInitialized ) return; // do init only once
00355       
00356    fPDGs.push_back( Tauola::getDecayingParticle() );
00357       
00358    es.getData( fPDGTable ) ;
00359 
00360    Tauola::initialise();
00361    Log::LogWarning(false);
00362    
00363    fIsInitialized = true;
00364    
00365    return;
00366 }
00367 
00368 HepMC::GenEvent* TauolaInterface::decay( HepMC::GenEvent* evt )
00369 {
00370       
00371    if ( !fIsInitialized ) return evt;
00372    
00373    int NPartBefore = evt->particles_size();
00374    int NVtxBefore  = evt->vertices_size();
00375    
00376    // what do we do if Hep::GenEvent size is larger than 10K ???
00377    // Tauola (& Photos, BTW) can only handle up to 10K via HEPEVT,
00378    // and in case of CMS, it's only up to 4K !!!
00379    //
00380    // if ( NPartBefore > 10000 ) return evt;
00381    //
00382    
00383     //construct tmp TAUOLA event
00384     //
00385     TauolaHepMCEvent * t_event = new TauolaHepMCEvent(evt);
00386    
00387     // another option: if one lets Pythia or another master gen to decay taus, 
00388     //                 we have to undecay them first
00389     // t_event->undecayTaus();
00390     
00391     // run Tauola on the tmp event - HepMC::GenEvernt will be MODIFIED !!!
00392     //
00393     t_event->decayTaus();
00394     
00395     // delet tmp Tauola event
00396     //
00397     delete t_event; 
00398     
00399     // fix barcodes of the newly added particles
00400     //
00401     for(HepMC::GenEvent::particle_const_iterator it = evt->particles_begin(); 
00402         it != evt->particles_end(); ++it ) 
00403     {
00404        //HepMC::GenParticle* GenPrt = (*it);
00405        if ( (*it)->barcode() > 10000 )
00406        {
00407           int NewBarcode = ((*it)->barcode()-10000) + NPartBefore;
00408           (*it)->suggest_barcode( NewBarcode ); 
00409        }
00410     }
00411     
00412 
00413     // do we also need to apply the lifetime and vtx position shift ??? 
00414     // (see TauolaInterface, for example)
00415     //
00416     for ( int iv=NVtxBefore+1; iv<=evt->vertices_size(); iv++ )
00417     {
00418        HepMC::GenVertex* GenVtx = evt->barcode_to_vertex(-iv);
00419        HepMC::GenParticle* GenPart = *(GenVtx->particles_in_const_begin());
00420        HepMC::FourVector PMom = GenPart->momentum();
00421        double mass = GenPart->generated_mass();
00422        const HepPDT::ParticleData* 
00423              PData = fPDGTable->particle(HepPDT::ParticleID(abs(GenPart->pdg_id()))) ;
00424        double lifetime = PData->lifetime().value();
00425        float prob = 0.;
00426        int length=1;
00427        ranmar_(&prob,&length);
00428        double ct = -lifetime * std::log(prob);
00429        double VxDec = GenVtx->position().x();
00430        VxDec += ct * (PMom.px()/mass);
00431        double VyDec = GenVtx->position().y();
00432        VyDec += ct * (PMom.py()/mass);
00433        double VzDec = GenVtx->position().z();
00434        VzDec += ct * (PMom.pz()/mass);
00435        double VtDec = GenVtx->position().t();
00436        VtDec += ct * (PMom.e()/mass);
00437        GenVtx->set_position( HepMC::FourVector(VxDec,VyDec,VzDec,VtDec) );       
00438     }
00439     
00440     return evt;
00441       
00442 }
00443 
00444 void TauolaInterface::statistics()
00445 {
00446    return;
00447 }
00448 
00449 
00450 */