StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
HadronLevel.cc
1 // HadronLevel.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2020 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // Function definitions (not found in the header) for the HadronLevel class.
7 
8 #include "Pythia8/HadronLevel.h"
9 
10 namespace Pythia8 {
11 
12 //==========================================================================
13 
14 // The PriorityNode class.
15 // Used to order scatterings and decays during hadronic rescattering.
16 
17 //--------------------------------------------------------------------------
18 
20 
21 public:
22 
23  PriorityNode(int iDecayIn, Vec4 originIn)
24  : i1(iDecayIn), i2(0), origin(originIn) {}
25  PriorityNode(int i1In, int i2In, Vec4 originIn, Vec4 displaced1In,
26  Vec4 displaced2In) : i1(i1In), i2(i2In), origin(originIn),
27  displaced1(displaced1In), displaced2(displaced2In) {}
28 
29  bool isDecay() { return i2 == 0; }
30 
31  // Priority comparison to be used by priority_queue.
32  // Note that lower t means higher priority!
33  // @FUTURE: allow the user to pick the comparer (time-ordering problem)?
34  bool operator<(const PriorityNode& r) const {
35  return origin.e() > r.origin.e(); }
36 
37  int i1, i2;
38  Vec4 origin, displaced1, displaced2;
39 };
40 
41 //==========================================================================
42 
43 // The HadronLevel class.
44 
45 //--------------------------------------------------------------------------
46 
47 // Constants: could be changed here if desired, but normally should not.
48 
49 // Small safety mass used in string-end rapidity calculations.
50 const double HadronLevel::MTINY = 0.1;
51 
52 //--------------------------------------------------------------------------
53 
54 // Find settings. Initialize HadronLevel classes as required.
55 
56 bool HadronLevel::init( TimeShowerPtr timesDecPtr, RHadrons* rHadronsPtrIn,
57  DecayHandlerPtr decayHandlePtr, vector<int> handledParticles,
58  StringIntPtr stringInteractionsPtrIn, PartonVertexPtr partonVertexPtrIn) {
59 
60  // Store other input pointers.
61  rHadronsPtr = rHadronsPtrIn;
62 
63  // Main flags.
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");
69 
70  // Boundary mass between string and ministring handling.
71  mStringMin = parm("HadronLevel:mStringMin");
72 
73  // For junction processing.
74  eNormJunction = parm("StringFragmentation:eNormJunction");
75 
76  // Allow R-hadron formation.
77  allowRH = flag("RHadrons:allow");
78 
79  // Particles that should decay or not before Bose-Einstein stage.
80  widthSepBE = parm("BoseEinstein:widthSep");
81 
82  // Displace hadron vertices from parton impact-parameter picture.
83  partonVertexPtr = partonVertexPtrIn;
84  doPartonVertex = flag("PartonVertex:setVertex");
85 
86  // Need string density information be collected?
87  closePacking = flag("StringPT:closePacking");
88 
89  // Initialize string interactions (Ropewalk and Flavour Ropes) if present.
90  fragmentationModifierPtr =
91  stringInteractionsPtrIn->getFragmentationModifier();
92  stringRepulsionPtr = stringInteractionsPtrIn->getStringRepulsion();
93 
94  // Initialize auxiliary fragmentation classes.
95  flavSel.init();
96  pTSel.init();
97  zSel.init();
98 
99  // Initialize auxiliary administrative class.
100  colConfig.init(infoPtr, &flavSel);
101 
102  // Initialize string and ministring fragmentation.
103  stringFrag.init(&flavSel, &pTSel, &zSel, fragmentationModifierPtr);
104  ministringFrag.init(&flavSel, &pTSel, &zSel);
105 
106  // Initialize particle decays.
107  decays.init(timesDecPtr, &flavSel, decayHandlePtr, handledParticles);
108 
109  // Initialize nucleon excitations.
110  string dataFile = word("xmlPath") + "NucleonExcitations.dat";
111  if (!nucleonExcitations.init(dataFile)) {
112  infoPtr->errorMsg("Abort from HadronLevel::init: "
113  "nucleon excitation data unavailable");
114  return false;
115  }
116 
117  // Initialize low-energy framework.
118  lowEnergyProcess.init(&flavSel, &stringFrag, &ministringFrag,
119  &lowEnergySigma, &nucleonExcitations);
120 
121  // Initialize low energy cross sections.
122  lowEnergySigma.init(&nucleonExcitations);
123 
124  // Initialize rescattering settings if applicable.
125  if (doRescatter) {
126 
127  // Break if conflicting settings.
128  if (doBoseEinstein) {
129  infoPtr->errorMsg("Error in HadronLevel::init: "
130  "Rescattering and Bose-Einstein cannot be on at the same time");
131  return false;
132  }
133 
134  // Read settings for rescattering.
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");
148  }
149 
150  // Initialize BoseEinstein.
151  boseEinstein.init();
152 
153  // Initialize DeuteronProduction.
154  if (doDeuteronProd) deuteronProd.init();
155 
156  // Initialize Hidden-Valley fragmentation, if necessary.
157  useHiddenValley = hiddenvalleyFrag.init();
158 
159  // Send flavour and z selection pointers to R-hadron machinery.
160  rHadronsPtr->fragPtrs( &flavSel, &zSel);
161 
162  // Initialize the colour tracing class.
163  colTrace.init(infoPtr);
164 
165  // Initialize the junction splitting class.
166  junctionSplitting.init();
167 
168  // Done.
169  return true;
170 
171 }
172 
173 //--------------------------------------------------------------------------
174 
175 // Hadronize and decay the next parton-level.
176 
177 bool HadronLevel::next( Event& event) {
178 
179  // Store current event size to mark Parton Level content.
180  event.savePartonLevelSize();
181 
182  // Do Hidden-Valley fragmentation, if necessary.
183  if (useHiddenValley) hiddenvalleyFrag.fragment(event);
184 
185  // Colour-octet onia states must be decayed to singlet + gluon.
186  if (!decayOctetOnia(event)) return false;
187 
188  // Set lifetimes for already existing hadrons, like onia.
189  for (int i = 0; i < event.size(); ++i) if (event[i].isHadron())
190  event[i].tau( event[i].tau0() * rndmPtr->exp() );
191 
192  // Remove junction structures.
193  if (!junctionSplitting.checkColours(event)) {
194  infoPtr->errorMsg("Error in HadronLevel::next: "
195  "failed colour/junction check");
196  return false;
197  }
198 
199  // Possibility of hadronization inside decay, but then no BE second time.
200  bool doBoseEinsteinNow = doBoseEinstein;
201  bool doDeuteronProdNow = doDeuteronProd;
202  bool decaysCausedHadronization;
203  do {
204  decaysCausedHadronization = false;
205 
206  // First part: string fragmentation.
207  if (doHadronize) {
208 
209  // Find the complete colour singlet configuration of the event.
210  // Keep junctions if we do shoving.
211  if (!findSinglets( event, (stringRepulsionPtr != nullptr) ))
212  return false;
213 
214  // Fragment off R-hadrons, if necessary.
215  if (allowRH && !rHadronsPtr->produce( colConfig, event))
216  return false;
217 
218  // Save list with rapidity pairs of the different string pieces.
219  if (closePacking) {
220  vector< vector< pair<double,double> > > rapPairs =
221  rapidityPairs(event);
222  colConfig.rapPairs = rapPairs;
223  }
224 
225  // Let strings interact in rope hadronization treatment.
226  // Do the shoving treatment.
227  if ( stringRepulsionPtr ) {
228 
229  // Extract all string segments from the event and do the
230  // string reulsion.
231  stringRepulsionPtr->stringRepulsion(event, colConfig);
232 
233  // Find singlets again.
234  iParton.resize(0);
235  colConfig.clear();
236  if (!findSinglets( event)) {
237  infoPtr->errorMsg("Error in HadronLevel::next: "
238  "ropes: failed 2nd singlet tracing.");
239  return false;
240  }
241  }
242 
243  // Prepare for flavour ropes.
244  if (fragmentationModifierPtr)
245  fragmentationModifierPtr->initEvent(event, colConfig);
246 
247  // Process all colour singlet (sub)systems.
248  for (int iSub = 0; iSub < colConfig.size(); ++iSub) {
249 
250  // Collect sequentially all partons in a colour singlet subsystem.
251  colConfig.collect(iSub, event);
252  int nBefFrag = event.size();
253 
254  // String fragmentation of each colour singlet (sub)system.
255  if ( colConfig[iSub].massExcess > mStringMin ) {
256  if (!stringFrag.fragment( iSub, colConfig, event)) return false;
257 
258  // Low-mass string treated separately. Tell if diffractive system.
259  } else {
260  bool isDiff = infoPtr->isDiffractiveA()
261  || infoPtr->isDiffractiveB();
262  if (!ministringFrag.fragment( iSub, colConfig, event, isDiff))
263  return false;
264  }
265 
266  // Displace hadron vertices transversely from parton MPI + shower.
267  if (doPartonVertex) partonVertexPtr->vertexHadrons( nBefFrag, event);
268  }
269  }
270 
271  // Second part: sequential decays of short-lived particles (incl. K0).
272 
273  // If rescattering is off, we don't care about the order of the decays.
274  if (doDecay && !doRescatter) {
275  decaysCausedHadronization = decays.decayAll(event, widthSepBE);
276 
277  // If rescattering is on, decays/rescatterings must happen in order.
278  } else if (doRescatter) {
279 
280  if (doBoost) {
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));
284  }
285 
286  // Queue potential decays and rescatterings.
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");
293  return false;
294  }
295 
296  // Get earliest decay/rescattering.
297  PriorityNode node = candidates.top();
298  candidates.pop();
299 
300  // Skip if either particle has already interacted elsewhere.
301  if (!event[node.i1].isFinal()
302  || (!node.isDecay() && !event[node.i2].isFinal())) continue;
303 
304  // Perform the queued action: decay.
305  int oldSize = event.size();
306  if (node.isDecay()) {
307  decays.decay(node.i1, event);
308  // @TODO If there is moreToDo, those things should also
309  // be handled in order?
310  if (decays.moreToDo()) decaysCausedHadronization = true;
311 
312  // Perform the queued action: two-body collision.
313  } else {
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,
318  hadA.m(), hadB.m());
319  if (type == 0) {
320  infoPtr->errorMsg("Error in HadronLevel::next: "
321  "no available rescattering processes", to_string(hadA.id())
322  + " + " + to_string(hadB.id()) + " @ " + to_string(eCM));
323  continue;
324  }
325  if (!lowEnergyProcess.collide(node.i1, node.i2, type, event,
326  node.origin, node.displaced1, node.displaced2)) continue;
327  }
328 
329  // If multiple rescattering is on, check for new interactions.
330  if (scatterManyTimes) queueDecResc(event, oldSize, candidates);
331 
332  // If multiple rescattering is off, decay new hadrons.
333  else if (doDecay) {
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;
341  }
342  }
343  }
344  }
345 
346  if (doBoost) {
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));
350  }
351  }
352 
353  // Third part: include Bose-Einstein effects among current particles.
354  if (doBoseEinsteinNow) {
355  if (!boseEinstein.shiftEvent(event)) return false;
356  doBoseEinsteinNow = false;
357  }
358 
359  // Fourth part: sequential decays also of long-lived particles.
360  if (doDecay) {
361  if (decays.decayAll(event))
362  decaysCausedHadronization = true;
363  }
364 
365  // Fifth part: deuteron production.
366  if (doDeuteronProdNow) {
367  if (!deuteronProd.combine(event)) return false;
368  doDeuteronProdNow = false;
369  decaysCausedHadronization = doDecay;
370  }
371 
372  // Normally done first time around, but sometimes not.
373  // (e.g. Upsilon decay can cause create unstable hadrons).
374  } while (decaysCausedHadronization);
375 
376  // Done.
377  return true;
378 
379 }
380 
381 //--------------------------------------------------------------------------
382 
383 // Allow more decays if on/off switches changed.
384 // Note: does not do sequential hadronization, e.g. for Upsilon.
385 
386 bool HadronLevel::moreDecays( Event& event) {
387 
388  // Colour-octet onia states must be decayed to singlet + gluon.
389  if (!decayOctetOnia(event)) return false;
390 
391  // Loop through all entries to find those that should decay.
392  int iDec = 0;
393  do {
394  if ( event[iDec].isFinal() && event[iDec].canDecay()
395  && event[iDec].mayDecay() ) decays.decay( iDec, event);
396  } while (++iDec < event.size());
397 
398  // Done.
399  return true;
400 
401 }
402 
403 //--------------------------------------------------------------------------
404 
405 // Prepare to be able to pick a low-energy hadron-hadron scattering.
406 
407 bool HadronLevel::initLowEnergyProcesses() {
408 
409  // Prepare for low-energy QCD processes.
410  doNonPertAll = flag("LowEnergyQCD:all");
411  if (!doNonPertAll) {
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);
420  }
421 
422  // Return true if any process is switched on.
423  return doNonPertAll || (nonPertProc.size() > 0);
424 
425 }
426 
427 //--------------------------------------------------------------------------
428 
429 // Pick process for a low-energy hadron-hadron scattering.
430 
431 int HadronLevel::pickLowEnergyProcess(int idA, int idB, double eCM,
432  double mA, double mB) {
433 
434  // Chosen process.
435  int procType;
436 
437  // If all processes are on, just call LowEnergySigma directly.
438  if (doNonPertAll) {
439  procType = lowEnergySigma.pickProcess(idA, idB, eCM, mA, mB);
440  if (procType == 0) {
441  infoPtr->errorMsg("Error in HadronLevel::pickLowEnergyProcess: "
442  "no available processes for specified particles and energy");
443  return 0;
444  }
445 
446  // Trivial choice if only one process.
447  } else if (nonPertProc.size() ==1) {
448  procType = nonPertProc[0];
449 
450  // If only certain processes are on, calculate those cross sections.
451  } else {
452  vector<int> procs;
453  vector<double> sigmas;
454  for (int proc : nonPertProc) {
455  double sigma = lowEnergySigma.sigmaPartial(idA, idB, eCM, mA, mB, proc);
456  if (sigma > 0.) {
457  procs.push_back(proc);
458  sigmas.push_back(sigma);
459  } else {
460  infoPtr->errorMsg("Warning in HadronLevel::pickLowEnergyProcess: "
461  "a process with zero cross section was explicitly turned on",
462  std::to_string(proc));
463  }
464  }
465 
466  // Error if no processes has a positive cross section. Else pick process.
467  if (procs.size() == 0) {
468  infoPtr->errorMsg("Error in HadronLevel::pickLowEnergyProcess: "
469  "no processes with positive cross sections have been turned on");
470  return 0;
471  }
472  procType = procs[rndmPtr->pick(sigmas)];
473  }
474 
475  // Pick specific resonance for proc == 9.
476  if (procType == 9) {
477  procType = lowEnergySigma.pickResonance(idA, idB, eCM);
478  if (procType == 0) {
479  infoPtr->errorMsg("Error in Pythia::nextNonPert: "
480  "no available resonances for the given particles and energy");
481  return 0;
482  }
483  }
484 
485  // Done.
486  return procType;
487 
488 }
489 
490 //--------------------------------------------------------------------------
491 
492 // Decay colour-octet onium states.
493 
494 bool HadronLevel::decayOctetOnia(Event& event) {
495 
496  // Loop over particles and decay any onia encountered.
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;
501 
502  // Set colour flow by hand: gluon inherits octet-onium state.
503  int iGlu = event.size() - 1;
504  event[iGlu].cols( event[iDec].col(), event[iDec].acol() );
505  }
506 
507  // Done.
508  return true;
509 
510 }
511 
512 //--------------------------------------------------------------------------
513 
514 // Trace colour flow in the event to form colour singlet subsystems.
515 // Option will keep junctions in the remainsJunction list,
516 // and not eliminate any junctions by insertion.
517 
518 bool HadronLevel::findSinglets(Event& event, bool keepJunctions) {
519 
520  // Clear up storage.
521  colConfig.clear();
522 
523  // Find a list of final partons and of all colour ends and gluons.
524  if (colTrace.setupColList(event)) return true;
525 
526  // Begin arrange the partons into separate colour singlets.
527 
528  // Junctions: loop over them, and identify kind.
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);
533  iParton.resize(0);
534 
535  // Loop over junction legs.
536  for (int iCol = 0; iCol < 3; ++iCol) {
537  int indxCol = event.colJunction(iJun, iCol);
538  iParton.push_back( -(10 + 10 * iJun + iCol) );
539  // Junctions: find color ends.
540  if (kindJun % 2 == 1 && !colTrace.traceFromAcol(indxCol, event, iJun,
541  iCol, iParton)) return false;
542  // Antijunctions: find anticolor ends.
543  if (kindJun % 2 == 0 && !colTrace.traceFromCol(indxCol, event, iJun,
544  iCol, iParton)) return false;
545  }
546 
547  // A junction may be eliminated by insert if two quarks are nearby.
548  if (!keepJunctions) {
549  int nJunOld = event.sizeJunction();
550  if (!colConfig.insert(iParton, event)) return false;
551  if (event.sizeJunction() < nJunOld) --iJun;
552  }
553  }
554 
555  // Open strings: pick up each colour end and trace to its anticolor end.
556  while (!colTrace.colFinished()) {
557  iParton.resize(0);
558  if (!colTrace.traceFromCol( -1, event, -1, -1, iParton)) return false;
559 
560  // Store found open string system. Analyze its properties.
561  if (!colConfig.insert(iParton, event)) return false;
562  }
563 
564  // Closed strings : begin at any gluon and trace until back at it.
565  while (!colTrace.finished()) {
566  iParton.resize(0);
567  if (!colTrace.traceInLoop(event, iParton)) return false;
568 
569  // Store found closed string system. Analyze its properties.
570  if (!colConfig.insert(iParton, event)) return false;
571  }
572 
573  // Done.
574  return true;
575 
576 }
577 
578 //--------------------------------------------------------------------------
579 
580 // Calculate possible decays and rescatterings and add all to the queue.
581 
582 void HadronLevel::queueDecResc(Event& event, int iStart,
583  priority_queue<HadronLevel::PriorityNode>& queue) {
584 
585  // Loop over all existing or newly added hadrons.
586  for (int iFirst = iStart; iFirst < event.size(); ++iFirst) {
587  Particle& hadA = event[iFirst];
588  if (!hadA.isFinal() || !hadA.isHadron()) continue;
589 
590  // Queue hadrons that should decay.
591  if (doDecay && hadA.canDecay() && hadA.mayDecay()
592  && hadA.mWidth() > widthSepRescatter)
593  queue.push(PriorityNode(iFirst, hadA.vDec()));
594 
595  // Find primary hadron mother, if any.
596  int iNowA = iFirst;
597  int iMotA = event[iNowA].mother1();
598  if (!scatterNeighbours)
599  while (event[iMotA].isHadron() && event[iNowA].mother2() == 0) {
600  iNowA = iMotA;
601  iMotA = event[iNowA].mother1();
602  }
603 
604  // Loop over a second existing hadron to study all pairs.
605  for (int iSecond = 0; iSecond < iFirst; ++iSecond) {
606  Particle& hadB = event[iSecond];
607  if (!hadB.isFinal() || !hadB.isHadron()) continue;
608 
609  // Early skip if particles are moving away from each other.
610  if (scatterQuickCheck && dot3( hadB.p() / hadB.e() - hadA.p() / hadA.e(),
611  hadB.vProd() - hadA.vProd() ) > 0. ) continue;
612 
613  // Skip rescattering among decay products or already scattered.
614  if ( event[hadA.mother1()].isHadron() && hadB.mother1() == hadA.mother1()
615  && hadB.mother2() == hadA.mother2()) continue;
616 
617  // Find primary hadron mother, if any.
618  if (!scatterNeighbours) {
619  int iNowB = iSecond;
620  int iMotB = event[iNowB].mother1();
621  while (event[iMotB].isHadron() && event[iNowB].mother2() == 0) {
622  iNowB = iMotB;
623  iMotB = event[iNowB].mother1();
624  }
625 
626  // Optionally skip if hadrons are nearest neighbours.
627  if (abs(iNowB - iNowA) <= 1) continue;
628  }
629 
630  // Set up positions for each particle in the pair CM frame.
631  RotBstMatrix frame;
632 
633  if (useVelocityFrame)
634  frame.toSameVframe(hadA.p(), hadB.p());
635  else
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);
641 
642  // Rejection of pairs with large impact parameter.
643  double b2 = (vA - vB).pT2();
644  if (b2 > b2Max) continue;
645 
646  // Offset particles to position when the last particle is created.
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();
650 
651  // Abort if particles have already passed each other.
652  if (zA >= zB) continue;
653 
654  // Optionally allow regeneration time delay.
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;
663  if (regA || regB) {
664  if (regA) vA += tauRegeneration * FM2MM * rndmPtr->exp()
665  * pA / hadA.m();
666  if (regB) vB += tauRegeneration * FM2MM * rndmPtr->exp()
667  * pB / hadB.m();
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;
672  }
673  }
674 
675  // Calculate sigma and abort if impact parameter is too large.
676  double eCM = (pA + pB).mCalc();
677  double sigma = lowEnergySigma.sigmaTotal(hadA.id(), hadB.id(), eCM,
678  hadA.m(), hadB.m());
679  double b2Crit = MB2FMSQ * pow2(FM2MM) * sigma / (impactOpacity * M_PI);
680  double pAccept;
681  // Sharp edge or Gaussian profile.
682  if (impactModel == 0) pAccept = (b2 < b2Crit) ? impactOpacity : 0.;
683  else pAccept = impactOpacity * exp(-b2 / b2Crit);
684  if (rndmPtr->flat() > pAccept) continue;
685 
686  // Calculate origin of collision and transform to lab frame.
687  // Also particle scattering vertices for elastic and excitation.
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() );
693  frame.invert();
694  origin.rotbst(frame);
695  displacedA.rotbst(frame);
696  displacedB.rotbst(frame);
697 
698  // Queue hadron pair that should rescatter.
699  queue.push( PriorityNode(iFirst, iSecond, origin, displacedA,
700  displacedB) );
701  }
702  }
703 }
704 
705 //--------------------------------------------------------------------------
706 
707 // Extract rapidity pairs of string pieces.
708 
709 vector< vector< pair<double,double> > > HadronLevel::rapidityPairs(
710  Event& event) {
711 
712  // Loop over all string systems in the event.
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;
717 
718  // Special treatment for junction systems.
719  if (colConfig[iSub].hasJunction) {
720  // Pick smallest and largest rapidity parton.
721  double ymi = 1e10;
722  double yma = -1e10;
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;
730  }
731  rapsNow.push_back( make_pair(ymi, yma) );
732 
733  // Normal strings. For closed gluon loop include first-last pair.
734  } else {
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) );
745  }
746  }
747  rapPairs.push_back(rapsNow);
748  }
749  // Done.
750  return rapPairs;
751 }
752 
753 //==========================================================================
754 
755 } // end namespace Pythia8
Definition: AgUStep.h:26