CMS 3D CMS Logo

Pythia6Hadronizer.cc
Go to the documentation of this file.
1 
2 // -*- C++ -*-
3 
4 #include "Pythia6Hadronizer.h"
5 
6 #include "HepMC/GenEvent.h"
7 #include "HepMC/PdfInfo.h"
8 #include "HepMC/PythiaWrapper6_4.h"
9 #include "HepMC/HEPEVT_Wrapper.h"
10 #include "HepMC/IO_HEPEVT.h"
11 
14 
17 
19 
21 
23 
24 
25 HepMC::IO_HEPEVT conv;
26 
27 #include "HepPID/ParticleIDTranslations.hh"
28 
29 // NOTE: here a number of Pythia6 routines are declared,
30 // plus some functionalities to pass around Pythia6 params
31 //
34 
35 #include <iomanip>
36 
37 namespace gen
38 {
39 
40 extern "C" {
41 
42  //
43  // these two are NOT part of Pythi6 core code but are "custom" add-ons
44  // we keep them interfaced here, rather than in GenExtensions, because
45  // they tweak not at the ME level, but a step further, at the framgmentation
46  //
47  // stop-hadrons
48  //
49  void pystrhad_(); // init stop-hadrons (id's, names, charges...)
50  void pystfr_(int&); // tweaks fragmentation, fragments the string near to a stop,
51  // to form stop-hadron by producing a new q-qbar pair
52  // gluino/r-hadrons
53  void pyglrhad_();
54  void pyglfr_(); // tweaks fragmentation, fragment the string near to a gluino,
55  // to form gluino-hadron, either by producing a new g-g pair,
56  // or two new q-qbar ones
57 
58 
59 } // extern "C"
60 
61 class Pythia6ServiceWithCallback : public Pythia6Service {
62  public:
64 
65  private:
66  void upInit() override
68 
69  void upEvnt() override
70  {
74  }
75 
76  bool upVeto() override
77  {
79  return false;
80 
82  return true;
83 
84  bool retValue = Pythia6Hadronizer::getJetMatching()->match( nullptr, nullptr );
85  // below is old code and a note of it
86  // NOTE: I'm passing NULL pointers, instead of HepMC::GenEvent, etc.
87  //retValur = Pythia6Hadronizer::getJetMatching()->match(0, 0, true);
88  return retValue;
89 
90 
91  }
92 };
93 
94 static struct {
95  int n, npad, k[5][pyjets_maxn];
96  double p[5][pyjets_maxn], v[5][pyjets_maxn];
97 } pyjets_local;
98 
100 
103 
105  : BaseHadronizer(ps),
106  fPy6Service( new Pythia6ServiceWithCallback(ps) ), // this will store py6 params for further settings
107  fInitialState(PP),
108  fCOMEnergy(ps.getParameter<double>("comEnergy")),
109  fHepMCVerbosity(ps.getUntrackedParameter<bool>("pythiaHepMCVerbosity",false)),
110  fMaxEventsToPrint(ps.getUntrackedParameter<int>("maxEventsToPrint", 0)),
111  fPythiaListVerbosity(ps.getUntrackedParameter<int>("pythiaPylistVerbosity", 0)),
112  fDisplayPythiaBanner(ps.getUntrackedParameter<bool>("displayPythiaBanner",false)),
113  fDisplayPythiaCards(ps.getUntrackedParameter<bool>("displayPythiaCards",false))
114 {
115 
116 
117  // J.Y.: the following 3 parameters are hacked "for a reason"
118  //
119  if ( ps.exists( "PPbarInitialState" ) )
120  {
121  if ( fInitialState == PP )
122  {
124  edm::LogInfo("GeneratorInterface|Pythia6Interface")
125  << "Pythia6 will be initialized for PROTON-ANTIPROTON INITIAL STATE. "
126  << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
127  std::cout << "Pythia6 will be initialized for PROTON-ANTIPROTON INITIAL STATE." << std::endl;
128  std::cout << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
129  }
130  else
131  {
132  // probably need to throw on attempt to override ?
133  }
134  }
135  else if ( ps.exists( "ElectronPositronInitialState" ) )
136  {
137  if ( fInitialState == PP )
138  {
140  edm::LogInfo("GeneratorInterface|Pythia6Interface")
141  << "Pythia6 will be initialized for ELECTRON-POSITRON INITIAL STATE. "
142  << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
143  std::cout << "Pythia6 will be initialized for ELECTRON-POSITRON INITIAL STATE." << std::endl;
144  std::cout << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
145  }
146  else
147  {
148  // probably need to throw on attempt to override ?
149  }
150  }
151  else if ( ps.exists( "ElectronProtonInitialState" ) )
152  {
153  if ( fInitialState == PP )
154  {
156  fBeam1PZ = (ps.getParameter<edm::ParameterSet>("ElectronProtonInitialState")).getParameter<double>("electronMomentum");
157  fBeam2PZ = (ps.getParameter<edm::ParameterSet>("ElectronProtonInitialState")).getParameter<double>("protonMomentum");
158  edm::LogInfo("GeneratorInterface|Pythia6Interface")
159  << "Pythia6 will be initialized for ELECTRON-PROTON INITIAL STATE. "
160  << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
161  std::cout << "Pythia6 will be initialized for ELECTRON-PROTON INITIAL STATE." << std::endl;
162  std::cout << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
163  }
164  else
165  {
166  // probably need to throw on attempt to override ?
167  }
168  }
169  else if ( ps.exists( "PositronProtonInitialState" ) )
170  {
171  if ( fInitialState == PP )
172  {
174  fBeam1PZ = (ps.getParameter<edm::ParameterSet>("ElectronProtonInitialState")).getParameter<double>("positronMomentum");
175  fBeam2PZ = (ps.getParameter<edm::ParameterSet>("ElectronProtonInitialState")).getParameter<double>("protonMomentum");
176  edm::LogInfo("GeneratorInterface|Pythia6Interface")
177  << "Pythia6 will be initialized for POSITRON-PROTON INITIAL STATE. "
178  << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
179  std::cout << "Pythia6 will be initialized for POSITRON-PROTON INITIAL STATE." << std::endl;
180  std::cout << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
181  }
182  else
183  {
184  // throw on unknown initial state !
185  throw edm::Exception(edm::errors::Configuration,"Pythia6Interface")
186  <<" UNKNOWN INITIAL STATE. \n The allowed initial states are: PP, PPbar, ElectronPositron, ElectronProton, and PositronProton \n";
187  }
188  }
189 
190 
191  // J.Y.: the following 4 params are "hacked", in the sense
192  // that they're tracked but get in optionally;
193  // this will be fixed once we update all applications
194  //
195 
196  fStopHadronsEnabled = false;
197  if ( ps.exists( "stopHadrons" ) )
198  fStopHadronsEnabled = ps.getParameter<bool>("stopHadrons") ;
199 
200  fGluinoHadronsEnabled = false;
201  if ( ps.exists( "gluinoHadrons" ) )
202  fGluinoHadronsEnabled = ps.getParameter<bool>("gluinoHadrons");
203 
204  fImposeProperTime = false;
205  if ( ps.exists( "imposeProperTime" ) )
206  {
207  fImposeProperTime = ps.getParameter<bool>("imposeProperTime");
208  }
209 
210  fConvertToPDG = false;
211  if ( ps.exists( "doPDGConvert" ) )
212  fConvertToPDG = ps.getParameter<bool>("doPDGConvert");
213 
214  if ( ps.exists("jetMatching") )
215  {
216  edm::ParameterSet jmParams =
218  "jetMatching");
219 
220  fJetMatching = JetMatching::create(jmParams).release();
221  }
222 
223  // first of all, silence Pythia6 banner printout, unless display requested
224  //
225  if ( !fDisplayPythiaBanner )
226  {
227  if (!call_pygive("MSTU(12)=12345"))
228  {
229  throw edm::Exception(edm::errors::Configuration,"PythiaError")
230  <<" Pythia did not accept MSTU(12)=12345";
231  }
232  }
233 
234 // silence printouts from PYGIVE, unless display requested
235 //
236  if ( ! fDisplayPythiaCards )
237  {
238  if (!call_pygive("MSTU(13)=0"))
239  {
240  throw edm::Exception(edm::errors::Configuration,"PythiaError")
241  <<" Pythia did not accept MSTU(13)=0";
242  }
243  }
244 
245  // tmp stuff to deal with EvtGen corrupting pyjets
246  // NPartsBeforeDecays = 0;
247  flushTmpStorage();
248 
249 }
250 
252 {
253  if ( fPy6Service != nullptr ) delete fPy6Service;
254  if ( fJetMatching != nullptr ) delete fJetMatching;
255 }
256 
257 void Pythia6Hadronizer::doSetRandomEngine(CLHEP::HepRandomEngine* v)
258 {
260 }
261 
263 {
264 
265  pyjets_local.n = 0 ;
266  pyjets_local.npad = 0 ;
267  for ( int ip=0; ip<pyjets_maxn; ip++ )
268  {
269  for ( int i=0; i<5; i++ )
270  {
271  pyjets_local.k[i][ip] = 0;
272  pyjets_local.p[i][ip] = 0.;
273  pyjets_local.v[i][ip] = 0.;
274  }
275  }
276  return;
277 
278 }
279 
281 {
282 
283  pyjets_local.n = pyjets.n;
284  pyjets_local.npad = pyjets.npad;
285  for ( int ip=0; ip<pyjets_maxn; ip++ )
286  {
287  for ( int i=0; i<5; i++ )
288  {
289  pyjets_local.k[i][ip] = pyjets.k[i][ip];
290  pyjets_local.p[i][ip] = pyjets.p[i][ip];
291  pyjets_local.v[i][ip] = pyjets.v[i][ip];
292  }
293  }
294 
295  return ;
296 
297 }
298 
300 {
301 
302  bool lhe = lheEvent() != nullptr;
303 
304  HepMC::PdfInfo pdf;
305 
306  // if we are in hadronizer mode, we can pass on information from
307  // the LHE input
308  if (lhe)
309  {
310  lheEvent()->fillEventInfo( event().get() );
311  lheEvent()->fillPdfInfo( &pdf );
312  }
313  else
314  {
315  // filling in factorization "Q scale" now! pthat moved to binningValues()
316  //
317 
318  if ( event()->signal_process_id() <= 0) event()->set_signal_process_id( pypars.msti[0] );
319  if ( event()->event_scale() <=0 ) event()->set_event_scale( pypars.pari[22] );
320  if ( event()->alphaQED() <= 0) event()->set_alphaQED( pyint1.vint[56] );
321  if ( event()->alphaQCD() <= 0) event()->set_alphaQCD( pyint1.vint[57] );
322 
323  // get pdf info directly from Pythia6 and set it up into HepMC::GenEvent
324  // S. Mrenna: Prefer vint block
325  //
326  if ( pdf.id1() <= 0) pdf.set_id1( pyint1.mint[14] == 21 ? 0 : pyint1.mint[14] );
327  if ( pdf.id2() <= 0) pdf.set_id2( pyint1.mint[15] == 21 ? 0 : pyint1.mint[15] );
328  if ( pdf.x1() <= 0) pdf.set_x1( pyint1.vint[40] );
329  if ( pdf.x2() <= 0) pdf.set_x2( pyint1.vint[41] );
330  if ( pdf.pdf1() <= 0) pdf.set_pdf1( pyint1.vint[38] / pyint1.vint[40] );
331  if ( pdf.pdf2() <= 0) pdf.set_pdf2( pyint1.vint[39] / pyint1.vint[41] );
332  if ( pdf.scalePDF() <= 0) pdf.set_scalePDF( pyint1.vint[50] );
333  }
334 
335 /* 9/9/2010 - JVY: This is the old piece of code - I can't remember why we implemented it this way.
336  However, it's causing problems with pdf1 & pdf2 when processing LHE samples,
337  specifically, because both are set to -1, it tries to fill with Py6 numbers that
338  are NOT valid/right at this point !
339  In general, for LHE/ME event processing we should implement the correct calculation
340  of the pdf's, rather than using py6 ones.
341 
342  // filling in factorization "Q scale" now! pthat moved to binningValues()
343 
344  if (!lhe || event()->signal_process_id() < 0) event()->set_signal_process_id( pypars.msti[0] );
345  if (!lhe || event()->event_scale() < 0) event()->set_event_scale( pypars.pari[22] );
346  if (!lhe || event()->alphaQED() < 0) event()->set_alphaQED( pyint1.vint[56] );
347  if (!lhe || event()->alphaQCD() < 0) event()->set_alphaQCD( pyint1.vint[57] );
348 
349  // get pdf info directly from Pythia6 and set it up into HepMC::GenEvent
350  // S. Mrenna: Prefer vint block
351  //
352  if (!lhe || pdf.id1() < 0) pdf.set_id1( pyint1.mint[14] == 21 ? 0 : pyint1.mint[14] );
353  if (!lhe || pdf.id2() < 0) pdf.set_id2( pyint1.mint[15] == 21 ? 0 : pyint1.mint[15] );
354  if (!lhe || pdf.x1() < 0) pdf.set_x1( pyint1.vint[40] );
355  if (!lhe || pdf.x2() < 0) pdf.set_x2( pyint1.vint[41] );
356  if (!lhe || pdf.pdf1() < 0) pdf.set_pdf1( pyint1.vint[38] / pyint1.vint[40] );
357  if (!lhe || pdf.pdf2() < 0) pdf.set_pdf2( pyint1.vint[39] / pyint1.vint[41] );
358  if (!lhe || pdf.scalePDF() < 0) pdf.set_scalePDF( pyint1.vint[50] );
359 */
360 
361  event()->set_pdf_info( pdf ) ;
362 
363  HepMC::GenCrossSection xsec;
364  double cs = pypars.pari[0]; // cross section in mb
365  cs *= 1.0e9; // translate to pb
366  double cserr = cs / sqrt(pypars.msti[4]);
367  xsec.set_cross_section(cs, cserr);
368  event()->set_cross_section(xsec);
369 
370  // this is "standard" Py6 event weight (corresponds to PYINT1/VINT(97)
371  //
372  if (lhe && std::abs(lheRunInfo()->getHEPRUP()->IDWTUP) == 4)
373  // translate mb to pb (CMS/Gen "convention" as of May 2009)
374  event()->weights().push_back( pyint1.vint[96] * 1.0e9 );
375  else
376  event()->weights().push_back( pyint1.vint[96] );
377  //
378  // this is event weight as 1./VINT(99) (PYINT1/VINT(99) is returned by the PYEVWT)
379  //
380  event()->weights().push_back( 1./(pyint1.vint[98]) );
381 
382  // now create the GenEventInfo product from the GenEvent and fill
383  // the missing pieces
384 
385  eventInfo().reset( new GenEventInfoProduct( event().get() ) );
386 
387  // in Pythia6 pthat is used to subdivide samples into different bins
388  // in LHE mode the binning is done by the external ME generator
389  // which is likely not pthat, so only filling it for Py6 internal mode
390  if (!lhe)
391  {
392  eventInfo()->setBinningValues( std::vector<double>(1, pypars.pari[16]) );
393  }
394 
395  // here we treat long-lived particles
396  //
397  if ( fImposeProperTime || pydat1.mstj[21]==3 || pydat1.mstj[21]==4 ) imposeProperTime();
398 
399  // convert particle IDs Py6->PDG, if requested
400  if ( fConvertToPDG ) {
401  for ( HepMC::GenEvent::particle_iterator part = event()->particles_begin();
402  part != event()->particles_end(); ++part) {
403  (*part)->set_pdg_id(HepPID::translatePythiatoPDT((*part)->pdg_id()));
404  }
405  }
406 
407  // service printouts, if requested
408  //
409  if (fMaxEventsToPrint > 0)
410  {
413  if (fHepMCVerbosity)
414  {
415  std::cout << "Event process = " << pypars.msti[0] << std::endl
416  << "----------------------" << std::endl;
417  event()->print();
418  }
419  }
420 
421  // dump of all settings after all initializations
422  if ( fDisplayPythiaCards ) {
423  fDisplayPythiaCards = false;
424  call_pylist(12);
425  call_pylist(13);
426  std::cout << "\n PYPARS \n" << std::endl;
427  std::cout << std::setw(5) << std::fixed << "I"
428  << std::setw(10) << std::fixed << "MSTP(I)"
429  << std::setw(16) << std::fixed << "PARP(I)"
430  << std::setw(10) << std::fixed << "MSTI(I)"
431  << std::setw(16) << std::fixed << "PARI(I)" << std::endl;
432  for ( unsigned int ind=0; ind < 200; ind++ ) {
433  std::cout << std::setw(5) << std::fixed << ind+1
434  << std::setw(10) << std::fixed << pypars.mstp[ind]
435  << std::setw(16) << std::fixed << pypars.parp[ind]
436  << std::setw(10) << std::fixed << pypars.msti[ind]
437  << std::setw(16) << std::fixed << pypars.pari[ind] << std::endl;
438  }
439  }
440 
441  return;
442 }
443 
445 {
446  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
447 
449 
450  // generate event with Pythia6
451  //
452 
454  {
455  // call_pygive("MSTJ(1)=-1");
456  call_pygive("MSTJ(14)=-1");
457  }
458 
459  call_pyevnt();
460 
462  {
463  // call_pygive("MSTJ(1)=1");
464  call_pygive("MSTJ(14)=1");
465  int ierr=0;
466  if ( fStopHadronsEnabled )
467  {
468  pystfr_(ierr);
469  if ( ierr != 0 ) // skip failed events
470  {
471  event().reset();
472  return false;
473  }
474  }
476  }
477 
478  if ( pyint1.mint[50] != 0 ) // skip event if py6 considers it bad
479  {
480  event().reset();
481  return false;
482  }
483 
484  call_pyhepc(1);
485  event().reset( conv.read_next_event() );
486 
487  // this is to deal with post-gen tools & residualDecay() that may reuse PYJETS
488  //
489  flushTmpStorage();
490  fillTmpStorage();
491 
492  return true;
493 }
494 
496 {
497  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
498 
501  if ( fJetMatching )
502  {
505  }
506 
507  // generate event with Pythia6
508  //
510  {
511  call_pygive("MSTJ(1)=-1");
512  call_pygive("MSTJ(14)=-1");
513  }
514 
515  call_pyevnt();
516 
517  if ( FortranCallback::getInstance()->getIterationsPerEvent() > 1 ||
518  hepeup_.nup <= 0 || pypars.msti[0] == 1 )
519  {
520  // update LHE matching statistics
522 
523  event().reset();
524  return false;
525  }
526 
527  // update LHE matching statistics
528  //
530 
532  {
533  call_pygive("MSTJ(1)=1");
534  call_pygive("MSTJ(14)=1");
535  int ierr = 0;
536  if ( fStopHadronsEnabled )
537  {
538  pystfr_(ierr);
539  if ( ierr != 0 ) // skip failed events
540  {
541  event().reset();
542  return false;
543  }
544  }
545 
547  }
548 
549  if ( pyint1.mint[50] != 0 ) // skip event if py6 considers it bad
550  {
551  event().reset();
552  return false;
553  }
554 
555  call_pyhepc(1);
556  event().reset( conv.read_next_event() );
557 
558  // this is to deal with post-gen tools and/or residualDecay(), that may reuse PYJETS
559  //
560  flushTmpStorage();
561  fillTmpStorage();
562 
563  return true;
564 }
565 
567 {
568  return true;
569 }
570 
572 {
573 
574  // event().get()->print();
575 
576  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
577 
578  // int nDocLines = pypars.msti[3];
579 
580  int NPartsBeforeDecays = pyjets_local.n ;
581  int NPartsAfterDecays = event().get()->particles_size();
582  int barcode = NPartsAfterDecays;
583 
584  // JVY: well, in principle, it's not a 100% fair to go up to NPartsBeforeDecays,
585  // because Photos will attach gamma's to existing vertexes, i.e. in the middle
586  // of the event rather than at the end; but this will only shift poiters down,
587  // so we'll be going again over a few "original" particle...
588  // in the alternative, we may go all the way up to the beginning of the event
589  // and re-check if anything remains to decay, that's fine even if it'll take
590  // some extra CPU...
591 
592  for ( int ipart=NPartsAfterDecays; ipart>NPartsBeforeDecays; ipart-- )
593  {
594  HepMC::GenParticle* part = event().get()->barcode_to_particle( ipart );
595  int status = part->status();
596  if ( status != 1 ) continue; // check only "stable" particles,
597  // as some undecayed may still be marked as such
598  int pdgid = part->pdg_id();
599  int py6ptr = pycomp_( pdgid );
600  if ( pydat3.mdcy[0][py6ptr-1] != 1 ) continue; // particle is not expected to decay
601  int py6id = HepPID::translatePDTtoPythia( pdgid );
602  //
603  // first, will need to zero out, then fill up PYJETS
604  // I better do it directly (by hands) rather than via py1ent
605  // - to avoid (additional) mass smearing
606  //
607  if ( part->momentum().t() <= part->generated_mass() )
608  {
609  continue ; // e==m --> 0-momentum, nothing to decay...
610  }
611  else
612  {
613  pyjets.n = 0;
614  for ( int i=0; i<5; i++ )
615  {
616  pyjets.k[i][0] = 0;
617  pyjets.p[i][0] = 0.;
618  pyjets.v[i][0] = 0.;
619  }
620  pyjets.k[0][0] = 1;
621  pyjets.k[1][0] = py6id;
622  pyjets.p[4][0] = part->generated_mass();
623  pyjets.p[3][0] = part->momentum().t();
624  pyjets.p[0][0] = part->momentum().x();
625  pyjets.p[1][0] = part->momentum().y();
626  pyjets.p[2][0] = part->momentum().z();
627  HepMC::GenVertex* prod_vtx = part->production_vertex();
628  if ( !prod_vtx ) continue; // in principle, should never happen but...
629  pyjets.v[0][0] = prod_vtx->position().x();
630  pyjets.v[1][0] = prod_vtx->position().y();
631  pyjets.v[2][0] = prod_vtx->position().z();
632  pyjets.v[3][0] = prod_vtx->position().t();
633  pyjets.v[4][0] = 0.;
634  pyjets.n = 1;
635  pyjets.npad = pyjets_local.npad;
636  }
637 
638  // now call Py6 decay routine
639  //
640  int parent = 1; // since we always pass to Py6 a single particle
641  pydecy_( parent );
642 
643  // now attach decay products to mother
644  //
645  for ( int iprt1=1; iprt1<pyjets.n; iprt1++ )
646  {
647  part->set_status( 2 );
648 
649  HepMC::GenVertex* DecVtx = new HepMC::GenVertex( HepMC::FourVector(pyjets.v[0][iprt1],
650  pyjets.v[1][iprt1],
651  pyjets.v[2][iprt1],
652  pyjets.v[3][iprt1]) );
653  DecVtx->add_particle_in( part ); // this will cleanup end_vertex if exists, replace with the new one
654  // I presume (vtx) barcode will be given automatically
655 
656  HepMC::FourVector pmom(pyjets.p[0][iprt1],pyjets.p[1][iprt1],
657  pyjets.p[2][iprt1],pyjets.p[3][iprt1] );
658 
659  int dstatus = 0;
660  if ( pyjets.k[0][iprt1] >= 1 && pyjets.k[0][iprt1] <= 10 )
661  {
662  dstatus = 1;
663  }
664  else if ( pyjets.k[0][iprt1] >= 11 && pyjets.k[0][iprt1] <= 20 )
665  {
666  dstatus = 2;
667  }
668  else if ( pyjets.k[0][iprt1] >= 21 && pyjets.k[0][iprt1] <= 30 )
669  {
670  dstatus = 3;
671  }
672  else if ( pyjets.k[0][iprt1] >= 31 && pyjets.k[0][iprt1] <= 100 )
673  {
674  dstatus = pyjets.k[0][iprt1];
675  }
676  HepMC::GenParticle* daughter = new HepMC::GenParticle(pmom,
677  HepPID::translatePythiatoPDT( pyjets.k[1][iprt1] ),
678  dstatus);
679  barcode++;
680  daughter->suggest_barcode( barcode );
681  DecVtx->add_particle_out( daughter );
682 
683  int iprt2;
684  for ( iprt2=iprt1+1; iprt2<pyjets.n; iprt2++ ) // the pointer is shifted by -1, c++ style
685  {
686  if ( pyjets.k[2][iprt2] != parent )
687  {
688  parent = pyjets.k[2][iprt2];
689  break; // another parent particle; reset & break the loop
690  }
691 
692  HepMC::FourVector pmomN(pyjets.p[0][iprt2],pyjets.p[1][iprt2],
693  pyjets.p[2][iprt2],pyjets.p[3][iprt2] );
694 
695  dstatus = 0;
696  if ( pyjets.k[0][iprt2] >= 1 && pyjets.k[0][iprt2] <= 10 )
697  {
698  dstatus = 1;
699  }
700  else if ( pyjets.k[0][iprt2] >= 11 && pyjets.k[0][iprt2] <= 20 )
701  {
702  dstatus = 2;
703  }
704  else if ( pyjets.k[0][iprt2] >= 21 && pyjets.k[0][iprt2] <= 30 )
705  {
706  dstatus = 3;
707  }
708  else if ( pyjets.k[0][iprt2] >= 31 && pyjets.k[0][iprt2] <= 100 )
709  {
710  dstatus = pyjets.k[0][iprt2];
711  }
712  HepMC::GenParticle* daughterN = new HepMC::GenParticle(pmomN,
713  HepPID::translatePythiatoPDT( pyjets.k[1][iprt2] ),
714  dstatus);
715  barcode++;
716  daughterN->suggest_barcode( barcode );
717  DecVtx->add_particle_out( daughterN );
718  }
719 
720  iprt1 = iprt2-1; // reset counter such that it doesn't go over the same child more than once
721  // don't forget to offset back into c++ counting, as it's already +1 forward
722 
723  event().get()->add_vertex( DecVtx );
724 
725  }
726 
727  }
728 
729  // now restore the very original Py6 event record
730  //
731  if ( pyjets_local.n != pyjets.n )
732  {
733  // restore pyjets to its state as it was before external decays -
734  // might have been jammed by action above or by py1ent calls in EvtGen
735  pyjets.n = pyjets_local.n;
736  pyjets.npad = pyjets_local.npad;
737  for ( int ip=0; ip<pyjets_local.n; ip++ )
738  {
739  for ( int i=0; i<5; i++ )
740  {
741  pyjets.k[i][ip] = pyjets_local.k[i][ip];
742  pyjets.p[i][ip] = pyjets_local.p[i][ip];
743  pyjets.v[i][ip] = pyjets_local.v[i][ip];
744  }
745  }
746  }
747 
748  return true;
749 }
750 
752 {
753 
754  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
755 
757  if ( key == 0 ) fPy6Service->setCSAParams();
759 
760  return true;
761 
762 }
763 
765 {
766  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
767 
768  // note: CSA mode is NOT supposed to work with external partons !!!
769 
770  // fPy6Service->setGeneralParams();
771 
773 
775 
776  if ( fStopHadronsEnabled )
777  {
778  // overwrite mstp(111), no matter what
779  call_pygive("MSTP(111)=0");
780  pystrhad_();
781  call_pygive("MWID(302)=0"); // I don't know if this is specific to processing ME/LHE only,
782  call_pygive("MDCY(302,1)=0"); // or this should also be the case for full event...
783  // anyway, this comes from experience of processing MG events
784  }
785 
786  if ( fGluinoHadronsEnabled )
787  {
788  // overwrite mstp(111), no matter what
789  call_pygive("MSTP(111)=0");
790  pyglrhad_();
791  //call_pygive("MWID(309)=0");
792  //call_pygive("MDCY(309,1)=0");
793  }
794 
795  call_pyinit("USER", "", "", 0.0);
796 
798 
799  std::vector<std::string> slha = lheRunInfo()->findHeader("slha");
800  if (!slha.empty()) {
801  edm::LogInfo("Generator|LHEInterface")
802  << "Pythia6 hadronisation found an SLHA header, "
803  << "will be passed on to Pythia." << std::endl;
806  }
807 
808  if ( fJetMatching )
809  {
811 // FIXME: the jet matching routine might not be interested in PS callback
812  call_pygive("MSTP(143)=1");
813  }
814 
815  return true;
816 }
817 
819 {
820 
821  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
822 
824 
825  if ( fStopHadronsEnabled )
826  {
827  // overwrite mstp(111), no matter what
828  call_pygive("MSTP(111)=0");
829  pystrhad_();
830  }
831 
832  if ( fGluinoHadronsEnabled )
833  {
834  // overwrite mstp(111), no matter what
835  call_pygive("MSTP(111)=0");
836  pyglrhad_();
837  }
838 
839  if ( fInitialState == PP ) // default
840  {
841  call_pyinit("CMS", "p", "p", fCOMEnergy);
842  }
843  else if ( fInitialState == PPbar )
844  {
845  call_pyinit( "CMS", "p", "pbar", fCOMEnergy);
846  }
847  else if ( fInitialState == ElectronPositron )
848  {
849  call_pyinit( "CMS", "e+", "e-", fCOMEnergy );
850  }
851  else if ( fInitialState == ElectronProton)
852  {
853  // set p(1,i) & p(2,i) for the beams in pyjets !
854  pyjets.p[0][0] = 0.;
855  pyjets.p[1][0] = 0.;
856  pyjets.p[2][0] = fBeam1PZ;
857  pyjets.p[0][1] = 0.;
858  pyjets.p[1][1] = 0.;
859  pyjets.p[2][1] = fBeam2PZ;
860  // call "3mon" frame & 0.0 win
861  call_pyinit( "3mom", "e-", "p", 0.0 );
862  }
863  else if ( fInitialState == PositronProton)
864  {
865  // set p(1,i) & p(2,i) for the beams in pyjets !
866  pyjets.p[0][0] = 0.;
867  pyjets.p[1][0] = 0.;
868  pyjets.p[2][0] = fBeam1PZ;
869  pyjets.p[0][1] = 0.;
870  pyjets.p[1][1] = 0.;
871  pyjets.p[2][1] = fBeam2PZ;
872  // call "3mon" frame & 0.0 win
873  call_pyinit( "3mom", "e+", "p", 0.0 );
874  }
875  else
876  {
877  // throw on unknown initial state !
878  throw edm::Exception(edm::errors::Configuration,"Pythia6Interface")
879  <<" UNKNOWN INITIAL STATE. \n The allowed initial states are: PP, PPbar, ElectronPositron, ElectronProton, and PositronProton \n";
880  }
881 
882 
884 
886 
887  return true;
888 }
889 
890 bool Pythia6Hadronizer::declareStableParticles( const std::vector<int>& pdg )
891 {
892 
893  for ( unsigned int i=0; i<pdg.size(); i++ )
894  {
895  int PyID = HepPID::translatePDTtoPythia( pdg[i] );
896  // int PyID = pdg[i];
897  int pyCode = pycomp_( PyID );
898  if ( pyCode > 0 )
899  {
900  std::ostringstream pyCard ;
901  pyCard << "MDCY(" << pyCode << ",1)=0";
902 /* this is a test printout...
903  std::cout << "pdg= " << pdg[i] << " " << pyCard.str() << std::endl;
904 */
905  call_pygive( pyCard.str() );
906  }
907  }
908 
909  return true;
910 }
911 
912 bool Pythia6Hadronizer::declareSpecialSettings( const std::vector<std::string>& settings )
913 {
914 
915  for ( unsigned int iss=0; iss<settings.size(); iss++ )
916  {
917  if ( settings[iss].find("QED-brem-off") == std::string::npos ) continue;
918  size_t fnd1 = settings[iss].find(":");
919  if ( fnd1 == std::string::npos ) continue;
920 
921  std::string value = settings[iss].substr (fnd1+1);
922 
923  if ( value == "all" )
924  {
925  call_pygive( "MSTJ(41)=3" );
926  }
927  else
928  {
929  int number = atoi(value.c_str());
930  int PyID = HepPID::translatePDTtoPythia( number );
931  int pyCode = pycomp_( PyID );
932  if ( pyCode > 0 )
933  {
934 
935  // first of all, check if mstj(39) is 0 or if we're trying to override user's setting
936  // if so, throw an exception and stop, because otherwise the user will get behaviour
937  // that's different from what she/he expects !
938  if ( pydat1_.mstj[38] > 0 && pydat1_.mstj[38] != pyCode )
939  {
940  throw edm::Exception(edm::errors::Configuration,"Pythia6Interface")
941  << " Fatal conflict: \n mandatory internal directive to set MSTJ(39)=" << pyCode
942  << " overrides user setting MSTJ(39)=" << pydat1_.mstj[38] << " - user will not get expected behaviour \n";
943  }
944  std::ostringstream pyCard ;
945  pyCard << "MSTJ(39)=" << pyCode ;
946  call_pygive( pyCard.str() );
947  }
948  }
949  }
950 
951  return true;
952 
953 }
954 
956 {
957 
958  // this is practically a copy/paste of the original code by J.Alcaraz,
959  // taken directly from PythiaSource
960 
961  int dumm=0;
962  HepMC::GenEvent::vertex_const_iterator vbegin = event()->vertices_begin();
963  HepMC::GenEvent::vertex_const_iterator vend = event()->vertices_end();
964  HepMC::GenEvent::vertex_const_iterator vitr = vbegin;
965  for (; vitr != vend; ++vitr )
966  {
967  HepMC::GenVertex::particle_iterator pbegin = (*vitr)->particles_begin(HepMC::children);
968  HepMC::GenVertex::particle_iterator pend = (*vitr)->particles_end(HepMC::children);
969  HepMC::GenVertex::particle_iterator pitr = pbegin;
970  for (; pitr != pend; ++pitr)
971  {
972  if ((*pitr)->end_vertex()) continue;
973  if ((*pitr)->status()!=1) continue;
974 
975  int pdgcode= abs((*pitr)->pdg_id());
976  // Do nothing if the particle is not expected to decay
977  if ( pydat3.mdcy[0][pycomp_(pdgcode)-1] !=1 ) continue;
978 
979  double ctau = pydat2.pmas[3][pycomp_(pdgcode)-1];
980  HepMC::FourVector mom = (*pitr)->momentum();
981  HepMC::FourVector vin = (*vitr)->position();
982  double x = 0.;
983  double y = 0.;
984  double z = 0.;
985  double t = 0.;
986  bool decayInRange = false;
987  while (!decayInRange)
988  {
989  double unif_rand = fPy6Service->call(pyr_, &dumm);
990  // Value of 0 is excluded, so following line is OK
991  double proper_length = - ctau * log(unif_rand);
992  double factor = proper_length/mom.m();
993  x = vin.x() + factor * mom.px();
994  y = vin.y() + factor * mom.py();
995  z = vin.z() + factor * mom.pz();
996  t = vin.t() + factor * mom.e();
997  // Decay must be happen outside a cylindrical region
998  if (pydat1.mstj[21]==4) {
999  if (std::sqrt(x*x+y*y)>pydat1.parj[72] || fabs(z)>pydat1.parj[73]) decayInRange = true;
1000  // Decay must be happen outside a given sphere
1001  }
1002  else if (pydat1.mstj[21]==3) {
1003  if (std::sqrt(x*x+y*y+z*z)>pydat1.parj[71]) decayInRange = true;
1004  }
1005  // Decay is always OK otherwise
1006  else {
1007  decayInRange = true;
1008  }
1009  }
1010 
1011  HepMC::GenVertex* vdec = new HepMC::GenVertex(HepMC::FourVector(x,y,z,t));
1012  event()->add_vertex(vdec);
1013  vdec->add_particle_in((*pitr));
1014  }
1015  }
1016 
1017  return;
1018 
1019 }
1020 
1022 {
1023 
1024  if ( !runInfo().internalXSec() )
1025  {
1026  // set xsec if not already done (e.g. from LHE cross section collector)
1027  double cs = pypars.pari[0]; // cross section in mb
1028  cs *= 1.0e9; // translate to pb (CMS/Gen "convention" as of May 2009)
1029  runInfo().setInternalXSec( cs );
1030 // FIXME: can we get the xsec statistical error somewhere?
1031  }
1032 
1033  call_pystat(1);
1034 
1035  return;
1036 
1037 }
1038 
1039 const char* Pythia6Hadronizer::classname() const
1040 {
1041  return "gen::Pythia6Hadronizer";
1042 }
1043 
1044 } // namespace gen
#define pydat1
struct gen::@661 pydat1_
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
void call(void(&fn)())
unsigned int fPythiaListVerbosity
Pythia6ServiceWithCallback(const edm::ParameterSet &ps)
HepMC::IO_HEPEVT conv
void fillEventInfo(HepMC::GenEvent *hepmc) const
Definition: LHEEvent.cc:242
unique_ptr< ClusterSequence > cs
static JetMatching * getJetMatching()
struct HEPEUP_ hepeup_
bool call_pygive(const std::string &line)
bool exists(std::string const &parameterName) const
checks if a parameter exists
const char * classname() const
void setLHERunInfo(lhef::LHERunInfo *lheri)
static struct gen::@630 pyjets_local
void count(LHERunInfo::CountMode count, double weight=1.0, double matchWeight=1.0)
Definition: LHEEvent.cc:200
virtual void beforeHadronisation(const lhef::LHEEvent *event)
Definition: JetMatching.cc:31
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
void setInternalXSec(const XSec &xsec)
#define vend()
Definition: vmac.h:43
void pyglrhad_()
void doSetRandomEngine(CLHEP::HepRandomEngine *v) override
double v[5][pyjets_maxn]
return((rh^lh)&mask)
virtual int match(const lhef::LHEEvent *partonLevel, const std::vector< fastjet::PseudoJet > *jetInput)=0
static const std::string kPythia6
GenRunInfoProduct & runInfo()
double p[5][pyjets_maxn]
bool declareStableParticles(const std::vector< int > &)
void call_pylist(int mode)
void resetMatchingStatus()
Definition: JetMatching.h:75
lhef::LHEEvent * lheEvent()
static const std::vector< std::string > theSharedResources
T sqrt(T t)
Definition: SSEVec.h:18
void setSLHAFromHeader(const std::vector< std::string > &lines)
#define vbegin()
Definition: vmac.h:36
void fillPdfInfo(HepMC::PdfInfo *info) const
Definition: LHEEvent.cc:214
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
#define pyint1
void pydecy_(int &ip)
void setPYUPDAParams(bool afterPyinit)
void pystfr_(int &)
Definition: value.py:1
Pythia6Hadronizer(edm::ParameterSet const &ps)
std::unique_ptr< HepMC::GenEvent > & event()
lhef::LHERunInfo * lheRunInfo()
int k[5][pyjets_maxn]
static const std::string kFortranInstance
static FortranCallback * getInstance()
int pycomp_(int &)
Pythia6Service * fPy6Service
#define pypars
void setLHEEvent(lhef::LHEEvent *lhee)
part
Definition: HCALResponse.h:20
std::unique_ptr< GenEventInfoProduct > & eventInfo()
virtual void beforeHadronisationExec()
Definition: JetMatching.cc:35
void setRandomEngine(CLHEP::HepRandomEngine *v)
bool isMatchingDone()
Definition: JetMatching.h:76
void pyglfr_()
bool declareSpecialSettings(const std::vector< std::string > &)
std::vector< std::string > findHeader(const std::string &tag) const
Definition: LHERunInfo.cc:525
double pyr_(int *idummy)
virtual void init(const lhef::LHERunInfo *runInfo)
Definition: JetMatching.cc:27
static std::unique_ptr< JetMatching > create(const edm::ParameterSet &params)
Definition: JetMatching.cc:47
void pystrhad_()
static JetMatching * fJetMatching