8 #include "Pythia8/ProcessLevel.h"
22 const int ProcessLevel::MAXLOOP = 5;
28 ProcessLevel::~ProcessLevel() {
31 for (
int i = 0; i < int(containerPtrs.size()); ++i)
32 delete containerPtrs[i];
35 for (
int i = 0; i < int(container2Ptrs.size()); ++i)
36 delete container2Ptrs[i];
44 bool ProcessLevel::init( Info* infoPtrIn, Settings& settings,
45 ParticleData* particleDataPtrIn, Rndm* rndmPtrIn,
46 BeamParticle* beamAPtrIn, BeamParticle* beamBPtrIn,
47 Couplings* couplingsPtrIn, SigmaTotal* sigmaTotPtrIn,
bool doLHA,
48 SLHAinterface* slhaInterfacePtrIn, UserHooks* userHooksPtrIn,
49 vector<SigmaProcess*>& sigmaPtrs, ostream& os) {
53 particleDataPtr = particleDataPtrIn;
55 beamAPtr = beamAPtrIn;
56 beamBPtr = beamBPtrIn;
57 couplingsPtr = couplingsPtrIn;
58 sigmaTotPtr = sigmaTotPtrIn;
59 userHooksPtr = userHooksPtrIn;
60 slhaInterfacePtr = slhaInterfacePtrIn;
63 resonanceDecays.init( infoPtr, particleDataPtr, rndmPtr);
66 sigmaTotPtr->init( infoPtr, settings, particleDataPtr);
67 int idA = infoPtr->idA();
68 int idB = infoPtr->idB();
69 double eCM = infoPtr->eCM();
70 sigmaTotPtr->calc( idA, idB, eCM);
71 sigmaND = sigmaTotPtr->sigmaND();
74 doSecondHard = settings.flag(
"SecondHard:generate");
75 doSameCuts = settings.flag(
"PhaseSpace:sameForSecond");
76 doResDecays = settings.flag(
"ProcessLevel:resonanceDecays");
77 startColTag = settings.mode(
"Event:startColTag");
80 if (doSecondHard && userHooksPtr != 0
81 && userHooksPtr->canBiasSelection()) {
82 infoPtr->errorMsg(
"Error in ProcessLevel::init: "
83 "cannot combine second interaction with biased phase space");
88 mHatMin1 = settings.parm(
"PhaseSpace:mHatMin");
89 mHatMax1 = settings.parm(
"PhaseSpace:mHatMax");
90 if (mHatMax1 < mHatMin1) mHatMax1 = eCM;
91 pTHatMin1 = settings.parm(
"PhaseSpace:pTHatMin");
92 pTHatMax1 = settings.parm(
"PhaseSpace:pTHatMax");
93 if (pTHatMax1 < pTHatMin1) pTHatMax1 = eCM;
94 mHatMin2 = settings.parm(
"PhaseSpace:mHatMinSecond");
95 mHatMax2 = settings.parm(
"PhaseSpace:mHatMaxSecond");
96 if (mHatMax2 < mHatMin2) mHatMax2 = eCM;
97 pTHatMin2 = settings.parm(
"PhaseSpace:pTHatMinSecond");
98 pTHatMax2 = settings.parm(
"PhaseSpace:pTHatMaxSecond");
99 if (pTHatMax2 < pTHatMin2) pTHatMax2 = eCM;
102 cutsAgree = doSameCuts;
103 if (mHatMin2 == mHatMin1 && mHatMax2 == mHatMax1 && pTHatMin2 == pTHatMin1
104 && pTHatMax2 == pTHatMax1) cutsAgree =
true;
105 cutsOverlap = cutsAgree;
107 bool mHatOverlap = (max( mHatMin1, mHatMin2)
108 < min( mHatMax1, mHatMax2));
109 bool pTHatOverlap = (max( pTHatMin1, pTHatMin2)
110 < min( pTHatMax1, pTHatMax2));
111 if (mHatOverlap && pTHatOverlap) cutsOverlap =
true;
115 SetupContainers setupContainers;
116 setupContainers.init(containerPtrs, infoPtr, settings, particleDataPtr,
120 if (sigmaPtrs.size() > 0) {
121 for (
int iSig = 0; iSig < int(sigmaPtrs.size()); ++iSig)
122 containerPtrs.push_back(
new ProcessContainer(sigmaPtrs[iSig],
128 SigmaProcess* sigmaPtr =
new SigmaLHAProcess();
129 containerPtrs.push_back(
new ProcessContainer(sigmaPtr) );
132 iLHACont = containerPtrs.size() - 1;
133 containerPtrs[iLHACont]->setLHAPtr(lhaUpPtr);
137 if (
int(containerPtrs.size()) == 0) {
138 infoPtr->errorMsg(
"Error in ProcessLevel::init: "
139 "no process switched on");
144 if (settings.flag(
"PhaseSpace:bias2Selection")) {
145 bool bias2Sel =
false;
146 if (sigmaPtrs.size() == 0 && !doLHA && !doSecondHard) {
148 for (
int i = 0; i < int(containerPtrs.size()); ++i) {
149 if (containerPtrs[i]->nFinal() != 2) bias2Sel =
false;
150 int code = containerPtrs[i]->code();
151 if (code > 100 && code < 110) bias2Sel =
false;
155 infoPtr->errorMsg(
"Error in ProcessLevel::init: "
156 "requested event weighting not possible");
162 bool hasSUSY =
false;
163 for (
int i = 0; i < int(containerPtrs.size()); ++i)
164 if (containerPtrs[i]->isSUSY()) hasSUSY =
true;
167 if(hasSUSY && !couplingsPtr->isSUSY) {
168 infoPtr->errorMsg(
"Error in ProcessLevel::init: "
169 "SUSY process switched on but no SUSY couplings found");
174 slhaInterfacePtr->pythia2slha(particleDataPtr);
178 for (
int i = 0; i < int(containerPtrs.size()); ++i)
179 if (containerPtrs[i]->init(
true, infoPtr, settings, particleDataPtr,
180 rndmPtr, beamAPtr, beamBPtr, couplingsPtr, sigmaTotPtr,
181 &resonanceDecays, slhaInterfacePtr, userHooksPtr)) ++numberOn;
185 for (
int i = 0; i < int(containerPtrs.size()); ++i)
186 sigmaMaxSum += containerPtrs[i]->sigmaMax();
191 setupContainers.init2(container2Ptrs, settings);
192 if (
int(container2Ptrs.size()) == 0) {
193 infoPtr->errorMsg(
"Error in ProcessLevel::init: "
194 "no second hard process switched on");
197 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
198 if (container2Ptrs[i2]->init(
false, infoPtr, settings, particleDataPtr,
199 rndmPtr, beamAPtr, beamBPtr, couplingsPtr, sigmaTotPtr,
200 &resonanceDecays, slhaInterfacePtr, userHooksPtr)) ++number2On;
202 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
203 sigma2MaxSum += container2Ptrs[i2]->sigmaMax();
207 if (settings.flag(
"Init:showProcesses")) {
210 string collision =
"We collide " + particleDataPtr->name(idA)
211 +
" with " + particleDataPtr->name(idB) +
" at a CM energy of ";
212 string pad( 51 - collision.length(),
' ');
215 os <<
"\n *------- PYTHIA Process Initialization ---------"
216 <<
"-----------------*\n"
219 <<
" | " << collision << scientific << setprecision(3)
220 << setw(9) << eCM <<
" GeV" << pad <<
" |\n"
223 <<
" |---------------------------------------------------"
224 <<
"---------------|\n"
227 <<
" | Subprocess Code"
228 <<
" | Estimated |\n"
233 <<
" |---------------------------------------------------"
234 <<
"---------------|\n"
239 map<int, double> sigmaMaxM;
240 map<int, string> nameM;
241 for (
int i = 0; i < int(containerPtrs.size()); ++i) {
242 int code = containerPtrs[i]->code();
243 nameM[code] = containerPtrs[i]->name();
244 sigmaMaxM[code] = containerPtrs[i]->sigmaMax() > sigmaMaxM[code] ?
245 containerPtrs[i]->sigmaMax() : sigmaMaxM[code];
247 for (map<int, string>::iterator i = nameM.begin(); i != nameM.end(); ++i)
248 os <<
" | " << left << setw(45) << i->second
249 << right << setw(5) << i->first <<
" | "
250 << scientific << setprecision(3) << setw(11)
251 << sigmaMaxM[i->first] <<
" |\n";
257 <<
" |---------------------------------------------------"
258 <<
"---------------|\n"
263 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
264 int code = container2Ptrs[i2]->code();
265 nameM[code] = container2Ptrs[i2]->name();
266 sigmaMaxM[code] = container2Ptrs[i2]->sigmaMax() > sigmaMaxM[code] ?
267 container2Ptrs[i2]->sigmaMax() : sigmaMaxM[code];
269 for (map<int, string>::iterator i2 = nameM.begin(); i2 != nameM.end();
271 os <<
" | " << left << setw(45) << i2->second
272 << right << setw(5) << i2->first <<
" | "
273 << scientific << setprecision(3) << setw(11)
274 << sigmaMaxM[i2->first] <<
" |\n";
280 <<
" *------- End PYTHIA Process Initialization ----------"
281 <<
"-------------*" << endl;
285 if ( numberOn == 0 || sigmaMaxSum <= 0.) {
286 infoPtr->errorMsg(
"Error in ProcessLevel::init: "
287 "all processes have vanishing cross sections");
290 if ( doSecondHard && (number2On == 0 || sigma2MaxSum <= 0.) ) {
291 infoPtr->errorMsg(
"Error in ProcessLevel::init: "
292 "all second hard processes have vanishing cross sections");
300 bool foundMatch =
false;
303 for (
int i = 0; i < int(containerPtrs.size()); ++i) {
306 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
307 if (container2Ptrs[i2]->code() == containerPtrs[i]->code())
309 containerPtrs[i]->isSame( foundMatch );
310 if (!foundMatch) allHardSame =
false;
311 if ( foundMatch) noneHardSame =
false;
315 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
318 for (
int i = 0; i < int(containerPtrs.size()); ++i)
319 if (containerPtrs[i]->code() == container2Ptrs[i2]->code())
321 container2Ptrs[i2]->isSame( foundMatch );
322 if (!foundMatch) allHardSame =
false;
323 if ( foundMatch) noneHardSame =
false;
328 if (!cutsAgree) allHardSame =
false;
329 someHardSame = !allHardSame && !noneHardSame;
344 bool ProcessLevel::next(
Event& process) {
347 bool physical = (doSecondHard) ? nextTwo( process) : nextOne( process);
350 if (physical) physical = checkColours( process);
360 bool ProcessLevel::nextLHAdec(
Event& process) {
363 infoPtr->setEndOfFile(
false);
364 if (!lhaUpPtr->setEvent()) {
365 infoPtr->setEndOfFile(
true);
370 containerLHAdec.constructDecays( process);
380 void ProcessLevel::accumulate() {
383 containerPtrs[iContainer]->accumulate();
389 double sigmaSum = 0.;
390 double delta2Sum = 0.;
391 double sigSelSum = 0.;
392 double weightSum = 0.;
394 long nTryNow, nSelNow, nAccNow;
395 double sigmaNow, deltaNow, sigSelNow, weightNow;
396 map<int, bool> duplicate;
397 for (
int i = 0; i < int(containerPtrs.size()); ++i)
398 if (containerPtrs[i]->sigmaMax() != 0.) {
399 codeNow = containerPtrs[i]->code();
400 nTryNow = containerPtrs[i]->nTried();
401 nSelNow = containerPtrs[i]->nSelected();
402 nAccNow = containerPtrs[i]->nAccepted();
403 sigmaNow = containerPtrs[i]->sigmaMC();
404 deltaNow = containerPtrs[i]->deltaMC();
405 sigSelNow = containerPtrs[i]->sigmaSelMC();
406 weightNow = containerPtrs[i]->weightSum();
410 sigmaSum += sigmaNow;
411 delta2Sum += pow2(deltaNow);
412 sigSelSum += sigSelNow;
413 weightSum += weightNow;
415 if (!duplicate[codeNow])
416 infoPtr->setSigma( codeNow, containerPtrs[i]->name(),
417 nTryNow, nSelNow, nAccNow, sigmaNow, deltaNow, weightNow);
419 infoPtr->addSigma( codeNow, nTryNow, nSelNow, nAccNow, sigmaNow,
421 duplicate[codeNow] =
true;
427 double deltaSum = sqrtpos(delta2Sum);
428 infoPtr->setSigma( 0,
"sum", nTrySum, nSelSum, nAccSum, sigmaSum, deltaSum,
434 container2Ptrs[i2Container]->accumulate();
438 sumImpactFac += infoPtr->enhanceMPI();
439 sum2ImpactFac += pow2(infoPtr->enhanceMPI());
442 double sigma2Sum = 0.;
443 double sig2SelSum = 0.;
444 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
445 if (container2Ptrs[i2]->sigmaMax() != 0.) {
446 nTrySum += container2Ptrs[i2]->nTried();
447 sigma2Sum += container2Ptrs[i2]->sigmaMC();
448 sig2SelSum += container2Ptrs[i2]->sigmaSelMC();
452 double invN = 1. / max(1, nImpact);
453 double impactFac = max( 1., sumImpactFac * invN);
454 double impactErr2 = ( sum2ImpactFac * invN / pow2(impactFac) - 1.) * invN;
458 double sigmaComb = 0.5 * (sigmaSum * sig2SelSum + sigSelSum * sigma2Sum);
459 sigmaComb *= impactFac / sigmaND;
460 if (allHardSame) sigmaComb *= 0.5;
461 double deltaComb = sqrtpos(2. / nAccSum + impactErr2) * sigmaComb;
464 infoPtr->setSigma( 0,
"sum", nTrySum, nSelSum, nAccSum, sigmaComb, deltaComb,
473 void ProcessLevel::statistics(
bool reset, ostream& os) {
477 statistics2(reset, os);
482 os <<
"\n *------- PYTHIA Event and Cross Section Statistics ------"
483 <<
"-------------------------------------------------------*\n"
486 <<
" | Subprocess Code | "
487 <<
" Number of events | sigma +- delta |\n"
489 <<
"Tried Selected Accepted | (estimated) (mb) |\n"
492 <<
" |------------------------------------------------------------"
493 <<
"-----------------------------------------------------|\n"
501 double sigmaSum = 0.;
502 double delta2Sum = 0.;
505 map<int, string> nameM;
506 map<int, long> nTryM, nSelM, nAccM;
507 map<int, double> sigmaM, delta2M;
508 vector<ProcessContainer*> lheContainerPtrs;
511 for (
int i = 0; i < int(containerPtrs.size()); ++i)
512 if (containerPtrs[i]->sigmaMax() != 0.) {
515 nTrySum += containerPtrs[i]->nTried();
516 nSelSum += containerPtrs[i]->nSelected();
517 nAccSum += containerPtrs[i]->nAccepted();
518 sigmaSum += containerPtrs[i]->sigmaMC();
519 delta2Sum += pow2(containerPtrs[i]->deltaMC());
522 if (containerPtrs[i]->code() == 9999) {
523 lheContainerPtrs.push_back(containerPtrs[i]);
528 int code = containerPtrs[i]->code();
529 nameM[code] = containerPtrs[i]->name();
530 nTryM[code] += containerPtrs[i]->nTried();
531 nSelM[code] += containerPtrs[i]->nSelected();
532 nAccM[code] += containerPtrs[i]->nAccepted();
533 sigmaM[code] += containerPtrs[i]->sigmaMC();
534 delta2M[code]+= pow2(containerPtrs[i]->deltaMC());
538 for (map<int, string>::iterator i = nameM.begin(); i != nameM.end(); ++i) {
540 os <<
" | " << left << setw(45) << i->second
541 << right << setw(5) << code <<
" | "
542 << setw(11) << nTryM[code] <<
" " << setw(10) << nSelM[code] <<
" "
543 << setw(10) << nAccM[code] <<
" | " << scientific << setprecision(3)
544 << setw(11) << sigmaM[code]
545 << setw(11) << sqrtpos(delta2M[code]) <<
" |\n";
549 for (
int i = 0; i < int(lheContainerPtrs.size()); ++i) {
550 ProcessContainer *ptr = lheContainerPtrs[i];
551 os <<
" | " << left << setw(45) << ptr->name()
552 << right << setw(5) << ptr->code() <<
" | "
553 << setw(11) << ptr->nTried() <<
" " << setw(10) << ptr->nSelected()
554 <<
" " << setw(10) << ptr->nAccepted() <<
" | " << scientific
555 << setprecision(3) << setw(11) << ptr->sigmaMC() << setw(11)
556 << ptr->deltaMC() <<
" |\n";
559 for (
int j = 0; j < ptr->codeLHASize(); ++j)
560 os <<
" | ... whereof user classification code " << setw(10)
561 << ptr->subCodeLHA(j) <<
" | " << setw(11) << ptr->nTriedLHA(j)
562 <<
" " << setw(10) << ptr->nSelectedLHA(j) <<
" " << setw(10)
563 << ptr->nAcceptedLHA(j) <<
" | | \n";
569 <<
" | " << left << setw(50) <<
"sum" << right <<
" | " << setw(11)
570 << nTrySum <<
" " << setw(10) << nSelSum <<
" " << setw(10)
571 << nAccSum <<
" | " << scientific << setprecision(3) << setw(11)
572 << sigmaSum << setw(11) << sqrtpos(delta2Sum) <<
" |\n";
577 <<
" *------- End PYTHIA Event and Cross Section Statistics -----"
578 <<
"-----------------------------------------------------*" << endl;
581 if (reset) resetStatistics();
589 void ProcessLevel::resetStatistics() {
591 for (
int i = 0; i < int(containerPtrs.size()); ++i)
592 containerPtrs[i]->reset();
594 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
595 container2Ptrs[i2]->reset();
603 bool ProcessLevel::nextOne(
Event& process) {
606 double eCM = infoPtr->eCM();
607 for (
int i = 0; i < int(containerPtrs.size()); ++i)
608 containerPtrs[i]->newECM(eCM);
611 bool physical =
true;
612 for (
int loop = 0; loop < MAXLOOP; ++loop) {
613 if (!physical) process.clear();
620 double sigmaMaxNow = sigmaMaxSum * rndmPtr->flat();
621 int iMax = containerPtrs.size() - 1;
623 do sigmaMaxNow -= containerPtrs[++iContainer]->sigmaMax();
624 while (sigmaMaxNow > 0. && iContainer < iMax);
627 if (containerPtrs[iContainer]->trialProcess())
break;
630 if (infoPtr->atEndOfFile())
return false;
634 if (containerPtrs[iContainer]->newSigmaMax()) {
636 for (
int i = 0; i < int(containerPtrs.size()); ++i)
637 sigmaMaxSum += containerPtrs[i]->sigmaMax();
641 containerPtrs[iContainer]->constructState();
642 if ( !containerPtrs[iContainer]->constructProcess( process) )
646 if ( physical && doResDecays
647 && !containerPtrs[iContainer]->decayResonances( process) )
651 if (physical) findJunctions( process);
665 bool ProcessLevel::nextTwo(
Event& process) {
668 double eCM = infoPtr->eCM();
669 for (
int i = 0; i < int(containerPtrs.size()); ++i)
670 containerPtrs[i]->newECM(eCM);
671 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
672 container2Ptrs[i2]->newECM(eCM);
675 bool physical =
true;
676 for (
int loop = 0; loop < MAXLOOP; ++loop) {
677 if (!physical) process.clear();
687 double sigmaMaxNow = sigmaMaxSum * rndmPtr->flat();
688 int iMax = containerPtrs.size() - 1;
690 do sigmaMaxNow -= containerPtrs[++iContainer]->sigmaMax();
691 while (sigmaMaxNow > 0. && iContainer < iMax);
694 if (containerPtrs[iContainer]->trialProcess())
break;
697 if (infoPtr->atEndOfFile())
return false;
701 if (containerPtrs[iContainer]->newSigmaMax()) {
703 for (
int i = 0; i < int(containerPtrs.size()); ++i)
704 sigmaMaxSum += containerPtrs[i]->sigmaMax();
711 double sigma2MaxNow = sigma2MaxSum * rndmPtr->flat();
712 int i2Max = container2Ptrs.size() - 1;
714 do sigma2MaxNow -= container2Ptrs[++i2Container]->sigmaMax();
715 while (sigma2MaxNow > 0. && i2Container < i2Max);
718 if (container2Ptrs[i2Container]->trialProcess())
break;
722 if (container2Ptrs[i2Container]->newSigmaMax()) {
724 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
725 sigma2MaxSum += container2Ptrs[i2]->sigmaMax();
729 containerPtrs[iContainer]->constructState();
730 container2Ptrs[i2Container]->constructState();
733 double xA1 = containerPtrs[iContainer]->x1();
734 double xB1 = containerPtrs[iContainer]->x2();
735 double xA2 = container2Ptrs[i2Container]->x1();
736 double xB2 = container2Ptrs[i2Container]->x2();
737 if (xA1 + xA2 >= 1. || xB1 + xB2 >= 1.)
continue;
743 int idA1 = containerPtrs[iContainer]->id1();
744 int idB1 = containerPtrs[iContainer]->id2();
745 int idA2 = container2Ptrs[i2Container]->id1();
746 int idB2 = container2Ptrs[i2Container]->id2();
747 double Q2Fac1 = containerPtrs[iContainer]->Q2Fac();
748 double Q2Fac2 = container2Ptrs[i2Container]->Q2Fac();
749 double pdfA2Raw = beamAPtr->xf( idA2, xA2,Q2Fac2);
750 double pdfB2Raw = beamBPtr->xf( idB2, xB2,Q2Fac2);
753 beamAPtr->append( 3, idA1, xA1);
754 beamAPtr->xfISR( 0, idA1, xA1, Q2Fac1);
755 beamAPtr->pickValSeaComp();
756 beamBPtr->append( 4, idB1, xB1);
757 beamBPtr->xfISR( 0, idB1, xB1, Q2Fac1);
758 beamBPtr->pickValSeaComp();
761 double pdfA2Mod = beamAPtr->xfMPI( idA2, xA2,Q2Fac2);
762 double pdfB2Mod = beamBPtr->xfMPI( idB2, xB2,Q2Fac2);
763 double wtPdfMod = (pdfA2Mod * pdfB2Mod) / (pdfA2Raw * pdfB2Raw);
764 if (wtPdfMod < rndmPtr->flat())
continue;
769 if ( someHardSame && containerPtrs[iContainer]->isSame()
770 && container2Ptrs[i2Container]->isSame()) {
772 if (rndmPtr->flat() > 0.5) toLoop =
true;
774 double mHat1 = containerPtrs[iContainer]->mHat();
775 double pTHat1 = containerPtrs[iContainer]->pTHat();
776 double mHat2 = container2Ptrs[i2Container]->mHat();
777 double pTHat2 = container2Ptrs[i2Container]->pTHat();
778 if (mHat1 > mHatMin2 && mHat1 < mHatMax2
779 && pTHat1 > pTHatMin2 && pTHat1 < pTHatMax2
780 && mHat2 > mHatMin1 && mHat2 < mHatMax1
781 && pTHat2 > pTHatMin1 && pTHat2 < pTHatMax1
782 && rndmPtr->flat() > 0.5) toLoop =
true;
785 if (toLoop)
continue;
793 process2.init(
"(second hard)", particleDataPtr, startColTag);
794 process2.initColTag();
795 if ( !containerPtrs[iContainer]->constructProcess( process) )
797 if (physical && !container2Ptrs[i2Container]->constructProcess( process2,
798 false) ) physical =
false;
801 if ( physical && doResDecays
802 && !containerPtrs[iContainer]->decayResonances( process) )
804 if ( physical && doResDecays
805 && !container2Ptrs[i2Container]->decayResonances( process2) )
809 if (physical) combineProcessRecords( process, process2);
812 if (physical) findJunctions( process);
827 void ProcessLevel::combineProcessRecords(
Event& process,
Event& process2) {
830 int nSize = process.size();
832 while (nHard < nSize && process[nHard].mother1() == 3) ++nHard;
835 vector<Particle> resProd;
837 for (
int i = nHard; i < nSize; ++i) resProd.push_back( process[i] );
838 process.popBack(nSize - nHard);
842 int nSize2 = process2.size();
844 while (nHard2 < nSize2 && process2[nHard2].mother1() == 3) ++nHard2;
847 int addPos = nHard - 3;
848 int addCol = process.lastColTag() - startColTag;
851 for (
int i = 3; i < nSize2; ++i) {
854 process2[i].offsetHistory( 2, addPos, 2, addPos);
855 process2[i].offsetCol( addCol);
858 if (i < nHard2) process.append( process2[i] );
862 int addPos2 = nHard2 - 3;
866 for (
int i = 5; i < nHard; ++i)
867 process[i].offsetHistory( 0, 0, nHard - 1, addPos2);
870 for (
int i = 0; i < int(resProd.size()); ++i) {
871 resProd[i].offsetHistory( nHard - 1, addPos2, nHard - 1, addPos2);
872 process.append( resProd[i] );
877 if (nHard2 < nSize2) {
878 int nHard3 = nHard + nHard2 - 3;
879 int addPos3 = nSize - nHard;
882 for (
int i = nHard + 2; i < nHard3; ++i)
883 process[i].offsetHistory( 0, 0, nHard3 - 1, addPos3);
886 for (
int i = nHard2; i < nSize2; ++i) {
887 process2[i].offsetHistory( nHard3 - 1, addPos3, nHard3 - 1, addPos3);
888 process.append( process2[i] );
893 process.scaleSecond( process2.scale() );
902 void ProcessLevel::findJunctions(
Event& junEvent) {
905 for (
int i = 1; i<junEvent.size(); i++) {
909 if (abs(junEvent[i].status()) <= 21 || junEvent[i].colType() == 0)
911 vector<int> motherList = junEvent.motherList(i);
912 int iMot1 = motherList[0];
913 vector<int> sisterList = junEvent.daughterList(iMot1);
917 map<int,int> colVertex, acolVertex;
920 for (
unsigned int indx = 0; indx < motherList.size(); indx++) {
921 int iMot = motherList[indx];
922 if ( abs(junEvent[iMot].colType()) == 1 )
923 barSum -= junEvent[iMot].colType();
924 else if ( abs(junEvent[iMot].colType()) == 3)
925 barSum -= 2*junEvent[iMot].colType()/3;
926 int col = junEvent[iMot].acol();
927 int acol = junEvent[iMot].col();
931 if (acolVertex.find(col) == acolVertex.end() ) colVertex[col] = iMot;
932 else acolVertex.erase(col);
933 }
else if (col < 0) {
934 if (colVertex.find(-col) == colVertex.end() ) acolVertex[-col] = iMot;
935 else colVertex.erase(-col);
938 if (colVertex.find(acol) == colVertex.end()) acolVertex[acol] = iMot;
939 else colVertex.erase(acol);
940 }
else if (acol < 0) {
941 if (acolVertex.find(-acol) == acolVertex.end())
942 colVertex[-acol] = iMot;
943 else acolVertex.erase(-acol);
948 for (
unsigned int indx = 0; indx < sisterList.size(); indx++) {
949 int iDau = sisterList[indx];
950 if ( abs(junEvent[iDau].colType()) == 1 )
951 barSum += junEvent[iDau].colType();
952 else if ( abs(junEvent[iDau].colType()) == 3)
953 barSum += 2*junEvent[iDau].colType()/3;
954 int col = junEvent[iDau].col();
955 int acol = junEvent[iDau].acol();
959 if (acolVertex.find(col) == acolVertex.end() ) colVertex[col] = iDau;
960 else acolVertex.erase(col);
961 }
else if (col < 0) {
962 if (colVertex.find(-col) == colVertex.end() ) acolVertex[-col] = iDau;
963 else colVertex.erase(-col);
966 if (colVertex.find(acol) == colVertex.end()) acolVertex[acol] = iDau;
967 else colVertex.erase(acol);
968 }
else if (acol < 0) {
969 if (acolVertex.find(-acol) == acolVertex.end())
970 colVertex[-acol] = iDau;
971 else acolVertex.erase(-acol);
977 if (barSum == 0)
continue;
980 for (
int iJun = 0; iJun < junEvent.sizeJunction(); ++iJun) {
982 for (
int j = 0; j < 3; ++j) {
983 int colNow = junEvent.colJunction(iJun, j);
984 if (junEvent.kindJunction(iJun) % 2 == 1) colVertex.erase(colNow);
985 else acolVertex.erase(colNow);
990 if (colVertex.size() == 0 && acolVertex.size() == 0)
continue;
994 if (colVertex.size() == 3 && acolVertex.size() == 0) kindJun = 1;
995 else if (colVertex.size() == 0 && acolVertex.size() == 3) kindJun = 2;
997 infoPtr->errorMsg(
"Error in ProcessLevel::findJunctions: "
998 "N(unmatched (anti)colour tags) != 3");
1003 map<int,int> colJun = (kindJun == 1) ? colVertex : acolVertex;
1007 for (map<int,int>::iterator it = colJun.begin();
1008 it != colJun.end(); it++) {
1009 int col = it->first;
1010 int iCol = it->second;
1011 for (
unsigned int indx = 0; indx < motherList.size(); indx++) {
1012 if (iCol == motherList[indx]) {
1014 colVec.insert(colVec.begin(),col);
1017 if (colVec.size() == 0 || colVec[0] != col) colVec.push_back(col);
1021 junEvent.appendJunction( kindJun, colVec[0], colVec[1], colVec[2]);
1030 bool ProcessLevel::checkColours(
Event& process) {
1033 bool physical =
true;
1035 int colType, col, acol, iPos, iNow, iNowA;
1036 vector<int> colTags, colPos, acolPos;
1039 for (
int i = 0; i < process.size(); ++i) {
1040 colType = process[i].colType();
1041 col = process[i].col();
1042 acol = process[i].acol();
1043 if (colType == 0 && (col != 0 || acol != 0)) physical =
false;
1044 else if (colType == 1 && (col <= 0 || acol != 0)) physical =
false;
1045 else if (colType == -1 && (col != 0 || acol <= 0)) physical =
false;
1046 else if (colType == 2 && (col <= 0 || acol <= 0)) physical =
false;
1049 else if (colType == 3 && (col <= 0 || acol >= 0)) physical =
false;
1050 else if (colType == -3 && (col >= 0 || acol <= 0)) physical =
false;
1052 else if (colType < -1 || colType > 3) physical =
false;
1057 for (
int ic = 0; ic < int(colTags.size()) ; ++ic)
1058 if (col == colTags[ic]) match =
true;
1059 if (!match) colTags.push_back(col);
1060 }
else if (acol > 0) {
1062 for (
int ic = 0; ic < int(colTags.size()) ; ++ic)
1063 if (acol == colTags[ic]) match =
true;
1064 if (!match) colTags.push_back(acol);
1069 for (
int ic = 0; ic < int(colTags.size()) ; ++ic)
1070 if (-col == colTags[ic]) match =
true;
1071 if (!match) colTags.push_back(-col);
1072 }
else if (acol < 0) {
1074 for (
int ic = 0; ic < int(colTags.size()) ; ++ic)
1075 if (-acol == colTags[ic]) match =
true;
1076 if (!match) colTags.push_back(-acol);
1082 infoPtr->errorMsg(
"Error in ProcessLevel::checkColours: "
1083 "incorrect colour assignment");
1088 for (
int iJun = 0; iJun < process.sizeJunction(); ++iJun) {
1089 for (
int j = 0; j < 3; ++j) {
1090 int colJun = process.colJunction(iJun, j);
1091 for (
int ic = 0; ic < int(colTags.size()) ; ++ic)
1092 if (colJun == colTags[ic]) {
1093 colTags[ic] = colTags[colTags.size() - 1];
1101 for (
int ic = 0; ic < int(colTags.size()); ++ic) {
1105 for (
int i = 0; i < process.size(); ++i) {
1106 if (process[i].col() == col || process[i].acol() == -col)
1107 colPos.push_back(i);
1108 if (process[i].acol() == col || process[i].col() == -col)
1109 acolPos.push_back(i);
1113 while (colPos.size() > 1) {
1114 iPos = colPos.size() - 1;
1115 iNow = colPos[iPos];
1116 if ( process[iNow].mother1() == colPos[iPos - 1]
1117 && process[iNow].mother2() == 0) colPos.pop_back();
1120 while (acolPos.size() > 1) {
1121 iPos = acolPos.size() - 1;
1122 iNow = acolPos[iPos];
1123 if ( process[iNow].mother1() == acolPos[iPos - 1]
1124 && process[iNow].mother2() == 0) acolPos.pop_back();
1129 if (colPos.size() + acolPos.size() != 2) physical =
false;
1132 else if (colPos.size() == 2) {
1134 if ( process[iNow].mother1() != colPos[0]
1135 && process[iNow].mother2() != colPos[0] ) physical =
false;
1137 else if (acolPos.size() == 2) {
1139 if ( process[iNowA].mother1() != acolPos[0]
1140 && process[iNowA].mother2() != acolPos[0] ) physical =
false;
1147 if ( process[iNow].status() == -21 && process[iNowA].status() == -21 );
1148 else if ( (process[iNow].mother1() != process[iNowA].mother1())
1149 || (process[iNow].mother2() != process[iNowA].mother2()) )
1156 if (!physical) infoPtr->errorMsg(
"Error in ProcessLevel::checkColours: "
1157 "unphysical colour flow");
1166 void ProcessLevel::statistics2(
bool reset, ostream& os) {
1169 double invN = 1. / max(1, nImpact);
1170 double impactFac = max( 1., sumImpactFac * invN);
1171 double impactErr2 = ( sum2ImpactFac * invN / pow2(impactFac) - 1.) * invN;
1174 double sigma2SelSum = 0.;
1176 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
1177 sigma2SelSum += container2Ptrs[i2]->sigmaSelMC();
1178 n2SelSum += container2Ptrs[i2]->nSelected();
1180 double factor1 = impactFac * sigma2SelSum / sigmaND;
1181 double rel1Err = sqrt(1. / max(1, n2SelSum) + impactErr2);
1182 if (allHardSame) factor1 *= 0.5;
1185 double sigma1SelSum = 0.;
1187 for (
int i = 0; i < int(containerPtrs.size()); ++i) {
1188 sigma1SelSum += containerPtrs[i]->sigmaSelMC();
1189 n1SelSum += containerPtrs[i]->nSelected();
1191 double factor2 = impactFac * sigma1SelSum / sigmaND;
1192 if (allHardSame) factor2 *= 0.5;
1193 double rel2Err = sqrt(1. / max(1, n1SelSum) + impactErr2);
1196 os <<
"\n *------- PYTHIA Event and Cross Section Statistics ------"
1197 <<
"--------------------------------------------------*\n"
1200 <<
" | Subprocess Code | "
1201 <<
"Number of events | sigma +- delta |\n"
1203 <<
" Selected Accepted | (estimated) (mb) |\n"
1206 <<
" |------------------------------------------------------------"
1207 <<
"------------------------------------------------|\n"
1210 <<
" | First hard process: | "
1219 double sigmaSum = 0.;
1220 double delta2Sum = 0.;
1223 map<int, string> nameM;
1224 map<int, long> nTryM, nSelM, nAccM;
1225 map<int, double> sigmaM, delta2M;
1228 for (
int i = 0; i < int(containerPtrs.size()); ++i)
1229 if (containerPtrs[i]->sigmaMax() != 0.) {
1232 int code = containerPtrs[i]->code();
1233 nTrySum += containerPtrs[i]->nTried();
1234 nSelSum += containerPtrs[i]->nSelected();
1235 nAccSum += containerPtrs[i]->nAccepted();
1236 sigmaSum += containerPtrs[i]->sigmaMC() * factor1;
1237 delta2Sum += pow2(containerPtrs[i]->deltaMC() * factor1);
1238 nameM[code] = containerPtrs[i]->name();
1239 nTryM[code] += containerPtrs[i]->nTried();
1240 nSelM[code] += containerPtrs[i]->nSelected();
1241 nAccM[code] += containerPtrs[i]->nAccepted();
1242 sigmaM[code] += containerPtrs[i]->sigmaMC() * factor1;
1243 delta2M[code] += pow2(containerPtrs[i]->deltaMC() * factor1);
1244 delta2M[code] += pow2(containerPtrs[i]->sigmaMC() * factor1 * rel1Err);
1248 for (map<int, string>::iterator i = nameM.begin(); i != nameM.end(); ++i) {
1249 int code = i->first;
1250 os <<
" | " << left << setw(40) << i->second
1251 << right << setw(5) << code <<
" | "
1252 << setw(11) << nTryM[code] <<
" " << setw(10) << nSelM[code] <<
" "
1253 << setw(10) << nAccM[code] <<
" | " << scientific << setprecision(3)
1254 << setw(11) << sigmaM[code]
1255 << setw(11) << sqrtpos(delta2M[code]) <<
" |\n";
1259 delta2Sum += pow2( sigmaSum * rel1Err );
1262 <<
" | " << left << setw(45) <<
"sum" << right <<
" | " << setw(11)
1263 << nTrySum <<
" " << setw(10) << nSelSum <<
" " << setw(10)
1264 << nAccSum <<
" | " << scientific << setprecision(3) << setw(11)
1265 << sigmaSum << setw(11) << sqrtpos(delta2Sum) <<
" |\n";
1270 <<
" |------------------------------------------------------------"
1271 <<
"------------------------------------------------|\n"
1274 <<
" | Second hard process: | "
1295 for (
int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
1296 if (container2Ptrs[i2]->sigmaMax() != 0.) {
1299 int code = container2Ptrs[i2]->code();
1300 nTrySum += container2Ptrs[i2]->nTried();
1301 nSelSum += container2Ptrs[i2]->nSelected();
1302 nAccSum += container2Ptrs[i2]->nAccepted();
1303 sigmaSum += container2Ptrs[i2]->sigmaMC() * factor2;
1304 delta2Sum += pow2(container2Ptrs[i2]->deltaMC() * factor2);
1305 nameM[code] = container2Ptrs[i2]->name();
1306 nTryM[code] += container2Ptrs[i2]->nTried();
1307 nSelM[code] += container2Ptrs[i2]->nSelected();
1308 nAccM[code] += container2Ptrs[i2]->nAccepted();
1309 sigmaM[code] += container2Ptrs[i2]->sigmaMC() * factor2;
1310 delta2M[code] += pow2(container2Ptrs[i2]->deltaMC() * factor2);
1311 delta2M[code] += pow2(container2Ptrs[i2]->sigmaMC() * factor2 * rel2Err);
1315 for (map<int, string>::iterator i2 = nameM.begin(); i2 != nameM.end(); ++i2) {
1316 int code = i2->first;
1317 os <<
" | " << left << setw(40) << i2->second
1318 << right << setw(5) << code <<
" | "
1319 << setw(11) << nTryM[code] <<
" " << setw(10) << nSelM[code] <<
" "
1320 << setw(10) << nAccM[code] <<
" | " << scientific << setprecision(3)
1321 << setw(11) << sigmaM[code]
1322 << setw(11) << sqrtpos(delta2M[code]) <<
" |\n";
1326 delta2Sum += pow2( sigmaSum * rel2Err );
1329 <<
" | " << left << setw(45) <<
"sum" << right <<
" | " << setw(11)
1330 << nTrySum <<
" " << setw(10) << nSelSum <<
" " << setw(10)
1331 << nAccSum <<
" | " << scientific << setprecision(3) << setw(11)
1332 << sigmaSum << setw(11) << sqrtpos(delta2Sum) <<
" |\n";
1337 <<
" |------------------------------------------------------------"
1338 <<
"------------------------------------------------|\n"
1341 <<
" | Uncombined cross sections for the two event sets were "
1342 << setw(10) << sigma1SelSum <<
" and " << sigma2SelSum <<
" mb, "
1343 <<
"respectively, combined |\n"
1344 <<
" | using a sigma(nonDiffractive) of " << setw(10) << sigmaND
1345 <<
" mb and an impact-parameter enhancement factor of "
1346 << setw(10) << impactFac <<
". |\n";
1351 <<
" *------- End PYTHIA Event and Cross Section Statistics -----"
1352 <<
"------------------------------------------------*" << endl;
1355 if (reset) resetStatistics();