1 // ProcessLevel.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2008 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.
20 ProcessLevel::~ProcessLevel() {
22 // Run through list of first hard processes and delete them.
23 for (int i = 0; i < int(containerPtrs.size()); ++i)
24 delete containerPtrs[i];
26 // Run through list of second hard processes and delete them.
27 for (int i =0; i < int(container2Ptrs.size()); ++i)
28 delete container2Ptrs[i];
34 // Main routine to initialize generation process.
36 bool ProcessLevel::init( Info* infoPtrIn, BeamParticle* beamAPtrIn,
37 BeamParticle* beamBPtrIn, SigmaTotal* sigmaTotPtrIn, bool doLHA,
38 SusyLesHouches* slhaPtrIn, UserHooks* userHooksPtrIn,
39 vector<SigmaProcess*>& sigmaPtrs, ostream& os) {
41 // Store input pointers for future use.
43 beamAPtr = beamAPtrIn;
44 beamBPtr = beamBPtrIn;
45 sigmaTotPtr = sigmaTotPtrIn;
46 userHooksPtr = userHooksPtrIn;
49 // Send on some input pointers.
50 resonanceDecays.init( infoPtr);
52 // Options to allow second hard interaction and resonance decays.
53 doSecondHard = Settings::flag("SecondHard:generate");
54 doResDecays = Settings::flag("ProcessLevel:resonanceDecays");
56 // Set up SigmaTotal. Store sigma_nondiffractive for future use.
57 sigmaTotPtr->init( infoPtr);
58 int idA = infoPtr->idA();
59 int idB = infoPtr->idB();
60 double eCM = infoPtr->eCM();
61 sigmaTotPtr->calc( idA, idB, eCM);
62 sigmaND = sigmaTotPtr->sigmaND();
64 // Initialize SUSY Les Houches Accord data
65 if (!initSLHA()) return false;
67 // Set up containers for all the internal hard processes.
68 SetupContainers setupContainers;
69 setupContainers.init(containerPtrs);
71 // Append containers for external hard processes, if any.
72 if (sigmaPtrs.size() > 0) {
73 for (int iSig = 0; iSig < int(sigmaPtrs.size()); ++iSig)
74 containerPtrs.push_back( new ProcessContainer(sigmaPtrs[iSig]) );
77 // Append single container for Les Houches processes, if any.
79 SigmaProcess* sigmaPtr = new SigmaLHAProcess();
80 containerPtrs.push_back( new ProcessContainer(sigmaPtr) );
82 // Store location of this container, and send in LHA pointer.
83 iLHACont = containerPtrs.size() - 1;
84 containerPtrs[iLHACont]->setLHAPtr(lhaUpPtr);
87 // If no processes found then refuse to do anything.
88 if ( int(containerPtrs.size()) == 0) {
89 infoPtr->errorMsg("Error in ProcessLevel::init: "
90 "no process switched on");
94 // Initialize alphaStrong generation for SigmaProcess.
95 double alphaSvalue = Settings::parm("SigmaProcess:alphaSvalue");
96 int alphaSorder = Settings::mode("SigmaProcess:alphaSorder");
97 alphaS.init( alphaSvalue, alphaSorder);
99 // Initialize alphaEM generation for SigmaProcess.
100 int alphaEMorder = Settings::mode("SigmaProcess:alphaEMorder");
101 alphaEM.init( alphaEMorder);
103 // Initialize each process.
105 for (int i = 0; i < int(containerPtrs.size()); ++i)
106 if (containerPtrs[i]->init(infoPtr, beamAPtr, beamBPtr, &alphaS,
107 &alphaEM, sigmaTotPtr, &resonanceDecays, slhaPtr, userHooksPtr))
110 // Sum maxima for Monte Carlo choice.
112 for (int i = 0; i < int(containerPtrs.size()); ++i)
113 sigmaMaxSum += containerPtrs[i]->sigmaMax();
115 // Option to pick a second hard interaction: repeat as above.
118 setupContainers.init2(container2Ptrs);
119 if ( int(container2Ptrs.size()) == 0) {
120 infoPtr->errorMsg("Error in ProcessLevel::init: "
121 "no second hard process switched on");
124 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
125 if (container2Ptrs[i2]->init(infoPtr, beamAPtr, beamBPtr, &alphaS,
126 &alphaEM, sigmaTotPtr, &resonanceDecays, slhaPtr, userHooksPtr))
129 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
130 sigma2MaxSum += container2Ptrs[i2]->sigmaMax();
133 // Construct string with incoming beams and for cm energy.
134 string collision = "We collide " + ParticleDataTable::name(idA)
135 + " with " + ParticleDataTable::name(idB) + " at a CM energy of ";
136 string pad( 51 - collision.length(), ' ');
138 // Print initialization information: header.
139 os << "\n *------- PYTHIA Process Initialization ---------"
140 << "-----------------*\n"
143 << " | " << collision << scientific << setprecision(3)<< setw(9) << eCM
144 << " GeV" << pad << " |\n"
147 << " |---------------------------------------------------"
148 << "---------------|\n"
151 << " | Subprocess Code"
152 << " | Estimated |\n"
157 << " |---------------------------------------------------"
158 << "---------------|\n"
163 // Loop over existing processes: print individual process info.
164 for (int i = 0; i < int(containerPtrs.size()); ++i)
165 os << " | " << left << setw(45) << containerPtrs[i]->name()
166 << right << setw(5) << containerPtrs[i]->code() << " | "
167 << scientific << setprecision(3) << setw(11)
168 << containerPtrs[i]->sigmaMax() << " |\n";
170 // Loop over second hard processes, if any, and repeat as above.
174 << " |---------------------------------------------------"
175 <<"---------------|\n"
178 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
179 os << " | " << left << setw(45) << container2Ptrs[i2]->name()
180 << right << setw(5) << container2Ptrs[i2]->code() << " | "
181 << scientific << setprecision(3) << setw(11)
182 << container2Ptrs[i2]->sigmaMax() << " |\n";
188 << " *------- End PYTHIA Process Initialization ----------"
189 <<"-------------*" << endl;
191 // If sum of maxima vanishes then refuse to do anything.
192 if ( numberOn == 0 || sigmaMaxSum <= 0.) {
193 infoPtr->errorMsg("Error in ProcessLevel::init: "
194 "all processes have vanishing cross sections");
197 if ( doSecondHard && (number2On == 0 || sigma2MaxSum <= 0.) ) {
198 infoPtr->errorMsg("Error in ProcessLevel::init: "
199 "all second hard processes have vanishing cross sections");
203 // If two hard processes then check whether some (but not all) agree.
207 bool foundMatch = false;
209 // Check for each first process if matched in second.
210 for (int i = 0; i < int(containerPtrs.size()); ++i) {
212 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
213 if (container2Ptrs[i2]->code() == containerPtrs[i]->code())
215 containerPtrs[i]->isSame( foundMatch );
216 if (!foundMatch) allHardSame = false;
217 if ( foundMatch) noneHardSame = false;
220 // Check for each second process if matched in first.
221 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
223 for (int i = 0; i < int(containerPtrs.size()); ++i)
224 if (containerPtrs[i]->code() == container2Ptrs[i2]->code())
226 container2Ptrs[i2]->isSame( foundMatch );
227 if (!foundMatch) allHardSame = false;
228 if ( foundMatch) noneHardSame = false;
231 someHardSame = !allHardSame && !noneHardSame;
233 // Reset counters for average impact-parameter enhancement.
238 // Statistics for LHA events.
248 // Main routine to generate the hard process.
250 bool ProcessLevel::next( Event& process) {
252 // Generate the next event with two or one hard interactions.
253 bool physical = (doSecondHard) ? nextTwo( process) : nextOne( process);
255 // Check that colour assignments make sense.
256 if (physical) physical = checkColours( process);
264 // Accumulate and update statistics (after possible user veto).
266 void ProcessLevel::accumulate() {
268 // Increase number of accepted events.
269 containerPtrs[iContainer]->accumulate();
271 // Provide current generated cross section estimate.
275 double sigmaSum = 0.;
276 double delta2Sum = 0.;
277 double sigSelSum = 0.;
278 for (int i = 0; i < int(containerPtrs.size()); ++i)
279 if (containerPtrs[i]->sigmaMax() != 0.) {
280 nTrySum += containerPtrs[i]->nTried();
281 nSelSum += containerPtrs[i]->nSelected();
282 nAccSum += containerPtrs[i]->nAccepted();
283 sigmaSum += containerPtrs[i]->sigmaMC();
284 delta2Sum += pow2(containerPtrs[i]->deltaMC());
285 sigSelSum += containerPtrs[i]->sigmaSelMC();
288 // For Les Houches events find subprocess type and update counter.
289 if (infoPtr->isLHA()) {
290 int codeLHANow = infoPtr->codeSub();
292 for (int i = 0; i < int(codeLHA.size()); ++i)
293 if (codeLHANow == codeLHA[i]) iFill = i;
294 if (iFill >= 0) ++nEvtLHA[iFill];
296 // Add new process when new code and then arrange in order.
298 codeLHA.push_back(codeLHANow);
299 nEvtLHA.push_back(1);
300 for (int i = int(codeLHA.size()) - 1; i > 0; --i) {
301 if (codeLHA[i] < codeLHA[i - 1]) {
302 swap(codeLHA[i], codeLHA[i - 1]);
303 swap(nEvtLHA[i], nEvtLHA[i - 1]);
310 // Normally only one hard interaction. Then store info and done.
312 double deltaSum = sqrtpos(delta2Sum);
313 infoPtr->setSigma( nTrySum, nSelSum, nAccSum, sigmaSum, deltaSum);
317 // Increase counter for a second hard interaction.
318 container2Ptrs[i2Container]->accumulate();
320 // Update statistics on average impact factor.
322 sumImpactFac += infoPtr->enhanceMI();
323 sum2ImpactFac += pow2(infoPtr->enhanceMI());
325 // Cross section estimate for second hard process.
326 double sigma2Sum = 0.;
327 double sig2SelSum = 0.;
328 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
329 if (container2Ptrs[i2]->sigmaMax() != 0.) {
330 nTrySum += container2Ptrs[i2]->nTried();
331 sigma2Sum += container2Ptrs[i2]->sigmaMC();
332 sig2SelSum += container2Ptrs[i2]->sigmaSelMC();
335 // Average impact-parameter factor and error.
336 double invN = 1. / max(1, nImpact);
337 double impactFac = max( 1., sumImpactFac * invN);
338 double impactErr2 = ( sum2ImpactFac * invN / pow2(impactFac) - 1.) * invN;
340 // Cross section estimate for combination of first and second process.
341 // Combine two possible ways and take average.
342 double sigmaComb = 0.5 * (sigmaSum * sig2SelSum + sigSelSum * sigma2Sum);
343 sigmaComb *= impactFac / sigmaND;
344 if (allHardSame) sigmaComb *= 0.5;
345 double deltaComb = sqrtpos(2. / nAccSum + impactErr2) * sigmaComb;
347 // Store info and done.
348 infoPtr->setSigma( nTrySum, nSelSum, nAccSum, sigmaComb, deltaComb);
354 // Print statistics on cross sections and number of events.
356 void ProcessLevel::statistics(bool reset, ostream& os) {
358 // Special processing if two hard interactions selected.
360 statistics2(reset, os);
365 os << "\n *------- PYTHIA Event and Cross Section Statistics ------"
366 << "-------------------------------------------------------*\n"
369 << " | Subprocess Code | "
370 << " Number of events | sigma +- delta |\n"
372 << "Tried Selected Accepted | (estimated) (mb) |\n"
375 << " |------------------------------------------------------------"
376 << "-----------------------------------------------------|\n"
380 // Reset sum counters.
384 double sigmaSum = 0.;
385 double delta2Sum = 0.;
387 // Loop over existing processes.
388 for (int i = 0; i < int(containerPtrs.size()); ++i)
389 if (containerPtrs[i]->sigmaMax() != 0.) {
391 // Read info for process. Sum counters.
392 long nTry = containerPtrs[i]->nTried();
393 long nSel = containerPtrs[i]->nSelected();
394 long nAcc = containerPtrs[i]->nAccepted();
395 double sigma = containerPtrs[i]->sigmaMC();
396 double delta = containerPtrs[i]->deltaMC();
401 delta2Sum += pow2(delta);
403 // Print individual process info.
404 os << " | " << left << setw(45) << containerPtrs[i]->name()
405 << right << setw(5) << containerPtrs[i]->code() << " | "
406 << setw(11) << nTry << " " << setw(10) << nSel << " "
407 << setw(10) << nAcc << " | " << scientific << setprecision(3)
408 << setw(11) << sigma << setw(11) << delta << " |\n";
410 // Print subdivision by user code for Les Houches process.
411 if (containerPtrs[i]->code() == 9999)
412 for (int j = 0; j < int(codeLHA.size()); ++j)
413 os << " | ... whereof user classification code " << setw(10)
414 << codeLHA[j] << " | " << setw(10)
415 << nEvtLHA[j] << " | | \n";
418 // Print summed process info.
421 << " | " << left << setw(50) << "sum" << right << " | " << setw(11)
422 << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
423 << nAccSum << " | " << scientific << setprecision(3) << setw(11)
424 << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
429 << " *------- End PYTHIA Event and Cross Section Statistics -----"
430 << "-----------------------------------------------------*" << endl;
432 // Optionally reset statistics contants.
433 if (reset) for (int i = 0; i < int(containerPtrs.size()); ++i)
434 containerPtrs[i]->reset();
440 // Initialize SUSY Les Houches Accord data.
442 bool ProcessLevel::initSLHA() {
444 // Check whether SUSY is on.
445 if ( !Settings::flag("SUSY") ) return true;
447 // Read SUSY Les Houches Accord File.
448 string slhaFile = Settings::word("SUSY:SusyLesHouchesFile");
449 int ifail = slhaPtr->readFile(slhaFile);
451 // In case of problems, print error and fail init.
453 infoPtr->errorMsg("Error from Pythia::initSLHA: "
454 "problem reading SLHA file", slhaFile);
458 // Update particle data.
459 int id = slhaPtr->mass.first();
460 for (int i = 1; i <= slhaPtr->mass.size() ; i++) {
461 double mass = abs(slhaPtr->mass(id));
462 ParticleDataTable::m0(id,mass);
463 id = slhaPtr->mass.next();
466 // Check spectrum for consistency. Switch off SUSY if necessary.
467 ifail = slhaPtr->checkSpectrum();
469 infoPtr->errorMsg("Warning from Pythia::initSLHA: "
470 "Problem with SLHA spectrum.",
471 "\n Only using masses and switching off SUSY.");
472 Settings::flag("SUSY", false);
473 slhaPtr->printSpectrum();
477 // Print spectrum. Done.
478 slhaPtr->printSpectrum();
485 // Generate the next event with one interaction.
487 bool ProcessLevel::nextOne( Event& process) {
489 // Update CM energy for phase space selection.
490 double eCM = infoPtr->eCM();
491 for (int i = 0; i < int(containerPtrs.size()); ++i)
492 containerPtrs[i]->newECM(eCM);
494 // Loop over tries until trial event succeeds.
497 // Pick one of the subprocesses.
498 double sigmaMaxNow = sigmaMaxSum * Rndm::flat();
499 int iMax = containerPtrs.size() - 1;
501 do sigmaMaxNow -= containerPtrs[++iContainer]->sigmaMax();
502 while (sigmaMaxNow > 0. && iContainer < iMax);
504 // Do a trial event of this subprocess; accept or not.
505 if (containerPtrs[iContainer]->trialProcess()) break;
507 // Check for end-of-file condition for Les Houches events.
508 if (infoPtr->atEndOfFile()) return false;
511 // Update sum of maxima if current maximum violated.
512 if (containerPtrs[iContainer]->newSigmaMax()) {
514 for (int i = 0; i < int(containerPtrs.size()); ++i)
515 sigmaMaxSum += containerPtrs[i]->sigmaMax();
518 // Construct kinematics of acceptable process.
519 if ( !containerPtrs[iContainer]->constructProcess( process) ) return false;
521 // Do all resonance decays.
522 if ( doResDecays && !containerPtrs[iContainer]->decayResonances(
523 process) ) return false;
525 // Add any junctions to the process event record list.
526 findJunctions( process);
534 // Generate the next event with two hard interactions.
536 bool ProcessLevel::nextTwo( Event& process) {
538 // Update CM energy for phase space selection.
539 double eCM = infoPtr->eCM();
540 for (int i = 0; i < int(containerPtrs.size()); ++i)
541 containerPtrs[i]->newECM(eCM);
542 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
543 container2Ptrs[i2]->newECM(eCM);
545 // Loop over both hard processes to find consistent common kinematics.
548 // Loop internally over tries for hardest process until succeeds.
551 // Pick one of the subprocesses.
552 double sigmaMaxNow = sigmaMaxSum * Rndm::flat();
553 int iMax = containerPtrs.size() - 1;
555 do sigmaMaxNow -= containerPtrs[++iContainer]->sigmaMax();
556 while (sigmaMaxNow > 0. && iContainer < iMax);
558 // Do a trial event of this subprocess; accept or not.
559 if (containerPtrs[iContainer]->trialProcess()) break;
561 // Check for end-of-file condition for Les Houches events.
562 if (infoPtr->atEndOfFile()) return false;
565 // Update sum of maxima if current maximum violated.
566 if (containerPtrs[iContainer]->newSigmaMax()) {
568 for (int i = 0; i < int(containerPtrs.size()); ++i)
569 sigmaMaxSum += containerPtrs[i]->sigmaMax();
572 // Loop internally over tries for second hardest process until succeeds.
575 // Pick one of the subprocesses.
576 double sigma2MaxNow = sigma2MaxSum * Rndm::flat();
577 int i2Max = container2Ptrs.size() - 1;
579 do sigma2MaxNow -= container2Ptrs[++i2Container]->sigmaMax();
580 while (sigma2MaxNow > 0. && i2Container < i2Max);
582 // Do a trial event of this subprocess; accept or not.
583 if (container2Ptrs[i2Container]->trialProcess()) break;
586 // Update sum of maxima if current maximum violated.
587 if (container2Ptrs[i2Container]->newSigmaMax()) {
589 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
590 sigma2MaxSum += container2Ptrs[i2]->sigmaMax();
593 // Check whether common set of x values is kinematically possible.
594 double xA1 = containerPtrs[iContainer]->x1();
595 double xB1 = containerPtrs[iContainer]->x2();
596 double xA2 = container2Ptrs[i2Container]->x1();
597 double xB2 = container2Ptrs[i2Container]->x2();
598 if (xA1 + xA2 >= 1. || xB1 + xB2 >= 1.) continue;
600 // Reset beam contents. Naive parton densities for second interaction.
601 // (Subsequent procedure could be symmetrized, but would be overkill.)
604 int idA1 = containerPtrs[iContainer]->id1();
605 int idB1 = containerPtrs[iContainer]->id2();
606 int idA2 = container2Ptrs[i2Container]->id1();
607 int idB2 = container2Ptrs[i2Container]->id2();
608 double Q2Fac1 = containerPtrs[iContainer]->Q2Fac();
609 double Q2Fac2 = container2Ptrs[i2Container]->Q2Fac();
610 double pdfA2Raw = beamAPtr->xf( idA2, xA2,Q2Fac2);
611 double pdfB2Raw = beamBPtr->xf( idB2, xB2,Q2Fac2);
613 // Remove partons in first interaction from beams.
614 beamAPtr->append( 3, idA1, xA1);
615 beamAPtr->xfISR( 0, idA1, xA1, Q2Fac1);
616 beamAPtr->pickValSeaComp();
617 beamBPtr->append( 4, idB1, xB1);
618 beamBPtr->xfISR( 0, idB1, xB1, Q2Fac1);
619 beamBPtr->pickValSeaComp();
621 // Reevaluate pdf's for second interaction and weight by reduction.
622 double pdfA2Mod = beamAPtr->xfMI( idA2, xA2,Q2Fac2);
623 double pdfB2Mod = beamBPtr->xfMI( idB2, xB2,Q2Fac2);
624 double wtPdfMod = (pdfA2Mod * pdfB2Mod) / (pdfA2Raw * pdfB2Raw);
625 if (wtPdfMod < Rndm::flat()) continue;
627 // Reduce by a factor of 2 for identical processes when others not.
628 if ( someHardSame && containerPtrs[iContainer]->isSame()
629 && container2Ptrs[i2Container]->isSame() && Rndm::flat() > 0.5)
632 // If come this far then acceptable event.
636 // Construct kinematics of acceptable processes.
638 process2.initColTag();
639 startColTag2 = process2.lastColTag();
640 if ( !containerPtrs[iContainer]->constructProcess( process) ) return false;
641 if ( !container2Ptrs[i2Container]->constructProcess( process2, false) )
644 // Do all resonance decays.
645 if ( doResDecays && !containerPtrs[iContainer]->decayResonances(
646 process) ) return false;
647 if ( doResDecays && !container2Ptrs[i2Container]->decayResonances(
648 process2) ) return false;
650 // Append second hard interaction to normal process object.
651 combineProcessRecords( process, process2);
653 // Add any junctions to the process event record list.
654 findJunctions( process);
662 // Append second hard interaction to normal process object.
663 // Complication: all resonance decay chains must be put at the end.
665 void ProcessLevel::combineProcessRecords( Event& process, Event& process2) {
667 // Find first event record size, excluding resonances.
668 int nSize = process.size();
670 while (nHard < nSize && process[nHard].mother1() == 3) ++nHard;
672 // Save resonance products temporarily elsewhere.
673 vector<Particle> resProd;
675 for (int i = nHard; i < nSize; ++i) resProd.push_back( process[i] );
676 process.popBack(nSize - nHard);
679 // Find second event record size, excluding resonances.
680 int nSize2 = process2.size();
682 while (nHard2 < nSize2 && process2[nHard2].mother1() == 3) ++nHard2;
684 // Find amount of necessary position and colour offset for second process.
685 int addPos = nHard - 3;
686 int addCol = process.lastColTag() - startColTag2;
688 // Loop over all particles (except beams) from second process.
689 for (int i = 3; i < nSize2; ++i) {
691 // Offset mother and daughter pointers and colour tags of particle.
692 process2[i].offsetHistory( 2, addPos, 2, addPos);
693 process2[i].offsetCol( addCol);
695 // Append hard-process particles from process2 to process.
696 if (i < nHard2) process.append( process2[i] );
699 // Reinsert resonance decay chains of first hard process.
700 int addPos2 = nHard2 - 3;
703 // Offset daughter pointers of unmoved mothers.
704 for (int i = 5; i < nHard; ++i)
705 process[i].offsetHistory( 0, 0, nHard - 1, addPos2);
707 // Modify history of resonance products when restoring.
708 for (int i = 0; i < int(resProd.size()); ++i) {
709 resProd[i].offsetHistory( nHard - 1, addPos2, nHard - 1, addPos2);
710 process.append( resProd[i] );
714 // Insert resonance decay chains of second hard process.
715 if (nHard2 < nSize2) {
716 int nHard3 = nHard + nHard2 - 3;
717 int addPos3 = nSize - nHard;
719 // Offset daughter pointers of second-process mothers.
720 for (int i = nHard + 2; i < nHard3; ++i)
721 process[i].offsetHistory( 0, 0, nHard3 - 1, addPos3);
723 // Modify history of second-process resonance products and insert.
724 for (int i = nHard2; i < nSize2; ++i) {
725 process2[i].offsetHistory( nHard3 - 1, addPos3, nHard3 - 1, addPos3);
726 process.append( process2[i] );
730 // Store PDF scale for second interaction.
731 process.scaleSecond( process2.scale() );
737 // Add any junctions to the process event record list.
738 // First try, so still incomplete. ??
739 // Also check that do not doublebook if called repeatedly.
741 void ProcessLevel::findJunctions( Event& junEvent) {
743 // Loop though event; isolate all uncoloured particles.
744 for (int i = 0; i < junEvent.size(); ++i)
745 if ( junEvent[i].col() == 0 && junEvent[i].acol() == 0) {
747 // Find all daughters and store daughter colours and anticolours.
748 vector<int> daughters = junEvent.daughterList(i);
749 vector<int> cols, acols;
750 for (int j = 0; j < int(daughters.size()); ++j) {
751 int colDau = junEvent[ daughters[j] ].col();
752 int acolDau = junEvent[ daughters[j] ].acol();
753 if (colDau > 0) cols.push_back( colDau);
754 if (acolDau > 0) acols.push_back( acolDau);
757 // Remove all matching colour-anticolour pairs.
758 bool foundPair = true;
759 while (foundPair && cols.size() > 0 && acols.size() > 0) {
761 for (int j = 0; j < int(cols.size()); ++j) {
762 for (int k = 0; k < int(acols.size()); ++k) {
763 if (acols[k] == cols[j]) {
764 cols[j] = cols.back();
766 acols[k] = acols.back();
771 } if (foundPair) break;
775 // Store an (anti)junction when three (anti)coloured daughters.
776 if (cols.size() == 3 && acols.size() == 0)
777 junEvent.appendJunction( 1, cols[0], cols[1], cols[2]);
778 if (acols.size() == 3 && cols.size() == 0)
779 junEvent.appendJunction( 2, acols[0], acols[1], acols[2]);
787 // Check that colours match up.
789 bool ProcessLevel::checkColours( Event& process) {
791 // Variables and arrays for common usage.
792 bool physical = true;
794 int colType, col, acol, iPos, iNow, iNowA;
795 vector<int> colTags, colPos, acolPos;
797 // Check that each particle has the kind of colours expected of it.
798 for (int i = 0; i < process.size(); ++i) {
799 colType = process[i].colType();
800 col = process[i].col();
801 acol = process[i].acol();
802 if (colType == 0 && (col != 0 || acol != 0)) physical = false;
803 else if (colType == 1 && (col <= 0 || acol != 0)) physical = false;
804 else if (colType == -1 && (col != 0 || acol <= 0)) physical = false;
805 else if (colType == 2 && (col <= 0 || acol <= 0)) physical = false;
806 else if (colType < -1 || colType > 2) physical = false;
808 // Add to the list of colour tags.
811 for (int ic = 0; ic < int(colTags.size()) ; ++ic)
812 if (col == colTags[ic]) match = true;
813 if (!match) colTags.push_back(col);
814 } else if (acol > 0) {
816 for (int ic = 0; ic < int(colTags.size()) ; ++ic)
817 if (acol == colTags[ic]) match = true;
818 if (!match) colTags.push_back(acol);
822 // Warn and give up if particles did not have the expected colours.
824 infoPtr->errorMsg("Error in ProcessLevel::checkColours: "
825 "incorrect colour assignment");
829 // Loop through all colour tags and find their positions (by sign).
830 for (int ic = 0; ic < int(colTags.size()); ++ic) {
834 for (int i = 0; i < process.size(); ++i) {
835 if (process[i].col() == col) colPos.push_back(i);
836 if (process[i].acol() == col) acolPos.push_back(i);
839 // Trace colours back through decays; remove daughters.
840 while (colPos.size() > 1) {
841 iPos = colPos.size() - 1;
843 if ( process[iNow].mother1() == colPos[iPos - 1]
844 && process[iNow].mother2() == 0) colPos.pop_back();
847 while (acolPos.size() > 1) {
848 iPos = acolPos.size() - 1;
849 iNow = acolPos[iPos];
850 if ( process[iNow].mother1() == acolPos[iPos - 1]
851 && process[iNow].mother2() == 0) acolPos.pop_back();
855 // Now colour should exist in only 2 copies.
856 if (colPos.size() + acolPos.size() != 2) physical = false;
858 // If both colours or both anticolours then one mother of the other.
859 else if (colPos.size() == 2) {
861 if ( process[iNow].mother1() != colPos[0]
862 && process[iNow].mother2() != colPos[0] ) physical = false;
864 else if (acolPos.size() == 2) {
866 if ( process[iNowA].mother1() != acolPos[0]
867 && process[iNowA].mother2() != acolPos[0] ) physical = false;
870 // If one of each then should have same mother(s), or point to beams.
874 if ( process[iNow].status() == -21 && process[iNowA].status() == -21 );
875 else if ( (process[iNow].mother1() != process[iNowA].mother1())
876 || (process[iNow].mother2() != process[iNowA].mother2()) )
882 // Error message if problem found. Done.
883 if (!physical) infoPtr->errorMsg("Error in ProcessLevel::checkColours: "
884 "unphysical colour flow");
891 // Print statistics when two hard processes allowed.
893 void ProcessLevel::statistics2(bool reset, ostream& os) {
895 // Average impact-parameter factor and error.
896 double invN = 1. / max(1, nImpact);
897 double impactFac = max( 1., sumImpactFac * invN);
898 double impactErr2 = ( sum2ImpactFac * invN / pow2(impactFac) - 1.) * invN;
900 // Derive scaling factor to be applied to first set of processes.
901 double sigma2SelSum = 0.;
903 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
904 sigma2SelSum += container2Ptrs[i2]->sigmaSelMC();
905 n2SelSum += container2Ptrs[i2]->nSelected();
907 double factor1 = impactFac * sigma2SelSum / sigmaND;
908 double rel1Err = sqrt(1. / max(1, n2SelSum) + impactErr2);
909 if (allHardSame) factor1 *= 0.5;
911 // Derive scaling factor to be applied to second set of processes.
912 double sigma1SelSum = 0.;
914 for (int i = 0; i < int(containerPtrs.size()); ++i) {
915 sigma1SelSum += containerPtrs[i]->sigmaSelMC();
916 n1SelSum += containerPtrs[i]->nSelected();
918 double factor2 = impactFac * sigma1SelSum / sigmaND;
919 if (allHardSame) factor2 *= 0.5;
920 double rel2Err = sqrt(1. / max(1, n1SelSum) + impactErr2);
923 os << "\n *------- PYTHIA Event and Cross Section Statistics ------"
924 << "--------------------------------------------------*\n"
927 << " | Subprocess Code | "
928 << "Number of events | sigma +- delta |\n"
930 << " Selected Accepted | (estimated) (mb) |\n"
933 << " |------------------------------------------------------------"
934 << "------------------------------------------------|\n"
937 << " | First hard process: | "
942 // Reset sum counters.
946 double sigmaSum = 0.;
947 double delta2Sum = 0.;
949 // Loop over existing first processes.
950 for (int i = 0; i < int(containerPtrs.size()); ++i)
951 if (containerPtrs[i]->sigmaMax() != 0.) {
953 // Read info for process. Sum counters.
954 long nTry = containerPtrs[i]->nTried();
955 long nSel = containerPtrs[i]->nSelected();
956 long nAcc = containerPtrs[i]->nAccepted();
957 double sigma = containerPtrs[i]->sigmaMC() * factor1;
958 double delta2 = pow2( containerPtrs[i]->deltaMC() * factor1 );
964 delta2 += pow2( sigma * rel1Err );
966 // Print individual process info.
967 os << " | " << left << setw(40) << containerPtrs[i]->name()
968 << right << setw(5) << containerPtrs[i]->code() << " | "
969 << setw(11) << nTry << " " << setw(10) << nSel << " "
970 << setw(10) << nAcc << " | " << scientific << setprecision(3)
971 << setw(11) << sigma << setw(11) << sqrtpos(delta2) << " |\n";
974 // Print summed info for first processes.
975 delta2Sum += pow2( sigmaSum * rel1Err );
978 << " | " << left << setw(45) << "sum" << right << " | " << setw(11)
979 << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
980 << nAccSum << " | " << scientific << setprecision(3) << setw(11)
981 << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
984 // Separation lines to second hard processes.
987 << " |------------------------------------------------------------"
988 << "------------------------------------------------|\n"
991 << " | Second hard process: | "
996 // Reset sum counters.
1003 // Loop over existing second processes.
1004 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
1005 if (container2Ptrs[i2]->sigmaMax() != 0.) {
1007 // Read info for process. Sum counters.
1008 long nTry = container2Ptrs[i2]->nTried();
1009 long nSel = container2Ptrs[i2]->nSelected();
1010 long nAcc = container2Ptrs[i2]->nAccepted();
1011 double sigma = container2Ptrs[i2]->sigmaMC() * factor2;
1012 double delta2 = pow2( container2Ptrs[i2]->deltaMC() * factor2 );
1017 delta2Sum += delta2;
1018 delta2 += pow2( sigma * rel2Err );
1020 // Print individual process info.
1021 os << " | " << left << setw(40) << container2Ptrs[i2]->name()
1022 << right << setw(5) << container2Ptrs[i2]->code() << " | "
1023 << setw(11) << nTry << " " << setw(10) << nSel << " "
1024 << setw(10) << nAcc << " | " << scientific << setprecision(3)
1025 << setw(11) << sigma << setw(11) << sqrtpos(delta2) << " |\n";
1028 // Print summed info for second processes.
1029 delta2Sum += pow2( sigmaSum * rel2Err );
1032 << " | " << left << setw(45) << "sum" << right << " | " << setw(11)
1033 << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
1034 << nAccSum << " | " << scientific << setprecision(3) << setw(11)
1035 << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
1037 // Print information on how the two processes were combined.
1040 << " |------------------------------------------------------------"
1041 << "------------------------------------------------|\n"
1044 << " | Uncombined cross sections for the two event sets were "
1045 << setw(10) << sigma1SelSum << " and " << sigma2SelSum << " mb, "
1046 << "respectively, combined |\n"
1047 << " | using a sigma(nonDiffractive) of " << setw(10) << sigmaND
1048 << " mb and an impact-parameter enhancement factor of "
1049 << setw(10) << impactFac << ". |\n";
1051 // Listing finished.
1054 << " *------- End PYTHIA Event and Cross Section Statistics -----"
1055 << "------------------------------------------------*" << endl;
1057 // Optionally reset statistics contants.
1059 for (int i = 0; i < int(containerPtrs.size()); ++i)
1060 containerPtrs[i]->reset();
1061 for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
1062 container2Ptrs[i2]->reset();
1067 //**************************************************************************
1069 } // end namespace Pythia8