8 #include "Pythia8/HadronLevel.h"
24 : i1(iDecayIn), i2(0), origin(originIn) {}
26 Vec4 displaced2In) : i1(i1In), i2(i2In), origin(originIn),
27 displaced1(displaced1In), displaced2(displaced2In) {}
29 bool isDecay() {
return i2 == 0; }
35 return origin.e() > r.origin.e(); }
38 Vec4 origin, displaced1, displaced2;
50 const double HadronLevel::MTINY = 0.1;
56 bool HadronLevel::init( TimeShowerPtr timesDecPtr,
RHadrons* rHadronsPtrIn,
57 DecayHandlerPtr decayHandlePtr, vector<int> handledParticles,
58 StringIntPtr stringInteractionsPtrIn, PartonVertexPtr partonVertexPtrIn) {
61 rHadronsPtr = rHadronsPtrIn;
64 doHadronize = flag(
"HadronLevel:Hadronize");
65 doDecay = flag(
"HadronLevel:Decay");
66 doRescatter = flag(
"HadronLevel:Rescatter");
67 doBoseEinstein = flag(
"HadronLevel:BoseEinstein");
68 doDeuteronProd = flag(
"HadronLevel:DeuteronProduction");
71 mStringMin = parm(
"HadronLevel:mStringMin");
74 eNormJunction = parm(
"StringFragmentation:eNormJunction");
77 allowRH = flag(
"RHadrons:allow");
80 widthSepBE = parm(
"BoseEinstein:widthSep");
83 partonVertexPtr = partonVertexPtrIn;
84 doPartonVertex = flag(
"PartonVertex:setVertex");
87 closePacking = flag(
"StringPT:closePacking");
90 fragmentationModifierPtr =
91 stringInteractionsPtrIn->getFragmentationModifier();
92 stringRepulsionPtr = stringInteractionsPtrIn->getStringRepulsion();
100 colConfig.init(infoPtr, &flavSel);
103 stringFrag.init(&flavSel, &pTSel, &zSel, fragmentationModifierPtr);
104 ministringFrag.init(&flavSel, &pTSel, &zSel);
107 decays.init(timesDecPtr, &flavSel, decayHandlePtr, handledParticles);
110 string dataFile = word(
"xmlPath") +
"NucleonExcitations.dat";
111 if (!nucleonExcitations.init(dataFile)) {
112 infoPtr->errorMsg(
"Abort from HadronLevel::init: "
113 "nucleon excitation data unavailable");
118 lowEnergyProcess.init(&flavSel, &stringFrag, &ministringFrag,
119 &lowEnergySigma, &nucleonExcitations);
122 lowEnergySigma.init(&nucleonExcitations);
128 if (doBoseEinstein) {
129 infoPtr->errorMsg(
"Error in HadronLevel::init: "
130 "Rescattering and Bose-Einstein cannot be on at the same time");
135 scatterManyTimes = flag(
"Rescattering:scatterManyTimes");
136 scatterQuickCheck = flag(
"Rescattering:quickCheck");
137 scatterNeighbours = flag(
"Rescattering:nearestNeighbours");
138 impactModel = mode(
"Rescattering:impactModel");
139 b2Max = pow2(FM2MM * parm(
"Rescattering:bMax"));
140 impactOpacity = parm(
"Rescattering:opacity");
141 widthSepRescatter = FMINV2GEV / parm(
"Rescattering:tau0RapidDecay");
142 delayRegeneration = flag(
"Rescattering:delayRegeneration");
143 tauRegeneration = parm(
"Rescattering:tauRegeneration");
144 boostDir = mode(
"Rescattering:boostDir");
145 boost = parm(
"Rescattering:boost");
146 doBoost = boostDir > 0 && boost > 0.;
147 useVelocityFrame = flag(
"Rescattering:useVelocityFrame");
154 if (doDeuteronProd) deuteronProd.init();
157 useHiddenValley = hiddenvalleyFrag.init();
160 rHadronsPtr->fragPtrs( &flavSel, &zSel);
163 colTrace.init(infoPtr);
166 junctionSplitting.init();
177 bool HadronLevel::next(
Event& event) {
180 event.savePartonLevelSize();
183 if (useHiddenValley) hiddenvalleyFrag.fragment(event);
186 if (!decayOctetOnia(event))
return false;
189 for (
int i = 0; i <
event.size(); ++i)
if (event[i].isHadron())
190 event[i].tau( event[i].tau0() * rndmPtr->exp() );
193 if (!junctionSplitting.checkColours(event)) {
194 infoPtr->errorMsg(
"Error in HadronLevel::next: "
195 "failed colour/junction check");
200 bool doBoseEinsteinNow = doBoseEinstein;
201 bool doDeuteronProdNow = doDeuteronProd;
202 bool decaysCausedHadronization;
204 decaysCausedHadronization =
false;
211 if (!findSinglets( event, (stringRepulsionPtr !=
nullptr) ))
215 if (allowRH && !rHadronsPtr->produce( colConfig, event))
220 vector< vector< pair<double,double> > > rapPairs =
221 rapidityPairs(event);
222 colConfig.rapPairs = rapPairs;
227 if ( stringRepulsionPtr ) {
231 stringRepulsionPtr->stringRepulsion(event, colConfig);
236 if (!findSinglets( event)) {
237 infoPtr->errorMsg(
"Error in HadronLevel::next: "
238 "ropes: failed 2nd singlet tracing.");
244 if (fragmentationModifierPtr)
245 fragmentationModifierPtr->initEvent(event, colConfig);
248 for (
int iSub = 0; iSub < colConfig.size(); ++iSub) {
251 colConfig.collect(iSub, event);
252 int nBefFrag =
event.size();
255 if ( colConfig[iSub].massExcess > mStringMin ) {
256 if (!stringFrag.fragment( iSub, colConfig, event))
return false;
260 bool isDiff = infoPtr->isDiffractiveA()
261 || infoPtr->isDiffractiveB();
262 if (!ministringFrag.fragment( iSub, colConfig, event, isDiff))
267 if (doPartonVertex) partonVertexPtr->vertexHadrons( nBefFrag, event);
274 if (doDecay && !doRescatter) {
275 decaysCausedHadronization = decays.decayAll(event, widthSepBE);
278 }
else if (doRescatter) {
281 if (boostDir == 1)
event.bst(tanh(boost), 0., 0.);
282 else if (boostDir == 2)
event.bst(0., tanh(boost), 0.);
283 else event.bst(0., 0., tanh(boost));
287 priority_queue<PriorityNode> candidates;
288 queueDecResc(event, 0, candidates);
289 while (!candidates.empty()) {
290 if (event.size() > 10000) {
291 infoPtr->errorMsg(
"Error in HadronLevel::next: "
292 "too many rescatterings; possibly caught in endless loop");
297 PriorityNode node = candidates.top();
301 if (!event[node.i1].isFinal()
302 || (!node.isDecay() && !
event[node.i2].isFinal()))
continue;
305 int oldSize =
event.size();
306 if (node.isDecay()) {
307 decays.decay(node.i1, event);
310 if (decays.moreToDo()) decaysCausedHadronization =
true;
314 Particle& hadA =
event[node.i1];
315 Particle& hadB =
event[node.i2];
316 double eCM = (hadA.p() + hadB.p()).mCalc();
317 int type = lowEnergySigma.pickProcess(hadA.id(), hadB.id(), eCM,
320 infoPtr->errorMsg(
"Error in HadronLevel::next: "
321 "no available rescattering processes", to_string(hadA.id())
322 +
" + " + to_string(hadB.id()) +
" @ " + to_string(eCM));
325 if (!lowEnergyProcess.collide(node.i1, node.i2, type, event,
326 node.origin, node.displaced1, node.displaced2))
continue;
330 if (scatterManyTimes) queueDecResc(event, oldSize, candidates);
334 for (
int i = oldSize; i <
event.size(); ++i) {
335 if (event[i].isFinal() &&
event[i].isHadron()
336 &&
event[i].canDecay() &&
event[i].mayDecay()
337 &&
event[i].mWidth() > widthSepBE) {
338 decays.decay(i, event);
339 if (decays.moreToDo())
340 decaysCausedHadronization =
true;
347 if (boostDir == 1)
event.bst(-tanh(boost), 0., 0.);
348 else if (boostDir == 2)
event.bst(0., -tanh(boost), 0.);
349 else event.bst(0., 0., -tanh(boost));
354 if (doBoseEinsteinNow) {
355 if (!boseEinstein.shiftEvent(event))
return false;
356 doBoseEinsteinNow =
false;
361 if (decays.decayAll(event))
362 decaysCausedHadronization =
true;
366 if (doDeuteronProdNow) {
367 if (!deuteronProd.combine(event))
return false;
368 doDeuteronProdNow =
false;
369 decaysCausedHadronization = doDecay;
374 }
while (decaysCausedHadronization);
386 bool HadronLevel::moreDecays(
Event& event) {
389 if (!decayOctetOnia(event))
return false;
394 if ( event[iDec].isFinal() && event[iDec].canDecay()
395 && event[iDec].mayDecay() ) decays.decay( iDec, event);
396 }
while (++iDec < event.size());
407 bool HadronLevel::initLowEnergyProcesses() {
410 doNonPertAll = flag(
"LowEnergyQCD:all");
412 if (flag(
"LowEnergyQCD:nonDiffractive")) nonPertProc.push_back(1);
413 if (flag(
"LowEnergyQCD:elastic")) nonPertProc.push_back(2);
414 if (flag(
"LowEnergyQCD:singleDiffractiveXB")) nonPertProc.push_back(3);
415 if (flag(
"LowEnergyQCD:singleDiffractiveAX")) nonPertProc.push_back(4);
416 if (flag(
"LowEnergyQCD:doubleDiffractive")) nonPertProc.push_back(5);
417 if (flag(
"LowEnergyQCD:excitation")) nonPertProc.push_back(7);
418 if (flag(
"LowEnergyQCD:annihilation")) nonPertProc.push_back(8);
419 if (flag(
"LowEnergyQCD:resonant")) nonPertProc.push_back(9);
423 return doNonPertAll || (nonPertProc.size() > 0);
431 int HadronLevel::pickLowEnergyProcess(
int idA,
int idB,
double eCM,
432 double mA,
double mB) {
439 procType = lowEnergySigma.pickProcess(idA, idB, eCM, mA, mB);
441 infoPtr->errorMsg(
"Error in HadronLevel::pickLowEnergyProcess: "
442 "no available processes for specified particles and energy");
447 }
else if (nonPertProc.size() ==1) {
448 procType = nonPertProc[0];
453 vector<double> sigmas;
454 for (
int proc : nonPertProc) {
455 double sigma = lowEnergySigma.sigmaPartial(idA, idB, eCM, mA, mB, proc);
457 procs.push_back(proc);
458 sigmas.push_back(sigma);
460 infoPtr->errorMsg(
"Warning in HadronLevel::pickLowEnergyProcess: "
461 "a process with zero cross section was explicitly turned on",
462 std::to_string(proc));
467 if (procs.size() == 0) {
468 infoPtr->errorMsg(
"Error in HadronLevel::pickLowEnergyProcess: "
469 "no processes with positive cross sections have been turned on");
472 procType = procs[rndmPtr->pick(sigmas)];
477 procType = lowEnergySigma.pickResonance(idA, idB, eCM);
479 infoPtr->errorMsg(
"Error in Pythia::nextNonPert: "
480 "no available resonances for the given particles and energy");
494 bool HadronLevel::decayOctetOnia(
Event& event) {
497 for (
int iDec = 0; iDec <
event.size(); ++iDec)
498 if (event[iDec].isFinal()
499 && particleDataPtr->isOctetHadron(event[iDec].
id())) {
500 if (!decays.decay( iDec, event))
return false;
503 int iGlu =
event.size() - 1;
504 event[iGlu].cols( event[iDec].col(), event[iDec].acol() );
518 bool HadronLevel::findSinglets(
Event& event,
bool keepJunctions) {
524 if (colTrace.setupColList(event))
return true;
529 for (
int iJun = 0; iJun <
event.sizeJunction(); ++iJun)
530 if (event.remainsJunction(iJun)) {
531 if (!keepJunctions)
event.remainsJunction(iJun,
false);
532 int kindJun =
event.kindJunction(iJun);
536 for (
int iCol = 0; iCol < 3; ++iCol) {
537 int indxCol =
event.colJunction(iJun, iCol);
538 iParton.push_back( -(10 + 10 * iJun + iCol) );
540 if (kindJun % 2 == 1 && !colTrace.traceFromAcol(indxCol, event, iJun,
541 iCol, iParton))
return false;
543 if (kindJun % 2 == 0 && !colTrace.traceFromCol(indxCol, event, iJun,
544 iCol, iParton))
return false;
548 if (!keepJunctions) {
549 int nJunOld =
event.sizeJunction();
550 if (!colConfig.insert(iParton, event))
return false;
551 if (event.sizeJunction() < nJunOld) --iJun;
556 while (!colTrace.colFinished()) {
558 if (!colTrace.traceFromCol( -1, event, -1, -1, iParton))
return false;
561 if (!colConfig.insert(iParton, event))
return false;
565 while (!colTrace.finished()) {
567 if (!colTrace.traceInLoop(event, iParton))
return false;
570 if (!colConfig.insert(iParton, event))
return false;
582 void HadronLevel::queueDecResc(
Event& event,
int iStart,
583 priority_queue<HadronLevel::PriorityNode>& queue) {
586 for (
int iFirst = iStart; iFirst <
event.size(); ++iFirst) {
587 Particle& hadA =
event[iFirst];
588 if (!hadA.isFinal() || !hadA.isHadron())
continue;
591 if (doDecay && hadA.canDecay() && hadA.mayDecay()
592 && hadA.mWidth() > widthSepRescatter)
593 queue.push(PriorityNode(iFirst, hadA.vDec()));
597 int iMotA =
event[iNowA].mother1();
598 if (!scatterNeighbours)
599 while (event[iMotA].isHadron() && event[iNowA].mother2() == 0) {
601 iMotA =
event[iNowA].mother1();
605 for (
int iSecond = 0; iSecond < iFirst; ++iSecond) {
606 Particle& hadB =
event[iSecond];
607 if (!hadB.isFinal() || !hadB.isHadron())
continue;
610 if (scatterQuickCheck && dot3( hadB.p() / hadB.e() - hadA.p() / hadA.e(),
611 hadB.vProd() - hadA.vProd() ) > 0. )
continue;
614 if ( event[hadA.mother1()].isHadron() && hadB.mother1() == hadA.mother1()
615 && hadB.mother2() == hadA.mother2())
continue;
618 if (!scatterNeighbours) {
620 int iMotB =
event[iNowB].mother1();
621 while (event[iMotB].isHadron() && event[iNowB].mother2() == 0) {
623 iMotB =
event[iNowB].mother1();
627 if (abs(iNowB - iNowA) <= 1)
continue;
633 if (useVelocityFrame)
634 frame.toSameVframe(hadA.p(), hadB.p());
636 frame.toCMframe(hadA.p(), hadB.p());
637 Vec4 vA = hadA.vProd(); vA.rotbst(frame);
638 Vec4 vB = hadB.vProd(); vB.rotbst(frame);
639 Vec4 pA = hadA.p(); pA.rotbst(frame);
640 Vec4 pB = hadB.p(); pB.rotbst(frame);
643 double b2 = (vA - vB).pT2();
644 if (b2 > b2Max)
continue;
647 double t0 = max(vA.e(), vB.e());
648 double zA = vA.pz() + (t0 - vA.e()) * pA.pz() / pA.e();
649 double zB = vB.pz() + (t0 - vB.e()) * pB.pz() / pB.e();
652 if (zA >= zB)
continue;
655 if (delayRegeneration && (hadA.status()/10 == 15
656 || hadB.status()/10 == 15)) {
657 bool regA = (hadA.status() == 152 || hadA.status() == 157);
658 if ( (hadA.status() == 153 || hadA.status() == 154)
659 && event[hadA.mother1()].isHadron()) regA =
true;
660 bool regB = (hadB.status() == 152 || hadB.status() == 157);
661 if ( (hadB.status() == 153 || hadB.status() == 154)
662 && event[hadB.mother1()].isHadron()) regB =
true;
664 if (regA) vA += tauRegeneration * FM2MM * rndmPtr->exp()
666 if (regB) vB += tauRegeneration * FM2MM * rndmPtr->exp()
668 t0 = max(vA.e(), vB.e());
669 zA = vA.pz() + (t0 - vA.e()) * pA.pz() / pA.e();
670 zB = vB.pz() + (t0 - vB.e()) * pB.pz() / pB.e();
671 if (zA >= zB)
continue;
676 double eCM = (pA + pB).mCalc();
677 double sigma = lowEnergySigma.sigmaTotal(hadA.id(), hadB.id(), eCM,
679 double b2Crit = MB2FMSQ * pow2(FM2MM) * sigma / (impactOpacity * M_PI);
682 if (impactModel == 0) pAccept = (b2 < b2Crit) ? impactOpacity : 0.;
683 else pAccept = impactOpacity * exp(-b2 / b2Crit);
684 if (rndmPtr->flat() > pAccept)
continue;
688 double tColl = t0 - (zB - zA) / (pB.pz() / pB.e() - pA.pz() / pA.e());
689 Vec4 origin(0.5 * (vA.px() + vB.px()), 0.5 * (vA.py() + vB.py()),
690 zA + pA.pz() / pA.e() * (tColl - t0), tColl);
691 Vec4 displacedA = Vec4( vA.px(), vA.py(), origin.pz(), origin.e() );
692 Vec4 displacedB = Vec4( vB.px(), vB.py(), origin.pz(), origin.e() );
694 origin.rotbst(frame);
695 displacedA.rotbst(frame);
696 displacedB.rotbst(frame);
699 queue.push( PriorityNode(iFirst, iSecond, origin, displacedA,
709 vector< vector< pair<double,double> > > HadronLevel::rapidityPairs(
713 vector< vector< pair<double,double> > > rapPairs;
714 for (
int iSub = 0; iSub < int(colConfig.size()); iSub++) {
715 vector< pair<double,double> > rapsNow;
716 vector<int> iPartons = colConfig[iSub].iParton;
719 if (colConfig[iSub].hasJunction) {
723 for (
int iP = 0; iP < int(iPartons.size()); iP++) {
724 int iQ = iPartons[iP];
725 if (iQ < 0)
continue;
726 if (event[iQ].
id() == 21)
continue;
727 double yNow = yMax(event[iQ], MTINY);
728 if (yNow > yma) yma = yNow;
729 if (yNow < ymi) ymi = yNow;
731 rapsNow.push_back( make_pair(ymi, yma) );
735 int size = int(iPartons.size());
736 int end = size - (colConfig[iSub].isClosed ? 0 : 1);
737 for (
int iP = 0; iP < end; iP++) {
738 int i1 = iPartons[iP];
739 int i2 = iPartons[(iP+1)%size];
740 double y1 = yMax(event[i1], MTINY);
741 double y2 = yMax(event[i2], MTINY);
742 double ymi = min(y1, y2);
743 double yma = max(y1, y2);
744 rapsNow.push_back( make_pair(ymi, yma) );
747 rapPairs.push_back(rapsNow);