1 // ProcessLevel.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2010 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
6 // Function definitions (not found in the header) for the ProcessLevel class.
8 #include "ProcessLevel.h"
12 //==========================================================================
14 // The ProcessLevel class.
16 //--------------------------------------------------------------------------
18 // Constants: could be changed here if desired, but normally should not.
19 // These are of technical nature, as described for each.
21 // Allow a few failures in final construction of events.
22 const int ProcessLevel::MAXLOOP = 5;
24 //--------------------------------------------------------------------------
28 ProcessLevel::~ProcessLevel() {
30 // Run through list of first hard processes and delete them.
31 for (int i = 0; i < int(containerPtrs.size()); ++i)
32 delete containerPtrs[i];
34 // Run through list of second hard processes and delete them.
35 for (int i =0; i < int(container2Ptrs.size()); ++i)
36 delete container2Ptrs[i];
40 //--------------------------------------------------------------------------
42 // Main routine to initialize generation process.
44 bool ProcessLevel::init( Info* infoPtrIn, Settings& settings,
45 ParticleData* particleDataPtrIn, Rndm* rndmPtrIn,
46 BeamParticle* beamAPtrIn, BeamParticle* beamBPtrIn, Couplings* couplingsPtrIn,
47 SigmaTotal* sigmaTotPtrIn, bool doLHA, SusyLesHouches* slhaPtrIn,
48 UserHooks* userHooksPtrIn, vector<SigmaProcess*>& sigmaPtrs, ostream& os) {
50 // Store input pointers for future use.
52 particleDataPtr = particleDataPtrIn;
54 beamAPtr = beamAPtrIn;
55 beamBPtr = beamBPtrIn;
56 couplingsPtr = couplingsPtrIn;
57 sigmaTotPtr = sigmaTotPtrIn;
58 userHooksPtr = userHooksPtrIn;
61 // Send on some input pointers.
62 resonanceDecays.init( infoPtr, particleDataPtr, rndmPtr);
64 // Set up SigmaTotal. Store sigma_nondiffractive for future use.
65 sigmaTotPtr->init( infoPtr, settings, particleDataPtr);
66 int idA = infoPtr->idA();
67 int idB = infoPtr->idB();
68 double eCM = infoPtr->eCM();
69 sigmaTotPtr->calc( idA, idB, eCM);
70 sigmaND = sigmaTotPtr->sigmaND();
72 // Options to allow second hard interaction and resonance decays.
73 doSecondHard = settings.flag("SecondHard:generate");
74 doSameCuts = settings.flag("PhaseSpace:sameForSecond");
75 doResDecays = settings.flag("ProcessLevel:resonanceDecays");
76 startColTag = settings.mode("Event:startColTag");
78 // Mass and pT cuts for two hard processes.
79 mHatMin1 = settings.parm("PhaseSpace:mHatMin");
80 mHatMax1 = settings.parm("PhaseSpace:mHatMax");
81 if (mHatMax1 < mHatMin1) mHatMax1 = eCM;
82 pTHatMin1 = settings.parm("PhaseSpace:pTHatMin");
83 pTHatMax1 = settings.parm("PhaseSpace:pTHatMax");
84 if (pTHatMax1 < pTHatMin1) pTHatMax1 = eCM;
85 mHatMin2 = settings.parm("PhaseSpace:mHatMinSecond");
86 mHatMax2 = settings.parm("PhaseSpace:mHatMaxSecond");
87 if (mHatMax2 < mHatMin2) mHatMax2 = eCM;
88 pTHatMin2 = settings.parm("PhaseSpace:pTHatMinSecond");
89 pTHatMax2 = settings.parm("PhaseSpace:pTHatMaxSecond");
90 if (pTHatMax2 < pTHatMin2) pTHatMax2 = eCM;
92 // Check whether mass and pT ranges agree or overlap.
93 cutsAgree = doSameCuts;
94 if (mHatMin2 == mHatMin1 && mHatMax2 == mHatMax1 && pTHatMin2 == pTHatMin1
95 && pTHatMax2 == pTHatMax1) cutsAgree = true;
96 cutsOverlap = cutsAgree;
98 bool mHatOverlap = (max( mHatMin1, mHatMin2)
99 < min( mHatMax1, mHatMax2));
100 bool pTHatOverlap = (max( pTHatMin1, pTHatMin2)
101 < min( pTHatMax1, pTHatMax2));
102 if (mHatOverlap && pTHatOverlap) cutsOverlap = true;
105 // Set up containers for all the internal hard processes.
106 SetupContainers setupContainers;
107 setupContainers.init(containerPtrs, settings, particleDataPtr, couplingsPtr);
109 // Append containers for external hard processes, if any.
110 if (sigmaPtrs.size() > 0) {
111 for (int iSig = 0; iSig < int(sigmaPtrs.size()); ++iSig)
112 containerPtrs.push_back( new ProcessContainer(sigmaPtrs[iSig],
116 // Append single container for Les Houches processes, if any.
118 SigmaProcess* sigmaPtr = new SigmaLHAProcess();
119 containerPtrs.push_back( new ProcessContainer(sigmaPtr) );
121 // Store location of this container, and send in LHA pointer.
122 iLHACont = containerPtrs.size() - 1;
123 containerPtrs[iLHACont]->setLHAPtr(lhaUpPtr);
126 // If no processes found then refuse to do anything.
127 if ( int(containerPtrs.size()) == 0) {
128 infoPtr->errorMsg("Error in ProcessLevel::init: "
129 "no process switched on");
133 // Check that SUSY couplings were indeed initialized where necessary.
134 bool hasSUSY = false;
135 for (int i = 0; i < int(containerPtrs.size()); ++i)
136 if (containerPtrs[i]->isSUSY()) hasSUSY = true;
138 //If SUSY processes requested but no SUSY couplings present
139 if(hasSUSY && !couplingsPtr->isSUSY) {
140 infoPtr->errorMsg("Error in ProcessLevel::init: "
141 "SUSY process switched on but no SUSY couplings found");
145 // Initialize each process.
147 for (int i = 0; i < int(containerPtrs.size()); ++i)
148 if (containerPtrs[i]->init(true, infoPtr, settings, particleDataPtr,
149 rndmPtr, beamAPtr, beamBPtr, couplingsPtr, sigmaTotPtr,
150 &resonanceDecays, slhaPtr, userHooksPtr)) ++numberOn;
152 // Sum maxima for Monte Carlo choice.
154 for (int i = 0; i < int(containerPtrs.size()); ++i)
155 sigmaMaxSum += containerPtrs[i]->sigmaMax();
157 // Option to pick a second hard interaction: repeat as above.
160 setupContainers.init2(container2Ptrs, settings);
161 if ( int(container2Ptrs.size()) == 0) {
162 infoPtr->errorMsg("Error in ProcessLevel::init: "
163 "no second hard process switched on");
166 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
167 if (container2Ptrs[i2]->init(false, infoPtr, settings, particleDataPtr,
168 rndmPtr, beamAPtr, beamBPtr, couplingsPtr, sigmaTotPtr,
169 &resonanceDecays, slhaPtr, userHooksPtr)) ++number2On;
171 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
172 sigma2MaxSum += container2Ptrs[i2]->sigmaMax();
175 // Construct string with incoming beams and for cm energy.
176 string collision = "We collide " + particleDataPtr->name(idA)
177 + " with " + particleDataPtr->name(idB) + " at a CM energy of ";
178 string pad( 51 - collision.length(), ' ');
180 // Print initialization information: header.
181 os << "\n *------- PYTHIA Process Initialization ---------"
182 << "-----------------*\n"
185 << " | " << collision << scientific << setprecision(3)<< setw(9) << eCM
186 << " GeV" << pad << " |\n"
189 << " |---------------------------------------------------"
190 << "---------------|\n"
193 << " | Subprocess Code"
194 << " | Estimated |\n"
199 << " |---------------------------------------------------"
200 << "---------------|\n"
205 // Loop over existing processes: print individual process info.
206 for (int i = 0; i < int(containerPtrs.size()); ++i)
207 os << " | " << left << setw(45) << containerPtrs[i]->name()
208 << right << setw(5) << containerPtrs[i]->code() << " | "
209 << scientific << setprecision(3) << setw(11)
210 << containerPtrs[i]->sigmaMax() << " |\n";
212 // Loop over second hard processes, if any, and repeat as above.
216 << " |---------------------------------------------------"
217 <<"---------------|\n"
220 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
221 os << " | " << left << setw(45) << container2Ptrs[i2]->name()
222 << right << setw(5) << container2Ptrs[i2]->code() << " | "
223 << scientific << setprecision(3) << setw(11)
224 << container2Ptrs[i2]->sigmaMax() << " |\n";
230 << " *------- End PYTHIA Process Initialization ----------"
231 <<"-------------*" << endl;
233 // If sum of maxima vanishes then refuse to do anything.
234 if ( numberOn == 0 || sigmaMaxSum <= 0.) {
235 infoPtr->errorMsg("Error in ProcessLevel::init: "
236 "all processes have vanishing cross sections");
239 if ( doSecondHard && (number2On == 0 || sigma2MaxSum <= 0.) ) {
240 infoPtr->errorMsg("Error in ProcessLevel::init: "
241 "all second hard processes have vanishing cross sections");
245 // If two hard processes then check whether some (but not all) agree.
249 bool foundMatch = false;
251 // Check for each first process if matched in second.
252 for (int i = 0; i < int(containerPtrs.size()); ++i) {
255 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
256 if (container2Ptrs[i2]->code() == containerPtrs[i]->code())
258 containerPtrs[i]->isSame( foundMatch );
259 if (!foundMatch) allHardSame = false;
260 if ( foundMatch) noneHardSame = false;
263 // Check for each second process if matched in first.
264 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
267 for (int i = 0; i < int(containerPtrs.size()); ++i)
268 if (containerPtrs[i]->code() == container2Ptrs[i2]->code())
270 container2Ptrs[i2]->isSame( foundMatch );
271 if (!foundMatch) allHardSame = false;
272 if ( foundMatch) noneHardSame = false;
276 // Concluding classification, including cuts.
277 if (!cutsAgree) allHardSame = false;
278 someHardSame = !allHardSame && !noneHardSame;
280 // Reset counters for average impact-parameter enhancement.
285 // Statistics for LHA events.
293 //--------------------------------------------------------------------------
295 // Main routine to generate the hard process.
297 bool ProcessLevel::next( Event& process) {
299 // Generate the next event with two or one hard interactions.
300 bool physical = (doSecondHard) ? nextTwo( process) : nextOne( process);
302 // Check that colour assignments make sense.
303 if (physical) physical = checkColours( process);
309 //--------------------------------------------------------------------------
311 // Accumulate and update statistics (after possible user veto).
313 void ProcessLevel::accumulate() {
315 // Increase number of accepted events.
316 containerPtrs[iContainer]->accumulate();
318 // Provide current generated cross section estimate.
322 double sigmaSum = 0.;
323 double delta2Sum = 0.;
324 double sigSelSum = 0.;
325 for (int i = 0; i < int(containerPtrs.size()); ++i)
326 if (containerPtrs[i]->sigmaMax() != 0.) {
327 nTrySum += containerPtrs[i]->nTried();
328 nSelSum += containerPtrs[i]->nSelected();
329 nAccSum += containerPtrs[i]->nAccepted();
330 sigmaSum += containerPtrs[i]->sigmaMC();
331 delta2Sum += pow2(containerPtrs[i]->deltaMC());
332 sigSelSum += containerPtrs[i]->sigmaSelMC();
335 // For Les Houches events find subprocess type and update counter.
336 if (infoPtr->isLHA()) {
337 int codeLHANow = infoPtr->codeSub();
339 for (int i = 0; i < int(codeLHA.size()); ++i)
340 if (codeLHANow == codeLHA[i]) iFill = i;
341 if (iFill >= 0) ++nEvtLHA[iFill];
343 // Add new process when new code and then arrange in order.
345 codeLHA.push_back(codeLHANow);
346 nEvtLHA.push_back(1);
347 for (int i = int(codeLHA.size()) - 1; i > 0; --i) {
348 if (codeLHA[i] < codeLHA[i - 1]) {
349 swap(codeLHA[i], codeLHA[i - 1]);
350 swap(nEvtLHA[i], nEvtLHA[i - 1]);
357 // Normally only one hard interaction. Then store info and done.
359 double deltaSum = sqrtpos(delta2Sum);
360 infoPtr->setSigma( nTrySum, nSelSum, nAccSum, sigmaSum, deltaSum);
364 // Increase counter for a second hard interaction.
365 container2Ptrs[i2Container]->accumulate();
367 // Update statistics on average impact factor.
369 sumImpactFac += infoPtr->enhanceMI();
370 sum2ImpactFac += pow2(infoPtr->enhanceMI());
372 // Cross section estimate for second hard process.
373 double sigma2Sum = 0.;
374 double sig2SelSum = 0.;
375 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
376 if (container2Ptrs[i2]->sigmaMax() != 0.) {
377 nTrySum += container2Ptrs[i2]->nTried();
378 sigma2Sum += container2Ptrs[i2]->sigmaMC();
379 sig2SelSum += container2Ptrs[i2]->sigmaSelMC();
382 // Average impact-parameter factor and error.
383 double invN = 1. / max(1, nImpact);
384 double impactFac = max( 1., sumImpactFac * invN);
385 double impactErr2 = ( sum2ImpactFac * invN / pow2(impactFac) - 1.) * invN;
387 // Cross section estimate for combination of first and second process.
388 // Combine two possible ways and take average.
389 double sigmaComb = 0.5 * (sigmaSum * sig2SelSum + sigSelSum * sigma2Sum);
390 sigmaComb *= impactFac / sigmaND;
391 if (allHardSame) sigmaComb *= 0.5;
392 double deltaComb = sqrtpos(2. / nAccSum + impactErr2) * sigmaComb;
394 // Store info and done.
395 infoPtr->setSigma( nTrySum, nSelSum, nAccSum, sigmaComb, deltaComb);
399 //--------------------------------------------------------------------------
401 // Print statistics on cross sections and number of events.
403 void ProcessLevel::statistics(bool reset, ostream& os) {
405 // Special processing if two hard interactions selected.
407 statistics2(reset, os);
412 os << "\n *------- PYTHIA Event and Cross Section Statistics ------"
413 << "-------------------------------------------------------*\n"
416 << " | Subprocess Code | "
417 << " Number of events | sigma +- delta |\n"
419 << "Tried Selected Accepted | (estimated) (mb) |\n"
422 << " |------------------------------------------------------------"
423 << "-----------------------------------------------------|\n"
427 // Reset sum counters.
431 double sigmaSum = 0.;
432 double delta2Sum = 0.;
434 // Loop over existing processes.
435 for (int i = 0; i < int(containerPtrs.size()); ++i)
436 if (containerPtrs[i]->sigmaMax() != 0.) {
438 // Read info for process. Sum counters.
439 long nTry = containerPtrs[i]->nTried();
440 long nSel = containerPtrs[i]->nSelected();
441 long nAcc = containerPtrs[i]->nAccepted();
442 double sigma = containerPtrs[i]->sigmaMC();
443 double delta = containerPtrs[i]->deltaMC();
448 delta2Sum += pow2(delta);
450 // Print individual process info.
451 os << " | " << left << setw(45) << containerPtrs[i]->name()
452 << right << setw(5) << containerPtrs[i]->code() << " | "
453 << setw(11) << nTry << " " << setw(10) << nSel << " "
454 << setw(10) << nAcc << " | " << scientific << setprecision(3)
455 << setw(11) << sigma << setw(11) << delta << " |\n";
457 // Print subdivision by user code for Les Houches process.
458 if (containerPtrs[i]->code() == 9999)
459 for (int j = 0; j < int(codeLHA.size()); ++j)
460 os << " | ... whereof user classification code " << setw(10)
461 << codeLHA[j] << " | " << setw(10)
462 << nEvtLHA[j] << " | | \n";
465 // Print summed process info.
468 << " | " << left << setw(50) << "sum" << right << " | " << setw(11)
469 << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
470 << nAccSum << " | " << scientific << setprecision(3) << setw(11)
471 << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
476 << " *------- End PYTHIA Event and Cross Section Statistics -----"
477 << "-----------------------------------------------------*" << endl;
479 // Optionally reset statistics contants.
480 if (reset) for (int i = 0; i < int(containerPtrs.size()); ++i)
481 containerPtrs[i]->reset();
485 //--------------------------------------------------------------------------
487 // Generate the next event with one interaction.
489 bool ProcessLevel::nextOne( Event& process) {
491 // Update CM energy for phase space selection.
492 double eCM = infoPtr->eCM();
493 for (int i = 0; i < int(containerPtrs.size()); ++i)
494 containerPtrs[i]->newECM(eCM);
496 // Outer loop in case of rare failures.
497 bool physical = true;
498 for (int loop = 0; loop < MAXLOOP; ++loop) {
499 if (!physical) process.clear();
502 // Loop over tries until trial event succeeds.
505 // Pick one of the subprocesses.
506 double sigmaMaxNow = sigmaMaxSum * rndmPtr->flat();
507 int iMax = containerPtrs.size() - 1;
509 do sigmaMaxNow -= containerPtrs[++iContainer]->sigmaMax();
510 while (sigmaMaxNow > 0. && iContainer < iMax);
512 // Do a trial event of this subprocess; accept or not.
513 if (containerPtrs[iContainer]->trialProcess()) break;
515 // Check for end-of-file condition for Les Houches events.
516 if (infoPtr->atEndOfFile()) return false;
519 // Update sum of maxima if current maximum violated.
520 if (containerPtrs[iContainer]->newSigmaMax()) {
522 for (int i = 0; i < int(containerPtrs.size()); ++i)
523 sigmaMaxSum += containerPtrs[i]->sigmaMax();
526 // Construct kinematics of acceptable process.
527 if ( !containerPtrs[iContainer]->constructProcess( process) )
530 // Do all resonance decays.
531 if ( physical && doResDecays
532 && !containerPtrs[iContainer]->decayResonances( process) )
535 // Add any junctions to the process event record list.
536 if (physical) findJunctions( process);
538 // Outer loop should normally work first time around.
546 //--------------------------------------------------------------------------
548 // Generate the next event with two hard interactions.
550 bool ProcessLevel::nextTwo( Event& process) {
552 // Update CM energy for phase space selection.
553 double eCM = infoPtr->eCM();
554 for (int i = 0; i < int(containerPtrs.size()); ++i)
555 containerPtrs[i]->newECM(eCM);
556 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
557 container2Ptrs[i2]->newECM(eCM);
559 // Outer loop in case of rare failures.
560 bool physical = true;
561 for (int loop = 0; loop < MAXLOOP; ++loop) {
562 if (!physical) process.clear();
565 // Loop over both hard processes to find consistent common kinematics.
568 // Loop internally over tries for hardest process until succeeds.
571 // Pick one of the subprocesses.
572 double sigmaMaxNow = sigmaMaxSum * rndmPtr->flat();
573 int iMax = containerPtrs.size() - 1;
575 do sigmaMaxNow -= containerPtrs[++iContainer]->sigmaMax();
576 while (sigmaMaxNow > 0. && iContainer < iMax);
578 // Do a trial event of this subprocess; accept or not.
579 if (containerPtrs[iContainer]->trialProcess()) break;
581 // Check for end-of-file condition for Les Houches events.
582 if (infoPtr->atEndOfFile()) return false;
585 // Update sum of maxima if current maximum violated.
586 if (containerPtrs[iContainer]->newSigmaMax()) {
588 for (int i = 0; i < int(containerPtrs.size()); ++i)
589 sigmaMaxSum += containerPtrs[i]->sigmaMax();
592 // Loop internally over tries for second hardest process until succeeds.
595 // Pick one of the subprocesses.
596 double sigma2MaxNow = sigma2MaxSum * rndmPtr->flat();
597 int i2Max = container2Ptrs.size() - 1;
599 do sigma2MaxNow -= container2Ptrs[++i2Container]->sigmaMax();
600 while (sigma2MaxNow > 0. && i2Container < i2Max);
602 // Do a trial event of this subprocess; accept or not.
603 if (container2Ptrs[i2Container]->trialProcess()) break;
606 // Update sum of maxima if current maximum violated.
607 if (container2Ptrs[i2Container]->newSigmaMax()) {
609 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
610 sigma2MaxSum += container2Ptrs[i2]->sigmaMax();
613 // Check whether common set of x values is kinematically possible.
614 double xA1 = containerPtrs[iContainer]->x1();
615 double xB1 = containerPtrs[iContainer]->x2();
616 double xA2 = container2Ptrs[i2Container]->x1();
617 double xB2 = container2Ptrs[i2Container]->x2();
618 if (xA1 + xA2 >= 1. || xB1 + xB2 >= 1.) continue;
620 // Reset beam contents. Naive parton densities for second interaction.
621 // (Subsequent procedure could be symmetrized, but would be overkill.)
624 int idA1 = containerPtrs[iContainer]->id1();
625 int idB1 = containerPtrs[iContainer]->id2();
626 int idA2 = container2Ptrs[i2Container]->id1();
627 int idB2 = container2Ptrs[i2Container]->id2();
628 double Q2Fac1 = containerPtrs[iContainer]->Q2Fac();
629 double Q2Fac2 = container2Ptrs[i2Container]->Q2Fac();
630 double pdfA2Raw = beamAPtr->xf( idA2, xA2,Q2Fac2);
631 double pdfB2Raw = beamBPtr->xf( idB2, xB2,Q2Fac2);
633 // Remove partons in first interaction from beams.
634 beamAPtr->append( 3, idA1, xA1);
635 beamAPtr->xfISR( 0, idA1, xA1, Q2Fac1);
636 beamAPtr->pickValSeaComp();
637 beamBPtr->append( 4, idB1, xB1);
638 beamBPtr->xfISR( 0, idB1, xB1, Q2Fac1);
639 beamBPtr->pickValSeaComp();
641 // Reevaluate pdf's for second interaction and weight by reduction.
642 double pdfA2Mod = beamAPtr->xfMI( idA2, xA2,Q2Fac2);
643 double pdfB2Mod = beamBPtr->xfMI( idB2, xB2,Q2Fac2);
644 double wtPdfMod = (pdfA2Mod * pdfB2Mod) / (pdfA2Raw * pdfB2Raw);
645 if (wtPdfMod < rndmPtr->flat()) continue;
647 // Reduce by a factor of 2 for identical processes when others not,
648 // and when in same phase space region.
650 if ( someHardSame && containerPtrs[iContainer]->isSame()
651 && container2Ptrs[i2Container]->isSame()) {
653 if (rndmPtr->flat() > 0.5) toLoop = true;
655 double mHat1 = containerPtrs[iContainer]->mHat();
656 double pTHat1 = containerPtrs[iContainer]->pTHat();
657 double mHat2 = container2Ptrs[i2Container]->mHat();
658 double pTHat2 = container2Ptrs[i2Container]->pTHat();
659 if (mHat1 > mHatMin2 && mHat1 < mHatMax2
660 && pTHat1 > pTHatMin2 && pTHat1 < pTHatMax2
661 && mHat2 > mHatMin1 && mHat2 < mHatMax1
662 && pTHat2 > pTHatMin1 && pTHat2 < pTHatMax1
663 && rndmPtr->flat() > 0.5) toLoop = true;
666 if (toLoop) continue;
668 // If come this far then acceptable event.
672 // Construct kinematics of acceptable processes.
674 process2.init( "(second hard)", particleDataPtr, startColTag);
675 process2.initColTag();
676 if ( !containerPtrs[iContainer]->constructProcess( process) )
678 if (physical && !container2Ptrs[i2Container]->constructProcess( process2,
679 false) ) physical = false;
681 // Do all resonance decays.
682 if ( physical && doResDecays
683 && !containerPtrs[iContainer]->decayResonances( process) )
685 if ( physical && doResDecays
686 && !container2Ptrs[i2Container]->decayResonances( process2) )
689 // Append second hard interaction to normal process object.
690 if (physical) combineProcessRecords( process, process2);
692 // Add any junctions to the process event record list.
693 if (physical) findJunctions( process);
695 // Outer loop should normally work first time around.
703 //--------------------------------------------------------------------------
705 // Append second hard interaction to normal process object.
706 // Complication: all resonance decay chains must be put at the end.
708 void ProcessLevel::combineProcessRecords( Event& process, Event& process2) {
710 // Find first event record size, excluding resonances.
711 int nSize = process.size();
713 while (nHard < nSize && process[nHard].mother1() == 3) ++nHard;
715 // Save resonance products temporarily elsewhere.
716 vector<Particle> resProd;
718 for (int i = nHard; i < nSize; ++i) resProd.push_back( process[i] );
719 process.popBack(nSize - nHard);
722 // Find second event record size, excluding resonances.
723 int nSize2 = process2.size();
725 while (nHard2 < nSize2 && process2[nHard2].mother1() == 3) ++nHard2;
727 // Find amount of necessary position and colour offset for second process.
728 int addPos = nHard - 3;
729 int addCol = process.lastColTag() - startColTag;
731 // Loop over all particles (except beams) from second process.
732 for (int i = 3; i < nSize2; ++i) {
734 // Offset mother and daughter pointers and colour tags of particle.
735 process2[i].offsetHistory( 2, addPos, 2, addPos);
736 process2[i].offsetCol( addCol);
738 // Append hard-process particles from process2 to process.
739 if (i < nHard2) process.append( process2[i] );
742 // Reinsert resonance decay chains of first hard process.
743 int addPos2 = nHard2 - 3;
746 // Offset daughter pointers of unmoved mothers.
747 for (int i = 5; i < nHard; ++i)
748 process[i].offsetHistory( 0, 0, nHard - 1, addPos2);
750 // Modify history of resonance products when restoring.
751 for (int i = 0; i < int(resProd.size()); ++i) {
752 resProd[i].offsetHistory( nHard - 1, addPos2, nHard - 1, addPos2);
753 process.append( resProd[i] );
757 // Insert resonance decay chains of second hard process.
758 if (nHard2 < nSize2) {
759 int nHard3 = nHard + nHard2 - 3;
760 int addPos3 = nSize - nHard;
762 // Offset daughter pointers of second-process mothers.
763 for (int i = nHard + 2; i < nHard3; ++i)
764 process[i].offsetHistory( 0, 0, nHard3 - 1, addPos3);
766 // Modify history of second-process resonance products and insert.
767 for (int i = nHard2; i < nSize2; ++i) {
768 process2[i].offsetHistory( nHard3 - 1, addPos3, nHard3 - 1, addPos3);
769 process.append( process2[i] );
773 // Store PDF scale for second interaction.
774 process.scaleSecond( process2.scale() );
778 //--------------------------------------------------------------------------
780 // Add any junctions to the process event record list.
781 // Also check that do not doublebook if called repeatedly.
783 void ProcessLevel::findJunctions( Event& junEvent) {
785 // Find the total number of unmatched colours & anticolours in the event
786 map<int,int> colMap, acolMap;
787 for (int i = 0; i < junEvent.size(); ++i) {
788 // Consider all external lines (including initial incoming ones)
789 int col = junEvent[i].col();
790 int acol = junEvent[i].acol();
791 if (junEvent[i].isFinal() || abs(junEvent[i].status()) == 21) {
792 // Cross initial-state colors
793 if (junEvent[i].status() == -21) {
794 col = junEvent[i].acol();
795 acol = junEvent[i].col();
798 // If unmatched (so far), add end. Else erase matching parton.
799 if (acolMap.find(col) == acolMap.end() ) colMap[col] = i;
800 else acolMap.erase(col);
803 // If unmatched (so far), add end. Else erase matching parton.
804 if (colMap.find(acol) == colMap.end()) acolMap[acol] = i;
805 else colMap.erase(acol);
808 // For internal particles, check for internal junction lines
809 // by counting total number of triplets at each vertex
810 else if (abs(junEvent[i].status()) == 22) {
812 int idRes = junEvent[i].id();
813 // Only consider triplets for the time being, since these are the ones
814 // most likely to cause trouble.
815 // (E.g., internal stop in resonant stop production)
816 if (junEvent[i].colType() != 1) continue;
817 // Decaying particle crossed => triplet <-> antitriplet
818 if (idRes < 0) cSum += (junEvent[i].colType() % 2) ;
819 else cSum -= (junEvent[i].colType() % 2) ;
820 int iDau1 = junEvent[i].daughter1();
821 int iDau2 = max(iDau1,junEvent[i].daughter2());
822 for (int iDau=iDau1; iDau<=iDau2; iDau++) {
823 if (junEvent[iDau].id() > 0) cSum += (junEvent[iDau].colType() % 2) ;
824 else cSum -= (junEvent[iDau].colType() % 2) ;
826 // Add dangling internal tag if not already present
828 if (idRes > 0 && acolMap.find(col) == acolMap.end()) acolMap[col]=i;
829 if (idRes < 0 && colMap.find(acol) == colMap.end()) colMap[acol]=i;
834 // Number of expected junctions and antijunctions
835 // (Add 2 to account for max 2 junction-antijunction connections)
836 int nJunc = (colMap.size()+2)/3;
837 int nAntiJunc = (acolMap.size()+2)/3;
839 //cout<<" nJunc = "<<nJunc<<" nAntiJunc = "<<nAntiJunc<<endl;
841 // If no junctions expected, return without doing anything more
842 if (max(nJunc,nAntiJunc) == 0) return;
844 // Junctions expected. Check (and skip) any that have already been added
845 for (int iJun = 0; iJun < junEvent.sizeJunction(); ++iJun) {
846 // Remove the tags corresponding to each of the 3 existing junction legs
847 for (int j = 0; j < 3; ++j) {
848 int colNow = junEvent.colJunction(iJun, j);
849 if (junEvent.kindJunction(iJun) % 2 == 1) colMap.erase(colNow);
850 else acolMap.erase(colNow);
854 // Update Number of expected junctions and antijunctions
855 nJunc = (colMap.size()+2)/3;
856 nAntiJunc = (acolMap.size()+2)/3;
858 // cout<<" AR nJunc = "<<nJunc<<" nAntiJunc = "<<nAntiJunc<<endl;
860 // If no (more) junctions expected, return without doing anything more
861 if (max(nJunc,nAntiJunc) == 0) return;
863 // Loop: first check colors, then anticolors
864 for (int mAcol = 0; mAcol <= 1; mAcol++) {
865 map<int,int>& cMap = colMap;
866 if (mAcol == 1) cMap = acolMap;
868 // Trace colours to find junction vertices and missing lines from
869 // internal junction-antijunction connections (such connections *must*
870 // be represented by internal lines connecting the junction vertices)
871 for (map<int,int>::iterator it = cMap.begin(); it != cMap.end(); it++) {
872 int col1 = it->first;
875 bool goForward = false;
876 // Reverse direction for particles in initial state
877 if ( !junEvent[i1].isFinal() ) goForward = true;
878 // Skip colour tags that have already been associated with a junction
879 bool skipCol = false;
880 for (int iJun = 0; iJun < junEvent.sizeJunction(); ++iJun) {
881 // Only look at other (anti)junctions
882 if (junEvent.kindJunction(iJun) % 2 == mAcol) continue;
883 for (int j = 0; j < 3; ++j) {
884 int colNow = junEvent.colJunction(iJun, j);
885 if (colNow == col1) skipCol = true;
889 //cout << "Skipping (a)col : "<<col1<<" at "<<i1<<endl;
892 //cout << "Tracing (a)col : "<<col1<<" from "<<i1<<endl;
895 // Step to mother (or daughter, if doing forward search)
898 // For now, assume daughter1 always is the one that leads to the
899 // hard interaction. Otherwise, may need to search among daughters.
900 i2 = junEvent[i1].daughter1();
902 i2 = junEvent[i1].mother2();
903 i1 = junEvent[i1].mother1();
905 int iDau1 = junEvent[i1].daughter1();
906 int iDau2 = max(iDau1,junEvent[i1].daughter2());
908 // If we went all the way back to the beam without finding a violation,
910 if (i1 <= 0 || abs(junEvent[i1].status()) <= 20) search = false;
911 // Check baryon number of vertex, counting incoming
912 // partons with a minus sign
914 //cout << " at : "<<i1<<" colType = "<<junEvent[i1].colType()<<endl;
915 if (abs(junEvent[i1].colType()) == 1) barSum -= junEvent[i1].colType();
916 if (i2 != 0 && abs(junEvent[i2].colType()) == 1 )
917 barSum -= junEvent[i2].colType();
918 for (int iDau = iDau1; iDau <= iDau2; iDau++)
919 if ( abs(junEvent[iDau].colType()) == 1 )
920 barSum += junEvent[iDau].colType();
922 // If still searching, and if B is violated at this vertex => junction
923 // Still needs additional refinement for complicated cases ???
924 if (search && barSum != 0) {
925 //cout<<" (anti)junction found at : "<<i1<<endl;
926 // Find the 3 (anti)colour tags for this junction
927 // If going forward, now change i2 from daughter to other mother
928 if (goForward && i2 == iDau1) {
929 if (junEvent[i2].mother1() == i1) i2 = junEvent[i2].mother2();
930 else i2 = junEvent[i2].mother1();
932 //cout <<" Checking vertex: i1 = "<<i1<<" i2 = "<<i2<<endl;
933 // Determine which (anti)color tags go to junction
935 int c1(0), c2(0), cMot1(0), cMot2(0);
936 // First determine number of incoming lines
938 // For junctions: look at incoming anticolors
939 c1 = junEvent[i1].acol();
941 // Also store incoming colors, to check for flow-through later
942 cMot1 = junEvent[i1].col();
944 c2 = junEvent[i2].acol();
945 cMot2 = junEvent[i1].col();
946 // Remove annihilation-type flows
947 if (c1 != 0 && junEvent[i2].col() == c1) c1 = 0;
948 if (c2 != 0 && junEvent[i1].col() == c2) c2 = 0;
949 // Remove anticolors flowing through diagram
950 for (int iDau = iDau1; iDau <= iDau2; iDau++) {
951 int acolDau = junEvent[iDau].acol();
952 if (c1 != 0 && acolDau == c1) c1 = 0;
953 if (c2 != 0 && acolDau == c2) c2 = 0;
957 // For antijunctions: look at incoming colors
958 c1 = junEvent[i1].col();
960 // Also store incoming anticolors, to check for flow-through later
961 cMot1 = junEvent[i1].acol();
963 c2 = junEvent[i2].col();
964 cMot2 = junEvent[i2].acol();
965 // Remove annihilation-type flows
966 if (c1 != 0 && junEvent[i2].acol() == c1) c1 = 0;
967 if (c2 != 0 && junEvent[i1].acol() == c2) c2 = 0;
968 // Remove colors flowing through diagram
969 for (int iDau = iDau1; iDau <= iDau2; iDau++) {
970 int colDau = junEvent[iDau].col();
971 if (c1 != 0 && colDau == c1) c1 = 0;
972 if (c2 != 0 && colDau == c2) c2 = 0;
976 // Add non-annihilated colors
977 if (c1 != 0) colJu.push_back(c1);
978 if (c2 != 0) colJu.push_back(c2);
979 // Determine junction kind from number of incoming lines
980 int kindJun = 1 + mAcol + 2*colJu.size();
981 //cout<<" Junction type : "<<kindJun<<endl;
982 // Now add daughter color tags to junction
983 for (int iDau = iDau1; iDau <= iDau2; iDau++) {
985 // For junctions: look at final-state colors, and vice-versa
986 if (mAcol == 0) c1 = junEvent[iDau].col();
987 else c1 = junEvent[iDau].acol();
988 // Remove non-existent and (anti)colors flowing through diagram
989 if (c1 == 0 || c1 == cMot1 || c1 == cMot2) continue;
990 // Remove final-state matching color-anticolor pairs
991 bool matchedPair = false;
992 for (int jDau = iDau1; jDau <= iDau2; jDau++)
993 if (mAcol==0 && c1 == junEvent[jDau].acol()) matchedPair = true;
994 else if (mAcol==1 && c1 == junEvent[jDau].col()) matchedPair = true;
995 if (matchedPair) continue;
996 // Else add anticolor to junction ends
997 else colJu.push_back(c1);
999 if (colJu.size() != 3) {
1000 cout<< " (ProcessLevel::findJunctions:) problem identifying junction "<<endl;
1003 //cout<< " adding junction type "
1004 // <<kindJun<<" "<<colJu[0]<<" "<<colJu[1]<<" "<<colJu[2]<<endl;
1005 junEvent.appendJunction( kindJun, colJu[0], colJu[1], colJu[2]);
1016 //--------------------------------------------------------------------------
1018 // Check that colours match up.
1020 bool ProcessLevel::checkColours( Event& process) {
1022 // Variables and arrays for common usage.
1023 bool physical = true;
1025 int colType, col, acol, iPos, iNow, iNowA;
1026 vector<int> colTags, colPos, acolPos;
1028 // Check that each particle has the kind of colours expected of it.
1029 for (int i = 0; i < process.size(); ++i) {
1030 colType = process[i].colType();
1031 col = process[i].col();
1032 acol = process[i].acol();
1033 if (colType == 0 && (col != 0 || acol != 0)) physical = false;
1034 else if (colType == 1 && (col <= 0 || acol != 0)) physical = false;
1035 else if (colType == -1 && (col != 0 || acol <= 0)) physical = false;
1036 else if (colType == 2 && (col <= 0 || acol <= 0)) physical = false;
1037 else if (colType < -1 || colType > 2) physical = false;
1039 // Add to the list of colour tags.
1042 for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1043 if (col == colTags[ic]) match = true;
1044 if (!match) colTags.push_back(col);
1045 } else if (acol > 0) {
1047 for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1048 if (acol == colTags[ic]) match = true;
1049 if (!match) colTags.push_back(acol);
1053 // Warn and give up if particles did not have the expected colours.
1055 infoPtr->errorMsg("Error in ProcessLevel::checkColours: "
1056 "incorrect colour assignment");
1060 // Remove (anti)colours coming from an (anti)junction.
1062 //cout<<" Removing junction tags in:"<<endl;
1064 //cout<<" Size of junctions "<<process.sizeJunction()<<endl;
1066 for (int iJun = 0; iJun < process.sizeJunction(); ++iJun) {
1067 for (int j = 0; j < 3; ++j) {
1068 int colJun = process.colJunction(iJun, j);
1069 for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1070 if (colJun == colTags[ic]) {
1071 colTags[ic] = colTags[colTags.size() - 1];
1078 // Loop through all colour tags and find their positions (by sign).
1079 for (int ic = 0; ic < int(colTags.size()); ++ic) {
1083 for (int i = 0; i < process.size(); ++i) {
1084 if (process[i].col() == col) colPos.push_back(i);
1085 if (process[i].acol() == col) acolPos.push_back(i);
1088 // Trace colours back through decays; remove daughters.
1089 while (colPos.size() > 1) {
1090 iPos = colPos.size() - 1;
1091 iNow = colPos[iPos];
1092 if ( process[iNow].mother1() == colPos[iPos - 1]
1093 && process[iNow].mother2() == 0) colPos.pop_back();
1096 while (acolPos.size() > 1) {
1097 iPos = acolPos.size() - 1;
1098 iNow = acolPos[iPos];
1099 if ( process[iNow].mother1() == acolPos[iPos - 1]
1100 && process[iNow].mother2() == 0) acolPos.pop_back();
1104 // Now colour should exist in only 2 copies.
1105 if (colPos.size() + acolPos.size() != 2) physical = false;
1107 // If both colours or both anticolours then one mother of the other.
1108 else if (colPos.size() == 2) {
1110 if ( process[iNow].mother1() != colPos[0]
1111 && process[iNow].mother2() != colPos[0] ) physical = false;
1113 else if (acolPos.size() == 2) {
1115 if ( process[iNowA].mother1() != acolPos[0]
1116 && process[iNowA].mother2() != acolPos[0] ) physical = false;
1119 // If one of each then should have same mother(s), or point to beams.
1123 if ( process[iNow].status() == -21 && process[iNowA].status() == -21 );
1124 else if ( (process[iNow].mother1() != process[iNowA].mother1())
1125 || (process[iNow].mother2() != process[iNowA].mother2()) ) {
1126 cout<<" Argh!"<<endl;
1133 // Error message if problem found. Done.
1134 if (!physical) infoPtr->errorMsg("Error in ProcessLevel::checkColours: "
1135 "unphysical colour flow");
1140 //--------------------------------------------------------------------------
1142 // Print statistics when two hard processes allowed.
1144 void ProcessLevel::statistics2(bool reset, ostream& os) {
1146 // Average impact-parameter factor and error.
1147 double invN = 1. / max(1, nImpact);
1148 double impactFac = max( 1., sumImpactFac * invN);
1149 double impactErr2 = ( sum2ImpactFac * invN / pow2(impactFac) - 1.) * invN;
1151 // Derive scaling factor to be applied to first set of processes.
1152 double sigma2SelSum = 0.;
1154 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
1155 sigma2SelSum += container2Ptrs[i2]->sigmaSelMC();
1156 n2SelSum += container2Ptrs[i2]->nSelected();
1158 double factor1 = impactFac * sigma2SelSum / sigmaND;
1159 double rel1Err = sqrt(1. / max(1, n2SelSum) + impactErr2);
1160 if (allHardSame) factor1 *= 0.5;
1162 // Derive scaling factor to be applied to second set of processes.
1163 double sigma1SelSum = 0.;
1165 for (int i = 0; i < int(containerPtrs.size()); ++i) {
1166 sigma1SelSum += containerPtrs[i]->sigmaSelMC();
1167 n1SelSum += containerPtrs[i]->nSelected();
1169 double factor2 = impactFac * sigma1SelSum / sigmaND;
1170 if (allHardSame) factor2 *= 0.5;
1171 double rel2Err = sqrt(1. / max(1, n1SelSum) + impactErr2);
1174 os << "\n *------- PYTHIA Event and Cross Section Statistics ------"
1175 << "--------------------------------------------------*\n"
1178 << " | Subprocess Code | "
1179 << "Number of events | sigma +- delta |\n"
1181 << " Selected Accepted | (estimated) (mb) |\n"
1184 << " |------------------------------------------------------------"
1185 << "------------------------------------------------|\n"
1188 << " | First hard process: | "
1193 // Reset sum counters.
1197 double sigmaSum = 0.;
1198 double delta2Sum = 0.;
1200 // Loop over existing first processes.
1201 for (int i = 0; i < int(containerPtrs.size()); ++i)
1202 if (containerPtrs[i]->sigmaMax() != 0.) {
1204 // Read info for process. Sum counters.
1205 long nTry = containerPtrs[i]->nTried();
1206 long nSel = containerPtrs[i]->nSelected();
1207 long nAcc = containerPtrs[i]->nAccepted();
1208 double sigma = containerPtrs[i]->sigmaMC() * factor1;
1209 double delta2 = pow2( containerPtrs[i]->deltaMC() * factor1 );
1214 delta2Sum += delta2;
1215 delta2 += pow2( sigma * rel1Err );
1217 // Print individual process info.
1218 os << " | " << left << setw(40) << containerPtrs[i]->name()
1219 << right << setw(5) << containerPtrs[i]->code() << " | "
1220 << setw(11) << nTry << " " << setw(10) << nSel << " "
1221 << setw(10) << nAcc << " | " << scientific << setprecision(3)
1222 << setw(11) << sigma << setw(11) << sqrtpos(delta2) << " |\n";
1225 // Print summed info for first processes.
1226 delta2Sum += pow2( sigmaSum * rel1Err );
1229 << " | " << left << setw(45) << "sum" << right << " | " << setw(11)
1230 << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
1231 << nAccSum << " | " << scientific << setprecision(3) << setw(11)
1232 << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
1235 // Separation lines to second hard processes.
1238 << " |------------------------------------------------------------"
1239 << "------------------------------------------------|\n"
1242 << " | Second hard process: | "
1247 // Reset sum counters.
1254 // Loop over existing second processes.
1255 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
1256 if (container2Ptrs[i2]->sigmaMax() != 0.) {
1258 // Read info for process. Sum counters.
1259 long nTry = container2Ptrs[i2]->nTried();
1260 long nSel = container2Ptrs[i2]->nSelected();
1261 long nAcc = container2Ptrs[i2]->nAccepted();
1262 double sigma = container2Ptrs[i2]->sigmaMC() * factor2;
1263 double delta2 = pow2( container2Ptrs[i2]->deltaMC() * factor2 );
1268 delta2Sum += delta2;
1269 delta2 += pow2( sigma * rel2Err );
1271 // Print individual process info.
1272 os << " | " << left << setw(40) << container2Ptrs[i2]->name()
1273 << right << setw(5) << container2Ptrs[i2]->code() << " | "
1274 << setw(11) << nTry << " " << setw(10) << nSel << " "
1275 << setw(10) << nAcc << " | " << scientific << setprecision(3)
1276 << setw(11) << sigma << setw(11) << sqrtpos(delta2) << " |\n";
1279 // Print summed info for second processes.
1280 delta2Sum += pow2( sigmaSum * rel2Err );
1283 << " | " << left << setw(45) << "sum" << right << " | " << setw(11)
1284 << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
1285 << nAccSum << " | " << scientific << setprecision(3) << setw(11)
1286 << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
1288 // Print information on how the two processes were combined.
1291 << " |------------------------------------------------------------"
1292 << "------------------------------------------------|\n"
1295 << " | Uncombined cross sections for the two event sets were "
1296 << setw(10) << sigma1SelSum << " and " << sigma2SelSum << " mb, "
1297 << "respectively, combined |\n"
1298 << " | using a sigma(nonDiffractive) of " << setw(10) << sigmaND
1299 << " mb and an impact-parameter enhancement factor of "
1300 << setw(10) << impactFac << ". |\n";
1302 // Listing finished.
1305 << " *------- End PYTHIA Event and Cross Section Statistics -----"
1306 << "------------------------------------------------*" << endl;
1308 // Optionally reset statistics contants.
1310 for (int i = 0; i < int(containerPtrs.size()); ++i)
1311 containerPtrs[i]->reset();
1312 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
1313 container2Ptrs[i2]->reset();
1318 //==========================================================================
1320 } // end namespace Pythia8