StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
LowEnergyProcess.cc
1 // LowEnergyProcess.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 LowEnergyProcess
7 // class.
8 
9 #include "Pythia8/LowEnergyProcess.h"
10 
11 namespace Pythia8 {
12 
13 //==========================================================================
14 
15 // LowEnergyProcess class.
16 // This class handles low-energy collisions between two hadrons.
17 
18 //--------------------------------------------------------------------------
19 
20 // Constants: could be changed here if desired, but normally should not.
21 // These are of technical nature, as described for each.
22 
23 // Maximum number of tries to split beam particles before reconnection.
24 static constexpr int MAXLOOP = 100;
25 
26 // Gradually reduce assumed quark masses from their constituent values.
27 static constexpr double MASSREDUCERATE = 0.025;
28 
29 // Parameters for diffractive mass spectrum, as in the SaS parametrization.
30 static constexpr double MDIFFMIN = 0.28;
31 static constexpr double CRES = 2.0;
32 static constexpr double MRES0 = 1.062;
33 
34 // The pion mass; used to check whether there is room for one more hadron.
35 static constexpr double MPI = 0.14;
36 
37 // K mass; used to check if eta can split into ssbar.
38 static constexpr double MK = 0.498;
39 
40 // Diquark-antidiquark system need extra mass excess for string handling.
41 static constexpr double MEXTRADIQDIQ = 0.5;
42 
43 // Pomeron trajectory alpha(t) = 1 + epsilon + alpha' * t.
44 static constexpr double ALPHAPRIME = 0.25;
45 
46 //--------------------------------------------------------------------------
47 
48 // Initialize the LowEnergyProcess class as required.
49 
50 void LowEnergyProcess::init( StringFlav* flavSelPtrIn,
51  StringFragmentation* stringFragPtrIn,
52  MiniStringFragmentation* ministringFragPtrIn,
53  LowEnergySigma* lowEnergySigmaPtrIn,
54  NucleonExcitations* nucleonExcitationsPtrIn) {
55 
56  // Save pointers.
57  flavSelPtr = flavSelPtrIn;
58  stringFragPtr = stringFragPtrIn;
59  ministringFragPtr = ministringFragPtrIn;
60  lowEnergySigmaPtr = lowEnergySigmaPtrIn,
61  nucleonExcitationsPtr = nucleonExcitationsPtrIn;
62 
63  // Relative fraction of s quark production in strin breaks.
64  probStoUD = parm("StringFlav:probStoUD");
65 
66  // Mixing for eta and eta'.
67  double theta = parm("StringFlav:thetaPS");
68  double alpha = (theta + 54.7) * M_PI / 180.;
69  fracEtass = pow2(sin(alpha));
70  fracEtaPss = 1. - fracEtass;
71 
72  // Longitudinal momentum sharing of valence quarks in hadrons.
73  xPowMes = parm("BeamRemnants:valencePowerMeson");
74  xPowBar = 0.5 * ( parm("BeamRemnants:valencePowerUinP")
75  + parm("BeamRemnants:valencePowerDinP") );
76  xDiqEnhance = parm("BeamRemnants:valenceDiqEnhance");
77 
78  // Transverse momentum spread.
79  sigmaQ = parm("StringPT:sigma") / sqrt(2.);
80 
81  // Boundary mass between string and ministring handling.
82  mStringMin = parm("HadronLevel:mStringMin");
83 
84  // Proton mass used as reference scale in diffraction.
85  sProton = pow2(particleDataPtr->m0(2212));
86 
87  // Probability of double annihilation when flavours allow.
88  probDoubleAnn = parm("LowEnergyQCD:probDoubleAnnihilation");
89 
90  // Initialize collision event record.
91  leEvent.init( "(low energy event)", particleDataPtr);
92 
93  // Done.
94  isInit = true;
95 }
96 
97 //--------------------------------------------------------------------------
98 
99 // Produce outgoing primary hadrons from collision of incoming pair.
100 // type | 1: nondiff; | 2 : el; | 3: SD (XB); | 4: SD (AX);
101 // | 5: DD; | 6: CD (AXB, not implemented)
102 // | 7: excitation | 8: annihilation | 9: resonant
103 // | >100: resonant through the specified resonance particle
104 
105 bool LowEnergyProcess::collide( int i1, int i2, int typeIn, Event& event,
106  Vec4 vtx, Vec4 vtx1, Vec4 vtx2) {
107 
108  // Check that class is initialized and that incoming are hadrons.
109  if (!isInit) {
110  infoPtr->errorMsg("Error in LowEnergyProcess::collide: "
111  "not initialized!");
112  return false;
113  }
114  if (!event[i1].isHadron() || !event[i2].isHadron()) return false;
115  sizeOld = event.size();
116 
117  // Store information about incoming particles.
118  type = typeIn;
119  id1 = event[i1].id();
120  id2 = event[i2].id();
121  isBaryon1 = ( (abs(id1)/1000)%10 > 0 );
122  isBaryon2 = ( (abs(id2)/1000)%10 > 0 );
123  m1 = event[i1].m();
124  m2 = event[i2].m();
125  eCM = (event[i1].p() + event[i2].p()).mCalc();
126  sCM = eCM * eCM;
127 
128  // Pick K0/K0bar combination if both particles are K_S/K_L.
129  if ((id1 == 310 || id1 == 130) && (id2 == 310 || id2 == 130)) {
130  double sigmaSame = lowEnergySigmaPtr->sigmaPartial(311, 311, eCM,
131  m1, m2, type);
132  double sigmaMix = lowEnergySigmaPtr->sigmaPartial(311, -311, eCM,
133  m1, m2, type);
134  int choice = rndmPtr->pick({ 0.25 * sigmaSame, 0.25 * sigmaSame,
135  0.50 * sigmaMix });
136  if (choice == 0) id1 = id2 = 311;
137  else if (choice == 1) id1 = id2 = -311;
138  else { id1 = 311; id2 = -311; }
139  }
140 
141  // Pick K0 or K0bar if either particle is K_S or K_L.
142  if (id1 == 310 || id1 == 130) {
143  double sigmaK = lowEnergySigmaPtr->sigmaPartial( 311, id2, eCM,
144  m1, m2, type);
145  double sigmaKbar = lowEnergySigmaPtr->sigmaPartial(-311, id2, eCM,
146  m1, m2, type);
147  id1 = (rndmPtr->pick({ sigmaK, sigmaKbar }) == 0) ? 311 : -311;
148  }
149  else if (id2 == 310 || id2 == 130) {
150  double sigmaK = lowEnergySigmaPtr->sigmaPartial(id1, 311, eCM,
151  m1, m2, type);
152  double sigmaKbar = lowEnergySigmaPtr->sigmaPartial(id1, -311, eCM,
153  m1, m2, type);
154  id2 = (rndmPtr->pick({ sigmaK, sigmaKbar }) == 0) ? 311 : -311;
155  }
156 
157  // Reset leEvent event record. Add incoming hadrons as beams in rest frame.
158  leEvent.reset();
159  leEvent.append( event[i1]);
160  leEvent.append( event[i2]);
161  leEvent[1].status( -12);
162  leEvent[2].status( -12);
163  RotBstMatrix MtoCM = toCMframe( leEvent[1].p(), leEvent[2].p());
164  leEvent.rotbst( MtoCM);
165 
166  // Get code from type; the same except for resonant process.
167  int code;
168  if (type >= 1 && type <= 8 && type != 6) code = type;
169  else if (abs(type) > 100) code = 9;
170  else {
171  infoPtr->errorMsg( "Error in LowEnergyProcess::collide: "
172  "invalid process type", std::to_string(type));
173  return false;
174  }
175 
176  // Perform collision specified by code.
177  if (code == 1) { if (!nondiff()) return false; }
178  else if (code >= 2 && code <= 5) { if (!eldiff()) return false; }
179  else if (code == 7) { if (!excitation()) return false; }
180  else if (code == 8) { if (!annihilation()) return false; }
181  else if (code == 9) { if (!resonance()) return false; }
182 
183  // Store number of direct daughters of the original colliding hadrons.
184  int nPrimaryProds = leEvent.size() - 3;
185 
186  nHadron = (code == 3 || code == 5) ? 0 : 1;
187 
188  // Hadronize new strings if necessary.
189  if (code == 1 || code == 3 || code == 4 || code == 5 || code == 8) {
190  if (!simpleHadronization()) {
191  infoPtr->errorMsg( "Error in LowEnergyProcess::collide: "
192  "hadronization failed");
193  return false;
194  }
195  }
196 
197  // Mother incides for the direct daughters.
198  int mother1 = max(i1, i2), mother2 = min(i1, i2);
199 
200  // Offset between position in low energy event and position in full event.
201  int indexOffset = sizeOld - 3;
202 
203  // Copy particles into regular event record.
204  for (int i = 3; i < leEvent.size(); ++i) {
205  int iNew = event.append(leEvent[i]);
206 
207  // For direct daughters, set mothers to the original particles.
208  if ( leEvent[i].mother1() == 1 || leEvent[i].mother1() == 2
209  || leEvent[i].mother2() == 1 || leEvent[i].mother2() == 2 ) {
210  event[iNew].mothers(mother1, mother2);
211  }
212  // For subsequent daughters, use offset indices.
213  else {
214  event[iNew].mother1(indexOffset + leEvent[i].mother1());
215  event[iNew].mother2(indexOffset + leEvent[i].mother2());
216  }
217 
218  // Set status, lifetime if final and daughters if not.
219  if (event[iNew].isFinal()) {
220  event[iNew].status(150 + code);
221  if (event[iNew].isHadron())
222  event[iNew].tau( event[iNew].tau0() * rndmPtr->exp() );
223  } else {
224  event[iNew].status(-(150 + code));
225  event[iNew].daughter1(indexOffset + leEvent[i].daughter1());
226  event[iNew].daughter2(indexOffset + leEvent[i].daughter2());
227  }
228  }
229 
230  // Set daughters for original particles.
231  event[i1].daughters(sizeOld, sizeOld + nPrimaryProds - 1);
232  event[i2].daughters(sizeOld, sizeOld + nPrimaryProds - 1);
233 
234  // Boost particles from subcollision frame to full event frame.
235  RotBstMatrix MfromCM = fromCMframe( event[i1].p(), event[i2].p());
236  if (code == 1 || code == 6 || code > 7) {
237  for (int i = sizeOld; i < event.size(); ++i) {
238  event[i].rotbst( MfromCM);
239  event[i].vProdAdd( vtx);
240  }
241 
242  // Special case for t-channel processes with displaced production vertices.
243  // nHadron & nParton is number in first system, i.e. where to switch.
244  } else {
245  int iHadron = 0;
246  int nParton = (code == 3 || code == 5) ? 2 : 0;
247  int iParton = 0;
248  for (int i = sizeOld; i < event.size(); ++i) {
249  event[i].rotbst( MfromCM);
250  if (event[i].status() > 0)
251  event[i].vProdAdd( (++iHadron <= nHadron) ? vtx1 : vtx2 );
252  else event[i].vProdAdd( (++iParton <= nParton) ? vtx1 : vtx2 );
253  }
254  }
255 
256  // Mark incoming colliding hadrons as decayed.
257  event[i1].statusNeg();
258  event[i2].statusNeg();
259 
260  // Done.
261  return true;
262 
263 }
264 
265 //--------------------------------------------------------------------------
266 
267 // Do an inelastic nondiffractive scattering.
268 
269 bool LowEnergyProcess::nondiff() {
270 
271  // Resolve flavours and check minimum new hadron masses.
272  pair< int, int> paircac1 = splitFlav( id1 );
273  idc1 = paircac1.first;
274  idac1 = paircac1.second;
275  pair< int, int> paircac2 = splitFlav( id2 );
276  idc2 = paircac2.first;
277  idac2 = paircac2.second;
278  mThr1 = mThreshold( idc1, idac2);
279  mThr2 = mThreshold( idc2, idac1);
280 
281  // Special two-body handling if below three-body threshold.
282  if (eCM < mThr1 + mThr2 + MPI) return twoBody();
283 
284  // Special three-body handling if below four-body threshold.
285  if (eCM < mThr1 + mThr2 + 2. * MPI) return threeBody();
286 
287  // Check that not stuck in infinite loop. Allow reduced quark masses.
288  int loop = 0;
289  double e1, pz1, epz1, pzc1, ec1, epz2, pzc2, ec2, mAbove1, mAbove2;
290  Vec4 pc1, pac1, pc2, pac2;
291  do {
292  do {
293  if (++loop == MAXLOOP) return threeBody();
294  double redStep = (loop < 10) ? 1. : exp( -MASSREDUCERATE * (loop - 9));
295 
296  // Split up hadrons A and B into q + qbar or q + qq for meson/baryon.
297  splitA( eCM, redStep);
298  splitB( eCM, redStep);
299 
300  // Assign relative sharing of longitudinal momentum.
301  z1 = splitZ( idc1, idac1, mTc1 / eCM, mTac1 / eCM);
302  z2 = splitZ( idc2, idac2, mTc2 / eCM, mTac2 / eCM);
303  mT1 = sqrt( mTsc1 / z1 + mTsac1 / (1. - z1));
304  mT2 = sqrt( mTsc2 / z2 + mTsac2 / (1. - z2));
305 
306  // Ensure that hadron beam remnants are not too massive.
307  } while (mT1 + mT2 > eCM);
308 
309  // Set up kinematics for outgoing beam remnants.
310  e1 = 0.5 * (sCM + mT1 * mT1 - mT2 * mT2) / eCM;
311  pz1 = sqrtpos(e1 * e1 - mT1 * mT1);
312  epz1 = z1 * (e1 + pz1);
313  pzc1 = 0.5 * (epz1 - mTsc1 / epz1 );
314  ec1 = 0.5 * (epz1 + mTsc1 / epz1 );
315  pc1.p( px1, py1, pzc1, ec1 );
316  pac1.p( -px1, -py1, pz1 - pzc1, e1 - ec1 );
317  epz2 = z2 * (eCM - e1 + pz1);
318  pzc2 = -0.5 * (epz2 - mTsc2 / epz2 );
319  ec2 = 0.5 * (epz2 + mTsc2 / epz2 );
320  pc2.p( px2, py2, pzc2, ec2 );
321  pac2.p( -px2, -py2, -pz1 - pzc2, eCM - e1 - ec2 );
322 
323  // Catch reconnected systems with too small masses.
324  mAbove1 = (pc1 + pac2).mCalc() - mThreshold( idc1, idac2);
325  mAbove2 = (pc2 + pac1).mCalc() - mThreshold( idc2, idac1);
326  } while ( max( mAbove1, mAbove2) < MPI || min( mAbove1, mAbove2) < 0. );
327 
328  // Store new reconnected string systems; lowest excess first.
329  if (mAbove1 < mAbove2) {
330  leEvent.append( idc1, 63, 1, 0, 0, 0, 101, 0, pc1, mc1);
331  leEvent.append( idac2, 63, 2, 0, 0, 0, 0, 101, pac2, mac2);
332  leEvent.append( idc2, 63, 2, 0, 0, 0, 102, 0, pc2, mc2);
333  leEvent.append( idac1, 63, 1, 0, 0, 0, 0, 102, pac1, mac1);
334  } else {
335  leEvent.append( idc2, 63, 2, 0, 0, 0, 102, 0, pc2, mc2);
336  leEvent.append( idac1, 63, 1, 0, 0, 0, 0, 102, pac1, mac1);
337  leEvent.append( idc1, 63, 1, 0, 0, 0, 101, 0, pc1, mc1);
338  leEvent.append( idac2, 63, 2, 0, 0, 0, 0, 101, pac2, mac2);
339  }
340 
341  // Done.
342  return true;
343 
344 }
345 
346 //--------------------------------------------------------------------------
347 
348 // Do an elastic or diffractive scattering.
349 
350 bool LowEnergyProcess::eldiff() {
351 
352  // Classify process type.
353  bool excite1 = (type == 3 || type == 5);
354  bool excite2 = (type == 4 || type == 5);
355 
356  // Check if low-mass diffraction partly covered by excitation processes.
357  bool hasExcitation = lowEnergySigmaPtr->hasExcitation( id1, id2);
358 
359  // Find excited mass ranges.
360  mA = m1;
361  mB = m2;
362  double mAmin = (excite1) ? mDiffThr(id1, m1) : m1;
363  double mBmin = (excite2) ? mDiffThr(id2, m2) : m2;
364  double mAmax = eCM - mBmin;
365  double mBmax = eCM - mAmin;
366  if (mAmin + mBmin > eCM) {
367  infoPtr->errorMsg("Error in LowEnergyProcess::eldiff: "
368  "too low invariant mass for diffraction",
369  "for " + to_string(id1) + " " + to_string(id2)
370  + " with type=" + to_string(type) + " @ " + to_string(eCM) + " GeV");
371  return false;
372  }
373 
374  // Useful kinematics definitions. Also some for diffraction.
375  double s1 = m1 * m1;
376  double s2 = m2 * m2;
377  double sA = mA * mA;
378  double sB = mB * mB;
379  double lam12 = sqrtpos(pow2( sCM - s1 - s2) - 4. * s1 * s2);
380  double sResXB = pow2(mA + MRES0);
381  double sResAX = pow2(mB + MRES0);
382 
383  // Find maximal t range.
384  double sAmin = mAmin * mAmin;
385  double sBmin = mBmin * mBmin;
386  double lamAB = sqrtpos(pow2( sCM - sAmin - sBmin) - 4. * sAmin * sBmin);
387  double tempA = sCM - (s1 + s2 + sAmin + sBmin) + (s1 - s2) * (sAmin - sBmin)
388  / sCM;
389  double tempB = lam12 * lamAB / sCM;
390  double tLowX = -0.5 * (tempA + tempB);
391  double wtA, wtB, tempC, tLow, tUpp, tNow;
392  double bNow = (type == 2) ? bSlope() : 2.;
393 
394  // Outer loop over t values to be matched against masses.
395  int loopT = 0;
396  bool failT = false;
397  do {
398  failT = false;
399  if (++loopT == MAXLOOP) {
400  infoPtr->errorMsg("Error in LowEnergyProcess::eldiff: "
401  "failed to construct valid kinematics (t)");
402  return false;
403  }
404 
405  // Inner loop over masses of either or both excited beams.
406  // Check that not stuck in infinite loop. Allow reduced quark masses.
407  int loopM = 0;
408  bool failM = false;
409  do {
410  failM = false;
411  if (++loopM == MAXLOOP) {
412  infoPtr->errorMsg("Error in LowEnergyProcess::eldiff: "
413  "failed to construct valid kinematics (m)");
414  return false;
415  }
416  double redStep = (loopM < 10) ? 1. : exp( -MASSREDUCERATE * (loopM - 9));
417 
418  // Split up hadron 1 (on side A) and assign excited A mass.
419  if (excite1) {
420  do {
421  mA = mAmin * pow( mAmax / mAmin, rndmPtr->flat() );
422  sA = mA * mA;
423  wtA = (hasExcitation) ? 1.
424  : (1. + CRES * sResXB / (sResXB + sA)) / (1. + CRES);
425  } while (wtA < rndmPtr->flat());
426  splitA( mA, redStep);
427  if (mTc1 + mTac1 > mA) failM = true;
428  }
429 
430 
431  // Split up hadron 2 (on side B) and assign excited B mass.
432  if (excite2 && !failM) {
433  do {
434  mB = mBmin * pow( mBmax / mBmin, rndmPtr->flat() );
435  sB = mB * mB;
436  wtB = (hasExcitation) ? 1.
437  : (1. + CRES * sResAX / (sResAX + sB)) / (1. + CRES);
438  } while (wtB < rndmPtr->flat());
439  splitB( mB, redStep);
440  if (mTc2 + mTac2 > mB) failM = true;
441  }
442 
443  // Ensure that pair of hadron masses not too large. Suppression at limit.
444  if (mA + mB > eCM) failM = true;
445  if (!failM) {
446  double wtM = 1.;
447  if (type == 3) wtM = 1. - sA / sCM;
448  else if (type == 4) wtM = 1. - sB / sCM;
449  else if (type == 5) wtM = (1. - pow2(mA + mB) / sCM)
450  * sCM * sProton / (sCM * sProton + sA * sB);
451  if (wtM < rndmPtr->flat()) failM = true;
452  }
453  } while (failM);
454 
455  // Calculate allowed t range.
456  lamAB = sqrtpos(pow2( sCM - sA - sB) - 4. * sA * sB);
457  tempA = sCM - (s1 + s2 + sA + sB) + (s1 - s2) * (sA - sB) / sCM;
458  tempB = lam12 * lamAB / sCM;
459  tempC = (sA - s1) * (sB - s2) + (s1 + sB - s2 - sA)
460  * (s1 * sB - s2 * sA) / sCM;
461  tLow = -0.5 * (tempA + tempB);
462  tUpp = tempC / tLow;
463 
464  // Pick t in maximal range and check if within allowed range.
465  if (type != 2) bNow = bSlope();
466  tNow = log(1. - rndmPtr->flat() * (1. - exp(bNow * tLowX))) / bNow;
467  if (tNow < tLow || tNow > tUpp) failT = true;
468  } while (failT);
469 
470  // Energies and longitudinal momenta of excited hadrons.
471  double eA = 0.5 * (sCM + sA - sB) / eCM;
472  double pzA = sqrtpos(eA * eA - sA);
473  Vec4 pA( 0., 0., pzA, eA);
474  Vec4 pB( 0., 0., -pzA, eCM - eA);
475 
476  // Internal kinematics on side A, boost to CM frame and store constituents.
477  if (excite1) {
478  double ec1 = 0.5 * (sA + mTsc1 - mTsac1) / mA;
479  double pzc1 = sqrtpos(ec1 * ec1 - mTsc1);
480  // Diquark always forward. Randomize for meson.
481  if ( abs(idac1) > 10 || (abs(idc1) < 10 && abs(idac1) < 10
482  && rndmPtr->flat() > 0.5) ) pzc1 = -pzc1;
483  Vec4 pc1( px1, py1, pzc1, ec1);
484  Vec4 pac1( -px1, -py1, -pzc1, mA - ec1);
485  pc1.bst(pA);
486  pac1.bst(pA);
487  leEvent.append( idc1, 63, 1, 0, 0, 0, 101, 0, pc1, mc1);
488  leEvent.append( idac1, 63, 1, 0, 0, 0, 0, 101, pac1, mac1);
489 
490  // Simple copy if not excited, and set momentum as in collision frame.
491  } else {
492  int iNew = leEvent.copy( 1, 63);
493  leEvent[iNew].p( pA);
494  leEvent[iNew].vProd( 0., 0., 0., 0.);
495  }
496 
497  // Internal kinematics on side B, boost to CM frame and store constituents.
498  if (excite2) {
499  double ec2 = 0.5 * (sB + mTsc2 - mTsac2) / mB;
500  double pzc2 = -sqrtpos(ec2 * ec2 - mTsc2);
501  // Diquark always forward (on negative side). Randomize for meson.
502  if ( abs(idac2) > 10 || (abs(idc2) < 10 && abs(idac2) < 10
503  && rndmPtr->flat() > 0.5) ) pzc2 = -pzc2;
504  Vec4 pc2( px2, py2, pzc2, ec2);
505  Vec4 pac2( -px2, -py2, -pzc2, mB - ec2);
506  pc2.bst(pB);
507  pac2.bst(pB);
508  leEvent.append( idc2, 63, 2, 0, 0, 0, 102, 0, pc2, mc2);
509  leEvent.append( idac2, 63, 2, 0, 0, 0, 0, 102, pac2, mac2);
510 
511  // Simple copy if not excited, and set momentum as in collision frame.
512  } else {
513  int iNew = leEvent.copy( 2, 63);
514  leEvent[iNew].p( pB);
515  leEvent[iNew].vProd( 0., 0., 0., 0.);
516  }
517 
518  // Reconstruct theta angle and rotate outgoing particles accordingly.
519  double cosTheta = min(1., max(-1., (tempA + 2. * tNow) / tempB));
520  double sinTheta = 2. * sqrtpos( -(tempC + tempA * tNow + tNow * tNow) )
521  / tempB;
522  double theta = asin( min(1., sinTheta));
523  if (cosTheta < 0.) theta = M_PI - theta;
524  if (!std::isfinite(theta)) {
525  infoPtr->errorMsg("Error in LowEnergyProcess::eldiff: "
526  "t is not finite");
527  return false;
528  }
529  double phi = 2. * M_PI * rndmPtr->flat();
530  for (int i = 3; i < leEvent.size(); ++i) leEvent[i].rot( theta, phi);
531 
532  // Done.
533  return true;
534 
535 }
536 
537 //-------------------------------------------------------------------------
538 
539 // Do an excitation collision.
540 
541 bool LowEnergyProcess::excitation() {
542 
543  // Generate excited hadrons and masses.
544  int idA, idB;
545  if (!nucleonExcitationsPtr->pickExcitation(id1, id2, eCM, idA, mA, idB, mB))
546  return false;
547 
548  // Calculate allowed t range.
549  double s1 = m1 * m1;
550  double s2 = m2 * m2;
551  double sA = mA * mA;
552  double sB = mB * mB;
553  double lam12 = sqrtpos(pow2( sCM - s1 - s2) - 4. * s1 * s2);
554  double lamAB = sqrtpos(pow2( sCM - sA - sB) - 4. * sA * sB);
555  double tempA = sCM - (s1 + s2 + sA + sB) + (s1 - s2) * (sA - sB) / sCM;
556  double tempB = lam12 * lamAB / sCM;
557  double tempC = (sA - s1) * (sB - s2) + (s1 + sB - s2 - sA)
558  * (s1 * sB - s2 * sA) / sCM;
559  double tLow = -0.5 * (tempA + tempB);
560  double tUpp = tempC / tLow;
561 
562  // Find t slope as in diffraction and calculate t.
563  int typeSave = type;
564  if (idA == id1 && idB == id2) type = 2;
565  else if (idB == id2) type = 3;
566  else if (idA == id1) type = 4;
567  else type = 5;
568  double bNow = bSlope();
569  type = typeSave;
570  double tNow = tUpp + log(1. - rndmPtr->flat()
571  * (1. - exp(bNow * (tLow - tUpp)))) / bNow;
572 
573  // Set up kinematics along the +- z direction.
574  double eA = 0.5 * (sCM + sA - sB) / eCM;
575  double pzA = sqrtpos(eA * eA - sA);
576  Vec4 pA( 0., 0., pzA, eA);
577  Vec4 pB( 0., 0., -pzA, eCM - eA);
578  int iA = leEvent.append(idA, 157, 1,2, 0,0, 0,0, pA, mA);
579  int iB = leEvent.append(idB, 157, 1,2, 0,0, 0,0, pB, mB);
580 
581  // Rotate suitably,
582  double cosTheta = min(1., max(-1., (tempA + 2. * tNow) / tempB));
583  double sinTheta = 2. * sqrtpos( -(tempC + tempA * tNow + tNow * tNow) )
584  / tempB;
585  double theta = asin( min(1., sinTheta));
586  if (cosTheta < 0.) theta = M_PI - theta;
587  double phi = 2. * M_PI * rndmPtr->flat();
588  leEvent[iA].rot( theta, phi);
589  leEvent[iB].rot( theta, phi);
590 
591  // Done.
592  return true;
593 }
594 
595 //--------------------------------------------------------------------------
596 
597 // Do an annihilation collision of a baryon-antibaryon pair.
598 
599 bool LowEnergyProcess::annihilation() {
600 
601  // Check that indeed baryon-antibaryon collision.
602  if (!isBaryon1 || !isBaryon2
603  || (id1 > 0 ? 1 : -1) * (id2 > 0 ? 1 : -1) > 0) {
604  infoPtr->errorMsg( "Error in LowEnergyProcess::annihilation: "
605  "not a baryon-antibaryon incoming pair",
606  std::to_string(id1) + " + " + std::to_string(id2));
607  return false;
608  }
609 
610  // Working areas.
611  int iqAll[2][3];
612  vector<int> iqPair;
613 
614  // Split first and second hadron by flavour content.
615  for (int iHad = 0; iHad < 2; ++iHad) {
616  int idAbs = (iHad == 0) ? abs(id1) : abs(id2);
617  iqAll[iHad][0] = (idAbs/1000)%10;
618  iqAll[iHad][1] = (idAbs/100)%10;
619  iqAll[iHad][2] = (idAbs/10)%10;
620  }
621 
622  // Find potential annihilating quark-antiquark pairs.
623  for (int i1 = 0; i1 < 3; ++i1)
624  for (int i2 = 0; i2 < 3; ++i2)
625  if (iqAll[1][i2] == iqAll[0][i1]) iqPair.push_back(10 * i1 + i2);
626 
627  // Return if no annihilation possible.
628  if (iqPair.size() == 0) {
629  infoPtr->errorMsg( "Error in LowEnergyProcess::annihilation: "
630  "flavour content does not allow annihilation");
631  return false;
632  }
633 
634  // Annihilate one quark-antiquark pair at random among options.
635  int iAnn = max( 0, min( int(iqPair.size()) - 1,
636  int(iqPair.size() * rndmPtr->flat()) ));
637  iqAll[0][iqPair[iAnn]/10] = iqAll[0][2];
638  iqAll[1][iqPair[iAnn]%10] = iqAll[1][2];
639 
640  // Check if second annihilation is possible and wanted.
641  iqPair.clear();
642  for (int i1 = 0; i1 < 2; ++i1)
643  for (int i2 = 0; i2 < 2; ++i2)
644  if (iqAll[1][i2] == iqAll[0][i1]) iqPair.push_back(10 * i1 + i2);
645 
646  // Annihilate second pair if possible and chosen.
647  if ( (iqPair.size() > 0) && (rndmPtr->flat() < probDoubleAnn) ) {
648  iAnn = max( 0, min( int(iqPair.size()) - 1,
649  int(iqPair.size() * rndmPtr->flat()) ));
650  iqAll[0][iqPair[iAnn]/10] = iqAll[0][1];
651  iqAll[1][iqPair[iAnn]%10] = iqAll[1][1];
652 
653  // Extract leftover partons and their masses. Scale down if masses too big.
654  int id1Ann = (id1 > 0) ? iqAll[0][0] : -iqAll[0][0];
655  int id2Ann = (id2 > 0) ? iqAll[1][0] : -iqAll[1][0];
656  double m1Ann = particleDataPtr->m0( id1Ann);
657  double m2Ann = particleDataPtr->m0( id2Ann);
658  if (m1Ann + m2Ann > 0.8 * eCM) {
659  double scaledown = 0.8 * eCM / (m1Ann + m2Ann);
660  m1Ann *= scaledown;
661  m2Ann *= scaledown;
662  }
663 
664  // Set up kinematics and done for two annihilations.
665  double e1Ann = 0.5 * (sCM + m1Ann*m1Ann - m2Ann*m2Ann) / eCM;
666  double pzAnn = sqrtpos(e1Ann*e1Ann - m1Ann*m1Ann);
667  Vec4 p1Ann( 0., 0., pzAnn, e1Ann );
668  Vec4 p2Ann( 0., 0., -pzAnn, eCM - e1Ann );
669  int col1 = (id1 > 0) ? 101 : 0;
670  int acol1 = (id1 > 0) ? 0 : 101;
671  leEvent.append( id1Ann, 63, 1, 2, 0, 0, col1, acol1, p1Ann, m1Ann);
672  leEvent.append( id2Ann, 63, 1, 2, 0, 0, acol1, col1, p2Ann, m2Ann);
673  return true;
674  }
675 
676  // Begin handling of two strings/pairs. Labels as if each hadron remnant
677  // is a colour plus an anticolour quark, so as to reuse nondiffractive code.
678  idc1 = (id1 > 0) ? iqAll[0][0] : -iqAll[0][0];
679  idac1 = (id1 > 0) ? iqAll[0][1] : -iqAll[0][1] ;
680  idc2 = (id2 > 0) ? iqAll[1][0] : -iqAll[1][0];
681  idac2 = (id2 > 0) ? iqAll[1][1] : -iqAll[1][1] ;
682  if (rndmPtr->flat() < 0.5) swap(idc2, idac2);
683 
684  // Check that not stuck in infinite loop. Allow reduced quark masses.
685  int loop = 0;
686  double e1, pz1, epz1, pzc1, ec1, epz2, pzc2, ec2, mAbove1, mAbove2;
687  Vec4 pc1, pac1, pc2, pac2;
688  do {
689  do {
690  if (++loop == MAXLOOP) {
691  infoPtr->errorMsg( "Error in LowEnergyProcess::annihilation: "
692  "failed to find working kinematics configuration");
693  return false;
694  }
695  double redStep = (loop < 10) ? 1. : exp( -MASSREDUCERATE * (loop - 9));
696 
697  // Split up hadrons A and B by relative pT.
698  splitA( eCM, redStep, false);
699  splitB( eCM, redStep, false);
700 
701  // Assign relative sharing of longitudinal momentum.
702  z1 = splitZ( idc1, idac1, mTc1 / eCM, mTac1 / eCM);
703  z2 = splitZ( idc2, idac2, mTc2 / eCM, mTac2 / eCM);
704  mT1 = sqrt( mTsc1 / z1 + mTsac1 / (1. - z1));
705  mT2 = sqrt( mTsc2 / z2 + mTsac2 / (1. - z2));
706 
707  // Ensure that hadron beam remnants are not too massive.
708  } while (mT1 + mT2 > eCM);
709 
710  // Set up kinematics for outgoing beam remnants.
711  e1 = 0.5 * (sCM + mT1 * mT1 - mT2 * mT2) / eCM;
712  pz1 = sqrtpos(e1 * e1 - mT1 * mT1);
713  epz1 = z1 * (e1 + pz1);
714  pzc1 = 0.5 * (epz1 - mTsc1 / epz1 );
715  ec1 = 0.5 * (epz1 + mTsc1 / epz1 );
716  pc1.p( px1, py1, pzc1, ec1 );
717  pac1.p( -px1, -py1, pz1 - pzc1, e1 - ec1 );
718  epz2 = z2 * (eCM - e1 + pz1);
719  pzc2 = -0.5 * (epz2 - mTsc2 / epz2 );
720  ec2 = 0.5 * (epz2 + mTsc2 / epz2 );
721  pc2.p( px2, py2, pzc2, ec2 );
722  pac2.p( -px2, -py2, -pz1 - pzc2, eCM - e1 - ec2 );
723 
724  // Catch reconnected systems with too small masses.
725  mAbove1 = (pc1 + pac2).mCalc() - mThreshold( idc1, idac2);
726  mAbove2 = (pc2 + pac1).mCalc() - mThreshold( idc2, idac1);
727  } while ( max( mAbove1, mAbove2) < MPI || min( mAbove1, mAbove2) < 0. );
728 
729  // Store new reconnected string systems; lowest excess first.
730  int col1 = (id1 > 0) ? 101 : 0;
731  int acol1 = (id1 > 0) ? 0 : 101;
732  int col2 = (id1 > 0) ? 102 : 0;
733  int acol2 = (id1 > 0) ? 0 : 102;
734  if (mAbove1 < mAbove2) {
735  leEvent.append( idc1, 63, 1, 0, 0, 0, col1, acol1, pc1, mc1);
736  leEvent.append( idac2, 63, 2, 0, 0, 0, acol1, col1, pac2, mac2);
737  leEvent.append( idac1, 63, 1, 0, 0, 0, col2, acol2, pac1, mac1);
738  leEvent.append( idc2, 63, 2, 0, 0, 0, acol2, col2, pc2, mc2);
739  } else {
740  leEvent.append( idac1, 63, 1, 0, 0, 0, col2, acol2, pac1, mac1);
741  leEvent.append( idc2, 63, 2, 0, 0, 0, acol2, col2, pc2, mc2);
742  leEvent.append( idc1, 63, 1, 0, 0, 0, col1, acol1, pc1, mc1);
743  leEvent.append( idac2, 63, 2, 0, 0, 0, acol1, col1, pac2, mac2);
744  }
745 
746  // Done.
747  return true;
748 
749 }
750 
751 //-------------------------------------------------------------------------
752 
753 // Do a resonance formation and decay.
754 
755 bool LowEnergyProcess::resonance() {
756 
757  // Create the resonance
758  int iNew = leEvent.append(type, 919, 1,2,0,0, 0,0, Vec4(0,0,0,eCM), eCM);
759 
760  leEvent[1].statusNeg(); leEvent[1].daughters(iNew, 0);
761  leEvent[2].statusNeg(); leEvent[2].daughters(iNew, 0);
762 
763  return true;
764 }
765 
766 //--------------------------------------------------------------------------
767 
768 // Simple version of hadronization for low-energy hadronic collisions.
769 // Only accepts simple q-qbar systems and hadrons.
770 
771 bool LowEnergyProcess::simpleHadronization() {
772 
773  // Find the complete colour singlet configuration of the event.
774  simpleColConfig.clear();
775  bool fixOrder = (type == 1);
776  for (int i = 0; i < leEvent.size(); ++i)
777  if (leEvent[i].isQuark() || leEvent[i].isDiquark()) {
778  vector<int> qqPair;
779  qqPair.push_back( i);
780  qqPair.push_back( ++i);
781  simpleColConfig.simpleInsert( qqPair, leEvent, fixOrder);
782  }
783 
784  // If no quarks are present, the system is already hadronized.
785  if (simpleColConfig.size() == 0) return true;
786 
787  // Process all colour singlet (sub)systems.
788  leEvent.saveSize();
789  int nHadronBeg = leEvent.size();
790  for (int iSub = 0; iSub < simpleColConfig.size(); ++iSub) {
791  if (iSub == 1) nHadron = leEvent.size() - nHadronBeg;
792 
793  // Diquark-antidiquark system needs higher mass to count as full string.
794  double mExcess = simpleColConfig[iSub].massExcess;
795  double mDiqDiq = ( leEvent[simpleColConfig[iSub].iParton[0]].isDiquark()
796  && leEvent[simpleColConfig[iSub].iParton[1]].isDiquark() )
797  ? MEXTRADIQDIQ : 0.;
798  bool fragDone = false;
799 
800  // String fragmentation of each colour singlet (sub)system.
801  if ( mExcess > mStringMin + mDiqDiq) {
802  fragDone = stringFragPtr->fragment( iSub, simpleColConfig, leEvent);
803  if (!fragDone && mExcess > mStringMin + mDiqDiq + 4. * MPI) return false;
804  }
805 
806  // Low-mass string treated separately. Tell if diffractive system.
807  if (!fragDone) {
808  bool isDiff = (type >= 3 && type <= 5);
809  if ( !ministringFragPtr->fragment( iSub, simpleColConfig, leEvent,
810  isDiff, false) ) return false;
811  }
812  }
813 
814  // If elastic try last time to find three-body inelastic (or two-body).
815  int nHad = 0, id3 = 0, id4 = 0;
816  for (int i = 1; i < leEvent.size(); ++i) if (leEvent[i].isFinal()) {
817  ++nHad;
818  if (nHad == 1) id3 = leEvent[i].id();
819  if (nHad == 2) id4 = leEvent[i].id();
820  }
821  if (type == 1 && nHad == 2 && ( (id3 == id1 && id4 == id2)
822  || (id3 == id2 && id4 == id1) )) {
823  leEvent.restoreSize();
824  return threeBody();
825  }
826 
827  // Done.
828  return true;
829 
830 }
831 
832 //--------------------------------------------------------------------------
833 
834 // Special two-body handling if below three-body threshold or in emergency.
835 
836 bool LowEnergyProcess::twoBody() {
837 
838  // Often impossible to rearrange baryon-antibaryon flavours.
839  if ( (abs(idc1) > 10 && abs(idac2) > 10)
840  || (abs(idc2) > 10 && abs(idac1) > 10) ) swap(idac1, idac2);
841 
842  // Combine to hadrons
843  int idH1 = flavSelPtr->combineToLightest( idc1, idac2);
844  int idH2 = flavSelPtr->combineToLightest( idc2, idac1);
845 
846  // Get masses
847  double mH1, mH2;
848  if ( (particleDataPtr->mMin(idH1) + particleDataPtr->mMin(idH2) >= eCM)
849  || !hadronWidthsPtr->pickMasses(idH1, idH2, eCM, mH1, mH2)) {
850  infoPtr->errorMsg("Warning in LowEnergyProcess::twoBody: "
851  "below mass threshold, defaulting to elastic collision");
852  idH1 = id1;
853  idH2 = id2;
854  mH1 = leEvent[1].m();
855  mH2 = leEvent[2].m();
856  }
857 
858  // Phase space. Fill particles into the event record and done.
859  pair<Vec4, Vec4> ps12 = rndmPtr->phaseSpace2(eCM, mH1, mH2);
860  for (int i = 3; i < leEvent.size(); ++i) leEvent[i].statusNeg();
861  leEvent.append( idH1, 111, 2, 1, 0, 0, 0, 0, ps12.first, mH1);
862  leEvent.append( idH2, 111, 2, 1, 0, 0, 0, 0, ps12.second, mH2);
863 
864  // Done.
865  return true;
866 
867 }
868 
869 //--------------------------------------------------------------------------
870 
871 // Special three-body handling if below four-body threshold or in emergency.
872 
873 bool LowEnergyProcess::threeBody() {
874 
875  // Impossible to rearrange baryon-antibaryon flavours.
876  if ( (abs(idc1) > 10 && abs(idac2) > 10)
877  || (abs(idc2) > 10 && abs(idac1) > 10) ) swap(idac1, idac2);
878 
879  // Try to find new flavour choice a couple of time.
880  int idc3, idH1, idH2, idH3;
881  double mH1, mH2, mH3;
882  for (int iTry = 0; iTry < 10; ++iTry) {
883  idc3 = (rndmPtr->flat() < 0.5) ? 1 : 2;
884  if (iTry < 8 && rndmPtr->flat() < 0.5) {
885  idH1 = flavSelPtr->combineToLightest( idc1, -idc3);
886  idH2 = flavSelPtr->combineToLightest( idc3, idac2);
887  idH3 = flavSelPtr->combineToLightest( idc2, idac1);
888  } else if (iTry < 8) {
889  idH1 = flavSelPtr->combineToLightest( idc1, idac2);
890  idH2 = flavSelPtr->combineToLightest( idc2, -idc3);
891  idH3 = flavSelPtr->combineToLightest( idc3, idac1);
892  } else {
893  idH1 = flavSelPtr->combineToLightest( idc1, idac2);
894  idH2 = flavSelPtr->combineToLightest( idc2, idac1);
895  idH3 = 111;
896  }
897 
898  // Check if sufficient energy, else go for two-body.
899  mH1 = particleDataPtr->mSel( idH1);
900  mH2 = particleDataPtr->mSel( idH2);
901  mH3 = particleDataPtr->mSel( idH3);
902  if (mH1 + mH2 + mH3 < eCM) break;
903  else if (iTry == 9) return twoBody();
904  }
905 
906  // Kinematical limits for 2+3 mass. Maximum phase-space weight.
907  double m23Min = mH2 + mH3;
908  double m23Max = eCM - mH1;
909  double p1Max = 0.5 * sqrtpos( (eCM - mH1 - m23Min) * (eCM + mH1 + m23Min)
910  * (eCM + mH1 - m23Min) * (eCM - mH1 + m23Min) ) / eCM;
911  double p23Max = 0.5 * sqrtpos( (m23Max - mH2 - mH3) * (m23Max + mH2 + mH3)
912  * (m23Max + mH2 - mH3) * (m23Max - mH2 + mH3) ) / m23Max;
913  double wtPSmax = 0.5 * p1Max * p23Max;
914 
915  // Pick an intermediate mass m23 flat in the allowed range.
916  double wtPS, m23, p1Abs, p23Abs;
917  do {
918  m23 = m23Min + rndmPtr->flat() * (m23Max - m23Min);
919 
920  // Translate into relative momenta and find phase-space weight.
921  p1Abs = 0.5 * sqrtpos( (eCM - mH1 - m23) * (eCM + mH1 + m23)
922  * (eCM + mH1 - m23) * (eCM - mH1 + m23) ) / eCM;
923  p23Abs = 0.5 * sqrtpos( (m23 - mH2 - mH3) * (m23 + mH2 + mH3)
924  * (m23 + mH2 - mH3) * (m23 - mH2 + mH3) ) / m23;
925  wtPS = p1Abs * p23Abs;
926 
927  // If rejected, try again with new invariant masses.
928  } while ( wtPS < rndmPtr->flat() * wtPSmax );
929 
930  // Set up particle momenta.
931  pair<Vec4, Vec4> ps123 = rndmPtr->phaseSpace2(eCM, mH1, m23);
932  Vec4 p1 = ps123.first;
933  pair<Vec4, Vec4> ps23 = rndmPtr->phaseSpace2(m23, mH2, mH3);
934  Vec4 p2 = ps23.first;
935  Vec4 p3 = ps23.second;
936  p2.bst( ps123.second, m23 );
937  p3.bst( ps123.second, m23 );
938 
939  // Fill particles into the event record and done.
940  for (int i = 3; i < leEvent.size(); ++i) leEvent[i].statusNeg();
941  leEvent.append( idH1, 111, 2, 1, 0, 0, 0, 0, p1, mH1);
942  leEvent.append( idH2, 111, 2, 1, 0, 0, 0, 0, p2, mH2);
943  leEvent.append( idH3, 111, 2, 1, 0, 0, 0, 0, p3, mH3);
944 
945  // Done.
946  return true;
947 
948 }
949 
950 //-------------------------------------------------------------------------
951 
952 // Split up hadron A into a colour-anticolour pair, with masses and pT values.
953 
954 bool LowEnergyProcess::splitA( double mMax, double redMpT, bool splitFlavour) {
955 
956  // Split up flavour of hadron into a colour and an anticolour constituent.
957  if (splitFlavour) {
958  pair< int, int> paircac = splitFlav( id1 );
959  idc1 = paircac.first;
960  idac1 = paircac.second;
961  }
962  if (idc1 == 0 || idac1 == 0) return false;
963 
964  // Allow a few tries to find acceptable internal kinematics.
965  for (int i = 0; i < 10; ++i) {
966 
967  // Find constituent masses and scale down to less than full mass.
968  mc1 = particleDataPtr->m0( idc1);
969  mac1 = particleDataPtr->m0( idac1);
970  double redNow = redMpT * min( 1., m1 / (mc1 + mac1));
971  mc1 *= redNow;
972  mac1 *= redNow;
973 
974  // Select Gaussian relative transverse momenta for constituents.
975  pair<double, double> gauss2 = rndmPtr->gauss2();
976  px1 = redMpT * sigmaQ * gauss2.first;
977  py1 = redMpT * sigmaQ * gauss2.second;
978  pTs1 = px1 * px1 + py1 * py1;
979 
980  // Construct transverse masses.
981  mTsc1 = pow2(mc1) + pTs1;
982  mTsac1 = pow2(mac1) + pTs1;
983  mTc1 = sqrt(mTsc1);
984  mTac1 = sqrt(mTsac1);
985 
986  // Check if solution found, else failed.
987  if (mTc1 + mTac1 < mMax) return true;
988  }
989  return false;
990 
991 }
992 
993 //-------------------------------------------------------------------------
994 
995 // Split up hadron B into a colour-anticolour pair, with masses and pT values.
996 
997 bool LowEnergyProcess::splitB( double mMax, double redMpT, bool splitFlavour) {
998 
999  // Split up flavour of hadron into a colour and an anticolour constituent.
1000  if (splitFlavour) {
1001  pair< int, int> paircac = splitFlav( id2 );
1002  idc2 = paircac.first;
1003  idac2 = paircac.second;
1004  }
1005  if (idc2 == 0 || idac2 == 0) return false;
1006 
1007  // Allow a few tries to find acceptable internal kinematics.
1008  for (int i = 0; i < 10; ++i) {
1009 
1010  // Find constituent masses and scale down to less than full mass.
1011  mc2 = particleDataPtr->m0( idc2);
1012  mac2 = particleDataPtr->m0( idac2);
1013  double redNow = redMpT * min( 1., m2 / (mc2 + mac2));
1014  mc2 *= redNow;
1015  mac2 *= redNow;
1016 
1017  // Select Gaussian relative transverse momenta for constituents.
1018  pair<double, double> gauss2 = rndmPtr->gauss2();
1019  px2 = redMpT * sigmaQ * gauss2.first;
1020  py2 = redMpT * sigmaQ * gauss2.second;
1021  pTs2 = px2 * px2 + py2 * py2;
1022 
1023  // Construct transverse masses.
1024  mTsc2 = pow2(mc2) + pTs2;
1025  mTsac2 = pow2(mac2) + pTs2;
1026  mTc2 = sqrt(mTsc2);
1027  mTac2 = sqrt(mTsac2);
1028 
1029  // Check if solution found, else failed.
1030  if (mTc2 + mTac2 < mMax) return true;
1031  }
1032  return false;
1033 
1034 }
1035 
1036 //-------------------------------------------------------------------------
1037 
1038 // Split up a hadron into a colour and an anticolour part, of q or qq kinds.
1039 
1040 pair< int, int> LowEnergyProcess::splitFlav( int id) {
1041 
1042  // Hadron flavour content.
1043  int idAbs = abs(id);
1044  int iq1 = (idAbs/1000)%10;
1045  int iq2 = (idAbs/100)%10;
1046  int iq3 = (idAbs/10)%10;
1047  int iq4, iq5;
1048 
1049  // Nondiagonal mesons.
1050  if (iq1 == 0 && iq2 != iq3) {
1051  if (id != 130 && id != 310) {
1052  if (iq2%2 == 1) swap( iq2, iq3);
1053  if (id > 0) return make_pair( iq2, -iq3);
1054  else return make_pair( iq3, -iq2);
1055 
1056  // K0S and K0L are mixes d sbar and dbar s.
1057  } else {
1058  if (rndmPtr->flat() < 0.5) return make_pair( 3, -1);
1059  else return make_pair( 1, -3);
1060  }
1061 
1062  // Diagonal mesons: assume complete mixing ddbar and uubar.
1063  } else if (iq1 == 0) {
1064  iq4 = iq2;
1065  // Special cases for 11x, 22x, and eta'
1066  if (iq2 < 3 || id == 331) {
1067  iq4 = (rndmPtr->flat() < 0.5) ? 1 : 2;
1068  // eta and eta' can also be s sbar.
1069  if (id == 221 && eCM > 2 * MK && rndmPtr->flat() < fracEtass) iq4 = 3;
1070  if (id == 331 && eCM > 2 * MK && rndmPtr->flat() < fracEtaPss) iq4 = 3;
1071  }
1072  return make_pair( iq4, -iq4);
1073 
1074  // Octet baryons.
1075  } else if (idAbs%10 == 2) {
1076  // Three identical quarks: emergency in case of higher spin 1/2 multiplet.
1077  if (iq1 == iq2 && iq2 == iq3) {iq4 = iq1; iq5 = 1100 * iq1 + 3;}
1078  // Two identical quarks, like normal p or n.
1079  else if (iq1 == iq2 || iq2 == iq3) {
1080  double rr6 = 6. * rndmPtr->flat();
1081  if (iq1 == iq2 && rr6 < 2.) { iq4 = iq3; iq5 = 1100 * iq1 + 3;}
1082  else if (rr6 < 2.) { iq4 = iq1; iq5 = 1100 * iq3 + 3;}
1083  else if (rr6 < 3.) { iq4 = iq2; iq5 = 1000 * iq1 + 100 * iq3 + 3;}
1084  else { iq4 = iq2; iq5 = 1000 * iq1 + 100 * iq3 + 1;}
1085  // Three nonidentical quarks, Sigma- or Lambda-like.
1086  } else {
1087  int isp = (iq2 > iq3) ? 3 : 1;
1088  if (iq3 > iq1) swap( iq1, iq3);
1089  if (iq3 > iq2) swap( iq2, iq3);
1090  double rr12 = 12. * rndmPtr->flat();
1091  if (rr12 < 4.) { iq4 = iq1; iq5 = 1000 * iq2 + 100 * iq3 + isp;}
1092  else if (rr12 < 5.) { iq4 = iq2; iq5 = 1000 * iq1 + 100 * iq3 + isp;}
1093  else if (rr12 < 6.) { iq4 = iq3; iq5 = 1000 * iq1 + 100 * iq2 + isp;}
1094  else if (rr12 < 9.) { iq4 = iq2; iq5 = 1000 * iq1 + 100 * iq3 + 4 - isp;}
1095  else { iq4 = iq3; iq5 = 1000 * iq1 + 100 * iq2 + 4 - isp;}
1096  }
1097  return (id > 0) ? make_pair(iq4, iq5) : make_pair(-iq5, -iq4);
1098 
1099  // Higher spin baryons.
1100  } else {
1101  double rr3 = 3. * rndmPtr->flat();
1102  // Sort quark order, e.g. for Lambdas.
1103  if (iq3 > iq1) swap( iq1, iq3);
1104  if (iq3 > iq2) swap( iq2, iq3);
1105  if (rr3 < 1.) { iq4 = iq1; iq5 = 1000 * iq2 + 100 * iq3 + 3;}
1106  else if (rr3 < 2.) { iq4 = iq2; iq5 = 1000 * iq1 + 100 * iq3 + 3;}
1107  else { iq4 = iq3; iq5 = 1000 * iq1 + 100 * iq2 + 3;}
1108  return (id > 0) ? make_pair(iq4, iq5) : make_pair(-iq5, -iq4);
1109  }
1110 
1111  // Done. (Fake call to avoid unwarranted compiler warning.)
1112  return make_pair( 0, 0);
1113 }
1114 
1115 //-------------------------------------------------------------------------
1116 
1117 // Find relative momentum of colour and anticolour constituents in hadron.
1118 
1119 double LowEnergyProcess::splitZ(int iq1, int iq2, double mRat1, double mRat2) {
1120 
1121  // Initial values.
1122  int iq1Abs = abs(iq1);
1123  int iq2Abs = abs(iq2);
1124  if (iq2Abs > 10) swap( mRat1, mRat2);
1125  double x1, x2, x1a, x1b;
1126 
1127  // Handle mesons.
1128  if (iq1Abs < 10 && iq2Abs < 10) {
1129  do x1 = pow2( mRat1 + (1. - mRat1) * rndmPtr->flat() );
1130  while ( pow(1. - x1, xPowMes) < rndmPtr->flat() );
1131  do x2 = pow2( mRat2 + (1. - mRat2) * rndmPtr->flat() );
1132  while ( pow(1. - x2, xPowMes) < rndmPtr->flat() );
1133 
1134  // Handle baryons.
1135  } else {
1136  double mRat1ab = 0.5 * mRat1 / xDiqEnhance;
1137  do x1a = pow2( mRat1ab + (1. - mRat1ab) * rndmPtr->flat() );
1138  while ( pow(1. - x1a, xPowBar) < rndmPtr->flat() );
1139  do x1b = pow2( mRat1ab + (1. - mRat1ab) * rndmPtr->flat() );
1140  while ( pow(1. - x1b, xPowBar) < rndmPtr->flat() );
1141  x1 = xDiqEnhance * ( x1a + x1b);
1142  do x2 = pow2( mRat2 + (1. - mRat2) * rndmPtr->flat() );
1143  while ( pow(1. - x2, xPowBar) < rndmPtr->flat() );
1144  if (iq2Abs > 10) swap( x1, x2);
1145  }
1146 
1147  // Return z value.
1148  return x1 / (x1 + x2);
1149 
1150 }
1151 
1152 //-------------------------------------------------------------------------
1153 
1154 // Overestimate mass of lightest state for given flavour combination.
1155 
1156 double LowEnergyProcess::mThreshold( int iq1, int iq2) {
1157 
1158  // Initial values.
1159  int iq1Abs = abs(iq1);
1160  int iq2Abs = abs(iq2);
1161  if (iq2Abs > 10) swap( iq1Abs, iq2Abs);
1162  double mThr = 0.;
1163 
1164  // Mesonic or baryonic state.
1165  if (iq2Abs < 10) mThr
1166  = particleDataPtr->m0( flavSelPtr->combineToLightest ( iq1, iq2) );
1167 
1168  // Baryon-antibaryon state.
1169  else mThr = min(
1170  particleDataPtr->m0( flavSelPtr->combineToLightest ( iq1Abs, 1) )
1171  + particleDataPtr->m0( flavSelPtr->combineToLightest ( iq2Abs, 1) ),
1172  particleDataPtr->m0( flavSelPtr->combineToLightest ( iq1Abs, 2) )
1173  + particleDataPtr->m0( flavSelPtr->combineToLightest ( iq2Abs, 2) ) );
1174 
1175  // Done.
1176  return mThr;
1177 
1178 }
1179 
1180 //-------------------------------------------------------------------------
1181 
1182 // Minimum mass required for diffraction into two hadrons.
1183 // Note that splitFlav is not deterministic, so neither is mDiffThr.
1184 
1185 double LowEnergyProcess::mDiffThr( int idNow, double mNow) {
1186 
1187  // Initial minimal value.
1188  double mThr = mNow + MDIFFMIN;
1189 
1190  // Split up hadron into color and anticolour.
1191  pair< int, int> paircac = splitFlav( idNow );
1192  int idcNow = paircac.first;
1193  int idacNow = paircac.second;
1194  if (idcNow == 0 || idacNow == 0) return mThr;
1195  if (idNow == 221 || idNow == 331) {idcNow = 3; idacNow = -3;}
1196 
1197  // Insert u-ubar or d-dbar pair to find lowest two-body state.
1198  double mThr2body = min(
1199  particleDataPtr->m0( flavSelPtr->combineToLightest ( idcNow, -1) )
1200  + particleDataPtr->m0( flavSelPtr->combineToLightest ( 1, idacNow) ),
1201  particleDataPtr->m0( flavSelPtr->combineToLightest ( idcNow, -2) )
1202  + particleDataPtr->m0( flavSelPtr->combineToLightest ( 2, idacNow) ) );
1203 
1204  // Done.
1205  return max(mThr, mThr2body);
1206 
1207 }
1208 
1209 //-------------------------------------------------------------------------
1210 
1211 // Pick slope b of exp(b * t) for elastic and diffractive events.
1212 
1213 double LowEnergyProcess::bSlope() {
1214 
1215  // Steeper slope for baryons than mesons.
1216  // Scale by AQM factor for strange, charm and bottom.
1217  if (id1 != id1sv) {
1218  bA = lowEnergySigmaPtr->nqEffAQM(id1) * ((isBaryon1) ? 2.3/3. : 1.4/2.);
1219  id1sv = id1;
1220  }
1221  if (id2 != id2sv) {
1222  bB = lowEnergySigmaPtr->nqEffAQM(id2) * ((isBaryon1) ? 2.3/3. : 1.4/2.);
1223  id2sv = id2;
1224  }
1225 
1226  // Elastic slope.
1227  if (type == 2)
1228  return 2. * bA + 2. * bB + 2. * ALPHAPRIME * log(ALPHAPRIME * sCM);
1229 
1230  // Single diffractive slope for XB and AX, respectively.
1231  if (type == 3) return 2. * bB + 2. * ALPHAPRIME * log(sCM / (mA * mA));
1232  if (type == 4) return 2. * bA + 2. * ALPHAPRIME * log(sCM / (mB * mB));
1233 
1234  // Double diffractive slope.
1235  return 2. * ALPHAPRIME * log(exp(4.) + sCM / (ALPHAPRIME * pow2(mA * mB)) );
1236 
1237 }
1238 
1239 //==========================================================================
1240 
1241 } // end namespace Pythia8
Definition: AgUStep.h:26