StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
HadronScatter.cc
1 // HadronScatter.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2018 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 #include "Pythia8/HadronScatter.h"
7 
8 namespace Pythia8 {
9 
10 //==========================================================================
11 
12 // The SigmaPartialWave class
13 // Reads in tables of partial wave data to provide dSigma/dCos(theta)
14 // The generic classes of process are:
15 // process = 0 (pi-pi), 1 (pi-K), 2 (pi-N)
16 // Subprocesses are defined (along with isospin coefficients) in:
17 // setupSubprocesses();
18 // Individual subprocesses are selected using:
19 // setSubprocess(subprocess); or setSubprocess(PDG1, PDG2);
20 // Internally, there are two std::map's, to convert between:
21 // subprocess <==> PDG1, PDG2
22 //
23 // Data are read in from files:
24 // Lines starting with a '#' are comments
25 // Lines starting with 'set' provide options:
26 // set eType [Wcm | Tlab] - energy bins in Wcm or Tlab
27 // set eUnit [MeV | GeV] - energy unit
28 // set input [eta,delta | Sn,delta | Tr,Ti | mod,phi ]
29 // - format of columns in partial waves
30 // set dUnit [deg | rad] - unit of phase shifts
31 // set norm [0 | 1] - normalisation
32 // Column headers give L,2I[,2J] (2J for e.g. piN)
33 // Input types: Sn,delta -> Sn = 1 - eta^2
34 // mod,phi -> amplitude T_L = |T_L| exp(i phi_L)
35 // Normalisation: 0 -> dSigma/dOmega = 1 / k^2 |T_L|^2
36 // 1 -> dSigma/dOmega = 16 / s |T_L|^2
37 //
38 // Internally data is stored as (J = 0 for spinless):
39 // pwData[L * LSHIFT + 2I * ISHIFT + J][energy_bin_centre] = T
40 // where the energy is Wcm in GeV.
41 //
42 // This is stored using std::map's, to take into account that not all
43 // L,I,J states are always present (e.g. negligable contributions or
44 // conservation rules) and that bin sizes are not fixed.
45 //
46 // Re[T] and Im[T] are interpolated between bins and extrapolated down to
47 // threshold from the first two bins. Above energy_bin_centre of the final
48 // bin, no extrapolation is done and the final bin value is always used.
49 //
50 // A simple scheme to provide correct distributions for cos(theta) at a
51 // given CM energy is included. Efficiency is not too bad, but can likely
52 // be greatly improved.
53 //
54 // For each subprocess, a grid in bins of Wcm and cos(theta) is setup with:
55 // setupGrid();
56 // The size of the grid is set by the constants:
57 // const double SigmaPartialWave::WCMBIN;
58 // const double SigmaPartialWave::CTBIN;
59 // For each bin of (Wcm, ct), the maximum sigma elastic is found by
60 // splitting this bin into subbins multiple times, controlled by:
61 // const int SigmaPartialWave::SUBBIN;
62 // const int SigmaPartialWave::ITER
63 // With the final maxium sigma elastic given by this value multipled by
64 // a safety factor:
65 // const double SigmaPartialWave::GRIDSAFETY
66 //
67 // To pick values of cos(theta) for a given CM energy, a:
68 // pickCosTheta(Wcm);
69 // function is provided. The above grid is used as an overestimate, to
70 // pick properly distributed values of cos(theta).
71 
72 //--------------------------------------------------------------------------
73 
74 // Constants
75 
76 // pwData[L * LSHIFT + 2I * ISHIFT + J]
77 const int SigmaPartialWave::LSHIFT = 1000000;
78 const int SigmaPartialWave::ISHIFT = 1000;
79 
80 // Convert GeV^-2 to mb
81 const double SigmaPartialWave::CONVERT2MB = 0.389380;
82 
83 // Size of bin in Wcm and cos(theta)
84 const double SigmaPartialWave::WCMBIN = 0.005;
85 const double SigmaPartialWave::CTBIN = 0.2;
86 // Number of subbins and iterations
87 const int SigmaPartialWave::SUBBIN = 2;
88 const int SigmaPartialWave::ITER = 2;
89 // Safety value to add on to grid maxima
90 const double SigmaPartialWave::MASSSAFETY = 0.001;
91 const double SigmaPartialWave::GRIDSAFETY = 0.05;
92 
93 
94 //--------------------------------------------------------------------------
95 
96 // Perform initialization and store pointers.
97 
98 bool SigmaPartialWave::init(int processIn, string xmlPath, string filename,
99  Info *infoPtrIn, ParticleData *particleDataPtrIn,
100  Rndm *rndmPtrIn) {
101  // Store incoming pointers
102  infoPtr = infoPtrIn;
103  particleDataPtr = particleDataPtrIn;
104  rndmPtr = rndmPtrIn;
105 
106  // Check incoming process is okay
107  if (processIn < 0 || processIn > 2) {
108  infoPtr->errorMsg("Error in SigmaPartialWave::init: "
109  "unknown process");
110  return false;
111  }
112  process = processIn;
113 
114  // Setup subprocesses and isospin coefficients
115  setupSubprocesses();
116  setSubprocess(0);
117 
118  // Read in partial-wave data
119  if (!readFile(xmlPath, filename)) return false;
120 
121  // Setup vector for Legendre polynomials
122  PlVec.resize(Lmax);
123  if (Lmax > 0) PlVec[0] = 1.;
124  // And derivatives if needed
125  if (process == 2) {
126  PlpVec.resize(Lmax);
127  if (Lmax > 0) PlpVec[0] = 0.;
128  if (Lmax > 1) PlpVec[1] = 1.;
129  }
130 
131  // Setup grid for integration
132  setupGrid();
133 
134  return true;
135 }
136 
137 
138 //--------------------------------------------------------------------------
139 
140 // Read input data file
141 
142 bool SigmaPartialWave::readFile(string xmlPath, string filename) {
143  // Create full path and open file
144  string fullPath = xmlPath + filename;
145  ifstream ifs(fullPath.c_str());
146  if (!ifs.good()) {
147  infoPtr->errorMsg("Error in SigmaPartialWave::init: "
148  "could not read data file");
149  return false;
150  }
151 
152  // Default unit settings
153  int eType = 0; // 0 = Wcm, 1 = Tlab
154  int eUnit = 0; // 0 = GeV, 1 = MeV
155  int input = 0; // 0 = eta, delta; 1 = Sn, delta (Sn = 1 - eta^2);
156  // 2 = Treal, Tim, 3 = mod, phi
157  int dUnit = 0; // 0 = deg, 1 = rad
158  norm = 0; // 0 = standard, 1 = sqrt(s) / sqrt(s - 4Mpi^2)
159 
160  // Once we have a header line, each column corresponds to
161  // values of L, I and J.
162  Lmax = Imax = 0;
163  binMax = 0.;
164  vector < int > Lvec, Ivec, Jvec;
165 
166  // Parse the file
167  string line;
168  while (ifs.good()) {
169  // Get line, convert to lowercase and strip leading whitespace
170  getline(ifs, line);
171  toLowerRep(line, false);
172  string::size_type startPos = line.find_first_not_of(" ");
173  if (startPos != string::npos) line = line.substr(startPos);
174  // Skip blank lines and lines that start with '#'
175  if (line.length() == 0 || line[0] == '#') continue;
176 
177  // Tokenise line on whitespace (spaces or tabs)
178  string lineT = line;
179  vector < string > token;
180  while (true) {
181  startPos = lineT.find_first_of(" ");
182  token.push_back(lineT.substr(0, startPos));
183  if (startPos == string::npos) break;
184  startPos = lineT.find_first_not_of(" ", startPos + 1);
185  if (startPos == string::npos) break;
186  lineT = lineT.substr(startPos);
187  }
188 
189  // Settings
190  if (token[0] == "set") {
191  bool badSetting = false;
192 
193  // eType
194  if (token[1] == "etype") {
195  if (token[2] == "wcm") eType = 0;
196  else if (token[2] == "tlab") eType = 1;
197  else badSetting = true;
198 
199  // eUnit
200  } else if (token[1] == "eunit") {
201  if (token[2] == "gev") eUnit = 0;
202  else if (token[2] == "mev") eUnit = 1;
203  else badSetting = true;
204 
205  // input
206  } else if (token[1] == "input") {
207  if (token[2] == "eta,delta") input = 0;
208  else if (token[2] == "sn,delta") input = 1;
209  else if (token[2] == "tr,ti") input = 2;
210  else if (token[2] == "mod,phi") input = 3;
211  else badSetting = true;
212 
213  // dUnit
214  } else if (token[1] == "dunit") {
215  if (token[2] == "deg") dUnit = 0;
216  else if (token[2] == "rad") dUnit = 1;
217  else badSetting = true;
218 
219  // norm
220  } else if (token[1] == "norm") {
221  if (token[2] == "0") norm = 0;
222  else if (token[2] == "1") norm = 1;
223  else badSetting = true;
224  }
225 
226  // Bad setting
227  if (badSetting) {
228  infoPtr->errorMsg("Error in SigmaPartialWave::init: "
229  "bad setting line");
230  return false;
231  }
232  continue;
233  }
234 
235  // Header line
236  if (line.substr(0, 1).find_first_of("0123456789.") != 0) {
237  // Clear current stored L,2I,2J values
238  Lvec.clear(); Ivec.clear(); Jvec.clear();
239 
240  // Parse header
241  bool badHeader = false;
242  for (unsigned int i = 1; i < token.size(); i++) {
243  // Extract L
244  startPos = token[i].find_first_of(",");
245  if (startPos == string::npos) { badHeader = true; break; }
246  string Lstr = token[i].substr(0, startPos);
247  token[i] = token[i].substr(startPos + 1);
248  // Extract 2I
249  string Istr;
250  startPos = token[i].find_first_of(", ");
251  if (startPos == string::npos) {
252  Istr = token[i];
253  token[i] = "";
254  } else {
255  Istr = token[i].substr(0, startPos);
256  token[i] = token[i].substr(startPos + 1);
257  }
258  // Extract 2J
259  string Jstr("0");
260  if (token[i].length() != 0) Jstr = token[i];
261 
262  // Convert to integers and store
263  int L, I, J;
264  stringstream Lss(Lstr); Lss >> L;
265  stringstream Iss(Istr); Iss >> I;
266  stringstream Jss(Jstr); Jss >> J;
267  if (Lss.fail() || Iss.fail() || Jss.fail())
268  { badHeader = true; break; }
269  Lvec.push_back(L);
270  Ivec.push_back(I);
271  Jvec.push_back(J);
272  Lmax = max(Lmax, L);
273  Imax = max(Imax, I);
274  }
275  if (badHeader) {
276  infoPtr->errorMsg("Error in SigmaPartialWave::init: "
277  "malformed header line");
278  return false;
279  }
280 
281  // Data line
282  } else {
283  bool badData = false;
284 
285  // Check there are the correct number of columns
286  if (token.size() != 2 * Lvec.size() + 1) badData = true;
287 
288  // Extract energy
289  double eNow = 0.;
290  if (!badData) {
291  stringstream eSS(token[0]);
292  eSS >> eNow;
293  if (eSS.fail()) badData = true;
294  // Convert to GeV if needed
295  if (eUnit == 1) eNow *= 1e-3;
296  // Convert to Wcm if needed
297  if (eType == 1) eNow = sqrt(2. * mB * eNow + pow2(mA + mB));
298  binMax = max(binMax, eNow);
299  }
300 
301  // Extract eta/phase shifts
302  if (!badData) {
303  for (unsigned int i = 1; i < token.size(); i += 2) {
304  // L,2I,2J
305  int LIJidx = (i - 1) / 2;
306  int L = Lvec[LIJidx];
307  int I = Ivec[LIJidx];
308  int J = Jvec[LIJidx];
309 
310  double i1, i2;
311  stringstream i1SS(token[i]); i1SS >> i1;
312  stringstream i2SS(token[i + 1]); i2SS >> i2;
313  if (i1SS.fail() || i2SS.fail()) { badData = true; break; }
314 
315  // Sn to eta
316  if (input == 1) i1 = sqrt(1. - i1);
317  // Degrees to radians
318  if ((input == 0 || input == 1 || input == 3) &&
319  dUnit == 0) i2 *= M_PI / 180.;
320 
321  // Convert to Treal and Timg
322  complex T(0., 0.);
323  if (input == 0 || input == 1) {
324  T = (i1 * exp(2. * complex(0., 1.) * i2) - 1.) /
325  2. / complex(0., 1.);
326  } else if (input == 2) {
327  T = complex(i1, i2);
328  } else if (input == 3) {
329  T = i1 * exp(complex(0., 1.) * i2);
330  }
331 
332  // Store
333  pwData[L * LSHIFT + I * ISHIFT + J][eNow] = T;
334  }
335  }
336  if (badData) {
337  infoPtr->errorMsg("Error in SigmaPartialWave::init: "
338  "malformed data line");
339  return false;
340  }
341  }
342  }
343 
344  // Make sure it was EOF that caused us to end
345  if (!ifs.eof()) { ifs.close(); return false; }
346 
347  // Maximum values of L and I
348  Lmax++; Imax++;
349 
350  return true;
351 }
352 
353 
354 //--------------------------------------------------------------------------
355 
356 // Setup isospin coefficients and subprocess mapping
357 
358 void SigmaPartialWave::setupSubprocesses() {
359 
360  // Setup isospin coefficients
361  switch (process) {
362  // pi-pi
363  case 0:
364  // Map subprocess to incoming
365  subprocessMax = 6;
366  sp2in[0] = pair < int, int > ( 211, 211);
367  sp2in[1] = pair < int, int > ( 211, -211);
368  sp2in[2] = pair < int, int > ( 211, 111);
369  sp2in[3] = pair < int, int > ( 111, 111);
370  sp2in[4] = pair < int, int > (-211, 111);
371  sp2in[5] = pair < int, int > (-211, -211);
372  // Incoming to subprocess
373  for (int i = 0; i < subprocessMax; i++) in2sp[sp2in[i]] = i;
374  // Isospin coefficients
375  isoCoeff[0][0] = 0.; isoCoeff[0][2] = 0.; isoCoeff[0][4] = 1.;
376  isoCoeff[1][0] = 1./3.; isoCoeff[1][2] = 1./2.; isoCoeff[1][4] = 1./6.;
377  isoCoeff[2][0] = 0.; isoCoeff[2][2] = 1./2.; isoCoeff[2][4] = 1./2.;
378  isoCoeff[3][0] = 1./3.; isoCoeff[3][2] = 0.; isoCoeff[3][4] = 2./3.;
379  isoCoeff[4][0] = 0.; isoCoeff[4][2] = 1./2.; isoCoeff[4][4] = 1./2.;
380  isoCoeff[5][0] = 0.; isoCoeff[5][2] = 0.; isoCoeff[5][4] = 1.;
381 
382  break;
383 
384  // pi-K and pi-N
385  case 1: case 2:
386  int id1, id2;
387  if (process == 1) { id1 = 321; id2 = 311; }
388  else { id1 = 2212; id2 = 2112; }
389 
390  // Map subprocess to incoming
391  subprocessMax = 12;
392  sp2in[0] = pair < int, int > ( 211, id1);
393  sp2in[1] = pair < int, int > ( 211, id2);
394  sp2in[2] = pair < int, int > ( 111, id1);
395  sp2in[3] = pair < int, int > ( 111, id2);
396  sp2in[4] = pair < int, int > (-211, id1);
397  sp2in[5] = pair < int, int > (-211, id2);
398  // Isospin coefficients
399  isoCoeff[0][1] = 0.; isoCoeff[0][3] = 1.;
400  isoCoeff[1][1] = 2. / 3.; isoCoeff[1][3] = 1. / 3.;
401  isoCoeff[2][1] = 1. / 3.; isoCoeff[2][3] = 2. / 3.;
402  isoCoeff[3][1] = 1. / 3.; isoCoeff[3][3] = 2. / 3.;
403  isoCoeff[4][1] = 2. / 3.; isoCoeff[4][3] = 1. / 3.;
404  isoCoeff[5][1] = 0.; isoCoeff[5][3] = 1.;
405  // Antiparticles
406  for (int i = 0; i < 6; i++) {
407  id1 = ((sp2in[i].first == 111) ? +1 : -1) * sp2in[i].first;
408  sp2in[i + 6] = pair < int, int > (id1, -sp2in[i].second);
409  isoCoeff[i + 6] = isoCoeff[i];
410  }
411  // Map incoming to subprocess
412  for (int i = 0; i < subprocessMax; i++) in2sp[sp2in[i]] = i;
413 
414  break;
415  }
416 
417  return;
418 }
419 
420 
421 //--------------------------------------------------------------------------
422 
423 // Setup grids for integration
424 
425 void SigmaPartialWave::setupGrid() {
426  // Reset sigma maximum
427  sigElMax = 0.;
428 
429  // Go through each subprocess
430  gridMax.resize(subprocessMax);
431  gridNorm.resize(subprocessMax);
432  for (int sp = 0; sp < subprocessMax; sp++) {
433  // Setup subprocess
434  setSubprocess(sp);
435 
436  // Bins in Wcm
437  int nBin1 = int( (binMax - mA - mB) / WCMBIN );
438  gridMax[subprocess].resize(nBin1);
439  gridNorm[subprocess].resize(nBin1);
440  for (int n1 = 0; n1 < nBin1; n1++) {
441  // Bin lower and upper
442  double bl1 = mA + mB + double(n1) * WCMBIN;
443  double bu1 = bl1 + WCMBIN;
444 
445  // Bins in cos(theta)
446  int nBin2 = int( 2. / CTBIN );
447  gridMax[subprocess][n1].resize(nBin2);
448  for (int n2 = 0; n2 < nBin2; n2++) {
449  // Bin lower and upper
450  double bl2 = -1. + double(n2) * CTBIN;
451  double bu2 = bl2 + CTBIN;
452 
453  // Find maximum
454  double maxSig = 0.;
455  double bl3 = bl1, bu3 = bu1, bl4 = bl2, bu4 = bu2;
456  for (int iter = 0; iter < ITER; iter++) {
457  int i3Save = -1, i4Save = -1;
458  double step3 = (bu3 - bl3) / double(SUBBIN);
459  double step4 = (bu4 - bl4) / double(SUBBIN);
460  for (int i3 = 0; i3 <= SUBBIN; i3++) {
461  double Wcm = bl3 + double(i3) * step3;
462  for (int i4 = 0; i4 <= SUBBIN; i4++) {
463  double ct = bl4 + double(i4) * step4;
464  double ds = dSigma(Wcm, ct);
465  if (ds > maxSig) {
466  i3Save = i3;
467  i4Save = i4;
468  maxSig = ds;
469  }
470  }
471  }
472  // Set new min/max
473  if (i3Save == -1 && i4Save == -1) break;
474  if (i3Save > -1) {
475  bl3 = bl3 + ((i3Save == 0) ? 0. : i3Save - 1.) * step3;
476  bu3 = bl3 + ((i3Save == SUBBIN) ? 1. : 2.) * step3;
477  }
478  if (i4Save > -1) {
479  bl4 = bl4 + ((i4Save == 0) ? 0. : i4Save - 1.) * step4;
480  bu4 = bl4 + ((i4Save == SUBBIN) ? 1. : 2.) * step4;
481  }
482  } // for (iter)
483 
484  // Save maximum value
485  gridMax[subprocess][n1][n2] = maxSig * (1. + GRIDSAFETY);
486  gridNorm[subprocess][n1] += maxSig * (1. + GRIDSAFETY) * CTBIN;
487  sigElMax = max(sigElMax, maxSig);
488 
489  } // for (n2)
490  } // for (n1)
491  } // for (sp)
492 
493  return;
494 }
495 
496 
497 //--------------------------------------------------------------------------
498 
499 // Pick a cos(theta) value
500 
501 double SigmaPartialWave::pickCosTheta(double Wcm) {
502  // Find grid bin in Wcm
503  int WcmBin = int((Wcm - mA - mB) / WCMBIN);
504  if (WcmBin < 0) WcmBin = 0;
505  if (WcmBin >= int(gridMax[subprocess].size()))
506  WcmBin = int(gridMax[subprocess].size() - 1);
507 
508  // Pick a value of cos(theta)
509  double ct, wgt;
510 
511  do {
512  // Sample from overestimate and inverse
513  double y = rndmPtr->flat() * gridNorm[subprocess][WcmBin];
514  double sum = 0.;
515  int ctBin;
516  for (ctBin = 0; ctBin < int(2. / CTBIN); ctBin++) {
517  if (sum + CTBIN * gridMax[subprocess][WcmBin][ctBin] > y) break;
518  sum += CTBIN * gridMax[subprocess][WcmBin][ctBin];
519  }
520 
521  // Linear interpolation
522  double x1 = -1. + CTBIN * double(ctBin);
523  double y1 = sum;
524  double x2 = x1 + CTBIN;
525  double y2 = sum + CTBIN * gridMax[subprocess][WcmBin][ctBin];
526  ct = (x2 - x1) / (y2 - y1) * (y - y1) + x1;
527  wgt = dSigma(Wcm, ct) / gridMax[subprocess][WcmBin][ctBin];
528  if (wgt >= 1.) {
529  infoPtr->errorMsg("Warning in SigmaPartialWave::pickCosTheta: "
530  "weight above unity");
531  break;
532  }
533  } while (wgt <= rndmPtr->flat());
534 
535  return ct;
536 }
537 
538 //--------------------------------------------------------------------------
539 
540 // Set subprocess
541 
542 bool SigmaPartialWave::setSubprocess(int spIn) {
543  if (sp2in.find(spIn) == sp2in.end()) return false;
544  subprocess = spIn;
545  pair < int, int > in = sp2in[spIn];
546  idA = in.first;
547  mA = particleDataPtr->m0(idA);
548  idB = in.second;
549  mB = particleDataPtr->m0(idB);
550  return true;
551 }
552 
553 bool SigmaPartialWave::setSubprocess(int idAin, int idBin) {
554  pair < int, int > in = pair < int, int > (idAin, idBin);
555  if (in2sp.find(in) == in2sp.end()) {
556  // Try the other way around as well
557  swap(in.first, in.second);
558  if (in2sp.find(in) == in2sp.end()) return false;
559  }
560  subprocess = in2sp[in];
561  idA = idAin;
562  mA = particleDataPtr->m0(idA);
563  idB = idBin;
564  mB = particleDataPtr->m0(idB);
565  return true;
566 }
567 
568 //--------------------------------------------------------------------------
569 
570 // Calculate: mode = 0 (sigma elastic), 1 (sigma total), 2 (dSigma/dcTheta)
571 
572 double SigmaPartialWave::sigma(int mode, double Wcm, double cTheta) {
573  // Below threshold, return 0
574  if (Wcm < (mA + mB + MASSSAFETY)) return 0.;
575 
576  // Return values
577  complex amp[2] = { complex(0., 0.) };
578  double sig = 0.;
579 
580  // Kinematic variables
581  double s = pow2(Wcm);
582  double k2 = (s - pow2(mB + mA)) * (s - pow2(mB - mA)) / 4. / s;
583 
584  // Precompute all required Pl and Pl' values
585  double sTheta = 0.;
586  if (mode == 2) {
587  if (process == 2) sTheta = sqrt(1. - pow2(cTheta));
588  legendreP(cTheta, ((process == 2) ? true : false));
589  }
590 
591  // Loop over L
592  for (int L = 0; L < Lmax; L++) {
593 
594  // Loop over J (only J = 0 for spinless)
595  complex ampJ[2] = { complex(0., 0.) };
596  int Jstart = (process != 2) ? 0 : 2 * L - 1;
597  int Jend = (process != 2) ? 1 : 2 * L + 2;
598  int Jstep = (process != 2) ? 1 : 2;
599  int Jcount = 0;
600  for (int J = Jstart; J < Jend; J += Jstep, Jcount++) {
601 
602  // Loop over isospin coefficients
603  for (int I = 0; I < Imax; I++) {
604  if (isoCoeff[subprocess][I] == 0.) continue;
605 
606  // Check wave exists
607  int LIJ = L * LSHIFT + I * ISHIFT + J;
608  if (pwData.find(LIJ) == pwData.end()) continue;
609 
610  // Extrapolation / interpolation (not for last bin)
611  map < double, complex >::iterator it = pwData[LIJ].upper_bound(Wcm);
612  if (it == pwData[LIJ].begin()) ++it;
613  double ar, ai;
614  if (it == pwData[LIJ].end()) {
615  ar = (--it)->second.real();
616  ai = it->second.imag();
617  } else {
618  double eA = it->first;
619  complex ampA = (it--)->second;
620  double eB = it->first;
621  complex ampB = it->second;
622 
623  ar = (ampA.real() - ampB.real()) / (eA - eB) *
624  (Wcm - eB) + ampB.real();
625  ai = (ampA.imag() - ampB.imag()) / (eA - eB) *
626  (Wcm - eB) + ampB.imag();
627  }
628 
629  // Isospin sum
630  ampJ[Jcount] += isoCoeff[subprocess][I] * complex(ar, ai);
631  }
632  }
633 
634  // Partial wave sum. Sigma elastic
635  if (mode == 0) {
636  if (process == 0 || process == 1) {
637  sig += (2. * L + 1.) * (ampJ[0] * conj(ampJ[0])).real();
638  } else if (process == 2) {
639  sig += ( (L + 0.) * (ampJ[0] * conj(ampJ[0])).real() +
640  (L + 1.) * (ampJ[1] * conj(ampJ[1])).real() );
641  }
642 
643  // Sigma total
644  } else if (mode == 1) {
645  if (process == 0 || process == 1) {
646  sig += (2. * L + 1.) * ampJ[0].imag();
647  } else if (process == 2) {
648  sig += ( (L + 0.) * ampJ[0].imag() + (L + 1.) * ampJ[1].imag() );
649  }
650 
651  // dSigma
652  } else if (mode == 2) {
653  if (process == 0 || process == 1) {
654  amp[0] += (2. * L + 1.) * ampJ[0] * PlVec[L];
655  } else if (process == 2) {
656  amp[0] += ((L + 0.) * ampJ[0] + double(L + 1.) * ampJ[1]) * PlVec[L];
657  amp[1] += complex(0., 1.) * (ampJ[1] - ampJ[0]) * sTheta * PlpVec[L];
658  }
659  }
660 
661  } // for (L)
662 
663  // Normalisation and return
664  if (mode == 0 || mode == 1) {
665  if (norm == 0) sig *= 4. * M_PI / k2 * CONVERT2MB;
666  else if (norm == 1) sig *= 64. * M_PI / s * CONVERT2MB;
667 
668  } else if (mode == 2) {
669  sig = (amp[0] * conj(amp[0])).real() + (amp[1] * conj(amp[1])).real();
670  if (norm == 0) sig *= 2. * M_PI / k2 * CONVERT2MB;
671  else if (norm == 1) sig *= 32. * M_PI / s * CONVERT2MB;
672  }
673  // Half for identical
674  return ((idA == idB) ? 0.5 : 1.) * sig;
675 }
676 
677 
678 //--------------------------------------------------------------------------
679 
680 // Bonnet's recursion formula for Legendre polynomials and derivatives
681 
682 void SigmaPartialWave::legendreP(double ct, bool deriv) {
683  if (Lmax > 1) PlVec[1] = ct;
684  for (int L = 2; L < Lmax; L++) {
685  PlVec[L] = ( (2. * L - 1.) * ct * PlVec[L - 1] -
686  (L - 1.) * PlVec[L - 2] ) / double(L);
687  if (deriv)
688  PlpVec[L] = ( (2. * L - 1.) * (PlVec[L - 1] + ct * PlpVec[L - 1]) -
689  (L - 1.) * PlpVec[L - 2] ) / double(L);
690  }
691  return;
692 }
693 
694 
695 //==========================================================================
696 
697 // HadronScatter class
698 
699 //--------------------------------------------------------------------------
700 
701 // Perform initialization and store pointers.
702 
703 bool HadronScatter::init(Info* infoPtrIn, Settings& settings,
704  Rndm *rndmPtrIn, ParticleData *particleDataPtr) {
705  // Save incoming pointers
706  infoPtr = infoPtrIn;
707  rndmPtr = rndmPtrIn;
708 
709  // Settings for new model.
710  scatterMode = settings.mode("HadronScatter:mode");
711  p2max = pow2(settings.parm("HadronScatter:pMax"));
712  yDiffMax = settings.parm("HadronScatter:yDiffMax");
713  Rmax = settings.parm("HadronScatter:Rmax");
714  scatSameString = settings.flag("HadronScatter:scatterSameString");
715  scatMultTimes = settings.flag("HadronScatter:scatterMultipleTimes");
716  maxProbDS = settings.parm("HadronScatter:maxProbDS");
717  neighNear = double(settings.mode("HadronScatter:neighbourNear"));
718  neighFar = double(settings.mode("HadronScatter:neighbourFar"));
719  minProbSS = settings.parm("HadronScatter:minProbSS");
720  maxProbSS = settings.parm("HadronScatter:maxProbSS");
721 
722  // Settings for old model.
723  doOldScatter = (scatterMode == 2);
724  afterDecay = settings.flag("HadronScatter:afterDecay");
725  allowDecayProd = settings.flag("HadronScatter:allowDecayProd");
726  scatterRepeat = settings.flag("HadronScatter:scatterRepeat");
727  // Hadron selection
728  hadronSelect = settings.mode("HadronScatter:hadronSelect");
729  Npar = settings.parm("HadronScatter:N");
730  kPar = settings.parm("HadronScatter:k");
731  pPar = settings.parm("HadronScatter:p");
732  // Scattering probability
733  scatterProb = settings.mode("HadronScatter:scatterProb");
734  jPar = settings.parm("HadronScatter:j");
735  rMax = settings.parm("HadronScatter:rMax");
736  rMax2 = rMax * rMax;
737  doTile = settings.flag("HadronScatter:tile");
738 
739  // String fragmentation and MPI settings
740  pTsigma = 2.0 * settings.parm("StringPT:sigma");
741  pTsigma2 = pTsigma * pTsigma;
742  double pT0ref = settings.parm("MultipartonInteractions:pT0ref");
743  double eCMref = settings.parm("MultipartonInteractions:eCMref");
744  double eCMpow = settings.parm("MultipartonInteractions:eCMpow");
745  double eCMnow = infoPtr->eCM();
746  pT0MPI = pT0ref * pow(eCMnow / eCMref, eCMpow);
747 
748  if (doOldScatter) {
749  // Tiling
750  double mp2 = particleDataPtr->m0(111) * particleDataPtr->m0(111);
751  double eA = infoPtr->eA();
752  double eB = infoPtr->eB();
753  double pzA = sqrt(eA * eA - mp2);
754  double pzB = -sqrt(eB * eB - mp2);
755  yMax = 0.5 * log((eA + pzA) / (eA - pzA));
756  yMin = 0.5 * log((eB + pzB) / (eB - pzB));
757  // Size in y and phi
758  if (doTile) {
759  ytMax = int((yMax - yMin) / rMax);
760  ytSize = (yMax - yMin) / double(ytMax);
761  ptMax = int(2. * M_PI / rMax);
762  ptSize = 2. * M_PI / double(ptMax);
763  } else {
764  ytMax = 1;
765  ytSize = yMax - yMin;
766  ptMax = 1;
767  ptSize = 2. * M_PI;
768  }
769  // Initialise tiles
770  tile.resize(ytMax);
771  for (int yt = 0; yt < ytMax; yt++) tile[yt].resize(ptMax);
772 
773  // Find path to data files, i.e. xmldoc directory location.
774  // Environment variable takes precedence, else use constructor input.
775  // XXX - as in Pythia.cc, but not passed around in e.g. Info/Settings,
776  // so redo here
777  string xmlPath = "";
778  const char* PYTHIA8DATA = "PYTHIA8DATA";
779  char* envPath = getenv(PYTHIA8DATA);
780  if (envPath != 0 && *envPath != '\0') {
781  int i = 0;
782  while (*(envPath+i) != '\0') xmlPath += *(envPath+(i++));
783  } else xmlPath = "../xmldoc";
784  if (xmlPath[ xmlPath.length() - 1 ] != '/') xmlPath += "/";
785 
786  // Hadron scattering partial wave cross sections
787  if ( !sigmaPW[0].init(0, xmlPath, "pipi-Froggatt.dat",
788  infoPtr, particleDataPtr, rndmPtr) ) return false;
789  if ( !sigmaPW[1].init(1, xmlPath, "piK-Estabrooks.dat",
790  infoPtr, particleDataPtr, rndmPtr) ) return false;
791  if ( !sigmaPW[2].init(2, xmlPath, "piN-SAID-WI08.dat",
792  infoPtr, particleDataPtr, rndmPtr) ) return false;
793  sigElMax = 0.;
794  sigElMax = max(sigElMax, sigmaPW[0].getSigmaElMax());
795  sigElMax = max(sigElMax, sigmaPW[1].getSigmaElMax());
796  sigElMax = max(sigElMax, sigmaPW[2].getSigmaElMax());
797 
798  // DEBUG
799  debugOutput();
800  }
801 
802  return true;
803 }
804 
805 
806 //--------------------------------------------------------------------------
807 
808 // Debug output
809 
810 void HadronScatter::debugOutput() {
811  // Print settings
812  cout << "Hadron scattering:" << endl
813  << " scatter = " << ((doOldScatter) ? "on" : "off") << endl
814  << " afterDecay = " << ((afterDecay) ? "on" : "off") << endl
815  << " allowDecayProd = " << ((allowDecayProd) ? "on" : "off") << endl
816  << " scatterRepeat = " << ((scatterRepeat) ? "on" : "off") << endl
817  << " tile = " << ((doTile) ? "on" : "off") << endl
818  << " yMin = " << yMin << endl
819  << " yMax = " << yMax << endl
820  << " ytMax = " << ytMax << endl
821  << " ytSize = " << ytSize << endl
822  << " ptMax = " << ptMax << endl
823  << " ptSize = " << ptSize << endl
824  << endl
825  << " hadronSelect = " << hadronSelect << endl
826  << " N = " << Npar << endl
827  << " k = " << kPar << endl
828  << " p = " << pPar << endl
829  << endl
830  << " scatterProb = " << scatterProb << endl
831  << " j = " << jPar << endl
832  << " rMax = " << rMax << endl
833  << endl
834  << " pTsigma = " << pTsigma2 << endl
835  << " pT0MPI = " << pT0MPI << endl
836  << endl
837  << " sigElMax = " << sigElMax << endl << endl;
838 
839  return;
840 }
841 
842 
843 //--------------------------------------------------------------------------
844 
845 // Perform hadron scattering - new version. Collective flow.
846 // Option 0: inv mass cut + probability based on rapidity difference.
847 // Option 1: probability based on difference in rapidity & azimuthal angle.
848 
849 void HadronScatter::scatter(Event& event) {
850 
851  // Fill a list with iHadron and rapidity.
852  vector< pair<int,double> > hadronRapidity;
853  for (int i = 0; i < int(event.size()); i++) {
854  if (event[i].isFinal() && event[i].isHadron())
855  hadronRapidity.push_back( pair<int,double>( i, event[i].y() ) );
856  }
857  // Sort in rapidity.
858  mergeSortCollFlow(hadronRapidity);
859 
860  // Fill list with possible hadron combinations.
861  vector< pair<int,int> > hadCombis;
862  for (int i1 = 0; i1 < int(hadronRapidity.size()) - 1; i1++) {
863  int iHad1 = hadronRapidity[i1].first;
864  // Go to increasing rapidity until yDiffMax/Rmax is reached.
865  for (int i2 = i1 + 1; i2 < int(hadronRapidity.size()); i2++) {
866  int iHad2 = hadronRapidity[i2].first;
867  // Safety: Skip the same hadron.
868  if (iHad1 == iHad2) continue;
869 
870  // For hadrons in the same string, decide if scattering should be done.
871  bool sameStr = ( (event[iHad1].mother1() == event[iHad2].mother1()) &&
872  (event[iHad1].mother2() == event[iHad2].mother2()) );
873  if (sameStr) {
874  if (!scatSameString) continue;
875  int indxDiff = abs(iHad1 - iHad2);
876  if (indxDiff < neighNear) continue;
877  double probNow = maxProbSS;
878  if (indxDiff < neighFar) {
879  if (neighFar == neighNear) probNow = max(maxProbSS,minProbSS);
880  else {
881  double grad = (maxProbSS - minProbSS) / (neighFar - neighNear);
882  double yint = maxProbSS - grad * neighFar;
883  probNow = grad * indxDiff + yint;
884  }
885  }
886  if (rndmPtr->flat() > probNow) continue;
887  }
888 
889  // Rapidity difference.
890  double yDiff = abs( hadronRapidity[i1].second
891  - hadronRapidity[i2].second );
892 
893  // Option 0:
894  if (scatterMode == 0) {
895  // Done once we went far enough in rapidity difference.
896  if (yDiff > yDiffMax) break;
897  // Check if invariant mass is small enough.
898  Vec4 pHad[2] = { event[iHad1].p(), event[iHad2].p() };
899  double m2max = pow2( sqrt(pHad[0].m2Calc() + p2max) +
900  sqrt(pHad[1].m2Calc() + p2max) );
901  if ( (pHad[0] + pHad[1]).m2Calc() > m2max ) continue;
902  // Probability linear between max and 0 for rapidity difference
903  // between 0 and yDiffMax.
904  if (rndmPtr->flat() > maxProbDS * (1.0 - yDiff / yDiffMax) ) continue;
905  }
906 
907  // Option 1:
908  else if (scatterMode == 1) {
909  // sqrt(yDiff^2+aDiff^2) >= yDiff; if yDiff > Rmax we went far enough.
910  if (yDiff > Rmax) break;
911  double aDiff = abs( event[iHad1].phi() - event[iHad2].phi() );
912  if (aDiff > M_PI) aDiff = 2. * M_PI - aDiff;
913  double Rdiff = sqrt( pow2(yDiff) + pow2(aDiff) );
914  // Probability linear between max and 0 for R difference
915  // between 0 and Rmax.
916  if (rndmPtr->flat() > maxProbDS * (1.0 - Rdiff / Rmax)) continue;
917  }
918 
919  // Save hadron pair.
920  hadCombis.push_back( pair<int,int>(iHad1,iHad2) );
921  // Done with loop over partners in case hadrons can scatter only once.
922  if (!scatMultTimes) break;
923  }
924  }
925 
926  // Now loop through the hadron pairs that will be changed, in random order.
927  int nPair = hadCombis.size();
928  for (int iPair = 0; iPair < nPair; ++iPair) {
929  int iPnow = min( int( rndmPtr->flat() * (nPair - iPair) ),
930  nPair - iPair - 1);
931  int iHad[2] = { hadCombis[iPnow].first, hadCombis[iPnow].second };
932 
933  // In case the hadrons already scattered, we need to get the new momenta.
934  bool hasScat[2] = {!event[iHad[0]].isFinal(), !event[iHad[1]].isFinal()};
935  for (int i = 0; i < 2; i++) if (hasScat[i]) {
936  bool found = false;
937  while (!found) {
938  iHad[i] = event[iHad[i]].daughter1();
939  if (event[iHad[i]].isFinal()) found = true;
940  }
941  }
942 
943  // Boost into CMS frame of hadron pair, rotate at random and boost back.
944  Vec4 pHad[2] = { event[iHad[0]].p(), event[iHad[1]].p() };
945  Vec4 pSumHad = pHad[0] + pHad[1];
946  double thetaRndm = acos( 2. * rndmPtr->flat() - 1.);
947  double phiRndm = 2. * M_PI * rndmPtr->flat();
948  for (int i = 0; i < 2; i++) {
949  pHad[i].bstback( pSumHad);
950  pHad[i].rot( thetaRndm, phiRndm);
951  pHad[i].bst( pSumHad);
952  }
953 
954  // Put new momenta into event record as new, copied particles.
955  for (int i = 0; i < 2; i++) {
956  // Copy old hadron.
957  int iNew = event.copy( iHad[i], (hasScat[i] ? 112 : 111));
958  // Change momentum.
959  event[iNew].p(pHad[i]);
960  }
961 
962  // Remove already considered pair fromn list.
963  hadCombis[iPnow] = hadCombis.back();
964  hadCombis.pop_back();
965  }
966 
967  // Done.
968  return;
969 }
970 
971 //--------------------------------------------------------------------------
972 
973 // Perform hadron scattering - old version.
974 
975 void HadronScatter::scatterOld(Event& event) {
976  // Reset tiles
977  for (int yt = 0; yt < ytMax; yt++)
978  for (int pt = 0; pt < ptMax; pt++)
979  tile[yt][pt].clear();
980 
981  // Generate list of hadrons which can take part in the scattering
982  for (int i = 0; i < event.size(); i++)
983  if (event[i].isFinal() && event[i].isHadron() && canScatter(event, i))
984  tile[yTile(event, i)][pTile(event, i)].insert(HSIndex(i, i));
985 
986  // Generate all pairwise interaction probabilities
987  vector < HadronScatterPair > scatterList;
988  // For each tile and for each hadron in the tile do pairing
989  for (int pt1 = 0; pt1 < ptMax; pt1++)
990  for (int yt1 = 0; yt1 < ytMax; yt1++)
991  for (set < HSIndex >::iterator si1 = tile[yt1][pt1].begin();
992  si1 != tile[yt1][pt1].end(); si1++)
993  tileIntProb(scatterList, event, *si1, yt1, pt1, false);
994  // Sort by ordering measure (largest to smallest)
995  sort(scatterList.rbegin(), scatterList.rend());
996 
997  // Reset list of things that have scattered
998  if (scatterRepeat) scattered.clear();
999 
1000  // Do scatterings
1001  while (scatterList.size() > 0) {
1002  // Check still valid and scatter
1003  HadronScatterPair &hsp = scatterList[0];
1004  if (!event[hsp.i1.second].isFinal() || !event[hsp.i2.second].isFinal()) {
1005  scatterList.erase(scatterList.begin());
1006  continue;
1007  }
1008  // Remove old entries in tiles and scatter
1009  tile[hsp.yt1][hsp.pt1].erase(hsp.i1);
1010  tile[hsp.yt2][hsp.pt2].erase(hsp.i2);
1011  hadronScatter(event, hsp);
1012  // Store new indices for later
1013  HSIndex iNew1 = hsp.i1, iNew2 = hsp.i2;
1014 
1015  // Check if hadrons can scatter again
1016  bool resort = false;
1017  if (scatterRepeat) {
1018  // Check for new scatters of iNew1 and iNew2
1019  HSIndex iNew = iNew1;
1020  for (int i = 0; i < 2; i++) {
1021  if (canScatter(event, iNew.second)) {
1022  // If both can scatter again, make sure they can't scatter
1023  // with each other
1024  if (i == 1) scattered.insert(HSIndex(min(iNew1.first, iNew2.first),
1025  max(iNew1.first, iNew2.first)));
1026  int yt = yTile(event, iNew.second);
1027  int pt = pTile(event, iNew.second);
1028  resort = tileIntProb(scatterList, event, iNew, yt, pt, true);
1029  tile[yt][pt].insert(iNew);
1030  }
1031  iNew = iNew2;
1032  } // for (i)
1033 
1034  } // if (scatterRepeat)
1035 
1036  // Remove the old entry and onto next
1037  scatterList.erase(scatterList.begin());
1038  // Resort list if anything added
1039  if (resort) sort(scatterList.rbegin(), scatterList.rend());
1040 
1041  } // while (scatterList.size() > 0)
1042 
1043  // Done.
1044  return;
1045 }
1046 
1047 
1048 //--------------------------------------------------------------------------
1049 
1050 // Criteria for if a hadron is allowed to scatter or not
1051 
1052 bool HadronScatter::canScatter(Event& event, int i) {
1053  // Probability to accept
1054  double p = 0.;
1055 
1056  // Pions, K+, K-, p+, pbar- only
1057  if (scatterProb == 1 || scatterProb == 2)
1058  if (event[i].idAbs() != 111 && event[i].idAbs() != 211 &&
1059  event[i].idAbs() != 321 && event[i].idAbs() != 2212)
1060  return false;
1061 
1062  // Probability
1063  switch (hadronSelect) {
1064  case 0:
1065  double t1 = exp( - event[i].pT2() / 2. / pTsigma2);
1066  double t2 = pow(pT0MPI, pPar) /
1067  pow(pT0MPI * pT0MPI + event[i].pT2(), pPar / 2.);
1068  p = Npar * t1 / ( (1 - kPar) * t1 + kPar * t2 );
1069  break;
1070  }
1071 
1072  // Return true/false
1073  if (p > rndmPtr->flat()) return true;
1074  else return false;
1075 }
1076 
1077 
1078 //--------------------------------------------------------------------------
1079 
1080 // Probability for scattering
1081 bool HadronScatter::doesScatter(Event& event, const HSIndex &i1,
1082  const HSIndex &i2) {
1083  Particle &p1 = event[i1.second];
1084  Particle &p2 = event[i2.second];
1085 
1086  // Can't come from the same decay
1087  if (!allowDecayProd && event[i1.first].mother1() ==
1088  event[i2.first].mother1() && event[event[i1.first].mother1()].isHadron())
1089  return false;
1090 
1091  // Check that the two hadrons have not already scattered
1092  if (scatterRepeat &&
1093  scattered.find(HSIndex(min(i1.first, i2.first), max(i1.first, i2.first)))
1094  != scattered.end()) return false;
1095 
1096  // K-K, p-p and K-p not allowed
1097  int id1 = min(p1.idAbs(), p2.idAbs());
1098  int id2 = max(p1.idAbs(), p2.idAbs());
1099  if (scatterProb == 1 || scatterProb == 2) {
1100  if ((id1 == 321 || id1 == 2212) && id1 == id2) return false;
1101  if (id1 == 321 && id2 == 2212) return false;
1102  }
1103 
1104  // Distance in y - phi space
1105  double dy = p1.y() - p2.y();
1106  double dp = abs(p1.phi() - p2.phi());
1107  if (dp > M_PI) dp = 2 * M_PI - dp;
1108  double dr2 = dy * dy + dp * dp;
1109  double p = max(0., 1. - dr2 / rMax2);
1110 
1111  // Additional factor depending on scatterProb
1112  if (scatterProb == 0 || scatterProb == 1) {
1113  p *= jPar;
1114 
1115  // Additional pair dependent probability
1116  } else if (scatterProb == 2) {
1117  // Wcm and which partial wave amplitude to use
1118  double Wcm = (p1.p() + p2.p()).mCalc();
1119  int pw = 0;
1120  if ((id1 == 111 || id1 == 211) && (id2 == 111 || id2 == 211)) pw = 0;
1121  else if ((id1 == 111 || id1 == 211) && id2 == 321) pw = 1;
1122  else if ((id1 == 111 || id1 == 211) && id2 == 2212) pw = 2;
1123  else {
1124  infoPtr->errorMsg("Error in HadronScatter::doesScatter:"
1125  "unknown subprocess");
1126  }
1127  if (!sigmaPW[pw].setSubprocess(p1.id(), p2.id())) {
1128  infoPtr->errorMsg("Error in HadronScatter::doesScatter:"
1129  "setSubprocess failed");
1130  } else {
1131  p *= 1 - exp(-jPar * sigmaPW[pw].sigmaEl(Wcm));
1132  }
1133  }
1134 
1135  // Return true/false
1136  return (p > rndmPtr->flat());
1137 }
1138 
1139 
1140 //--------------------------------------------------------------------------
1141 
1142 // Calculate ordering measure
1143 
1144 double HadronScatter::measure(Event& event, int idx1, int idx2) {
1145  Particle &p1 = event[idx1];
1146  Particle &p2 = event[idx2];
1147  return abs(p1.pT() / p1.mT() - p2.pT() / p2.mT());
1148 }
1149 
1150 
1151 //--------------------------------------------------------------------------
1152 
1153 // Scatter a pair
1154 
1155 bool HadronScatter::hadronScatter(Event& event, HadronScatterPair &hsp) {
1156  bool doSwap = (0.5 < rndmPtr->flat()) ? true : false;
1157  if (doSwap) swap(hsp.i1, hsp.i2);
1158 
1159  Particle &p1 = event[hsp.i1.second];
1160  Particle &p2 = event[hsp.i2.second];
1161 
1162  // Pick theta and phi (always flat)
1163  double ct = 0., phi = 2 * M_PI * rndmPtr->flat();
1164 
1165  // Flat for all flavours
1166  if (scatterProb == 0 || scatterProb == 1) {
1167  ct = 2. * rndmPtr->flat() - 1.;
1168 
1169  // pi-pi, pi-K and pi-p only using partial wave amplitudes
1170  } else if (scatterProb == 2) {
1171  // Wcm and which partial wave amplitude to use
1172  int id1 = min(p1.idAbs(), p2.idAbs());
1173  int id2 = max(p1.idAbs(), p2.idAbs());
1174  double Wcm = (p1.p() + p2.p()).mCalc();
1175  int pw = 0;
1176  if ((id1 == 111 || id1 == 211) && (id2 == 111 || id2 == 211)) pw = 0;
1177  else if ((id1 == 111 || id1 == 211) && id2 == 321) pw = 1;
1178  else if ((id1 == 111 || id1 == 211) && id2 == 2212) pw = 2;
1179  else {
1180  infoPtr->errorMsg("Error in HadronScatter::hadronScatter:"
1181  "unknown subprocess");
1182  }
1183  sigmaPW[pw].setSubprocess(p1.id(), p2.id());
1184  ct = sigmaPW[pw].pickCosTheta(Wcm);
1185  }
1186 
1187  // Rotation
1188  RotBstMatrix sMat;
1189  sMat.toCMframe(p1.p(), p2.p());
1190  sMat.rot(acos(ct), phi);
1191  sMat.fromCMframe(p1.p(), p2.p());
1192  Vec4 v1 = p1.p(), v2 = p2.p();
1193  v1.rotbst(sMat);
1194  v2.rotbst(sMat);
1195 
1196  // Update event record
1197  int iNew1 = event.copy(hsp.i1.second, 98);
1198  event[iNew1].p(v1);
1199  event[iNew1].e(event[iNew1].eCalc());
1200  event[hsp.i1.second].statusNeg();
1201  int iNew2 = event.copy(hsp.i2.second, 98);
1202  event[iNew2].p(v2);
1203  event[iNew2].e(event[iNew2].eCalc());
1204  event[hsp.i2.second].statusNeg();
1205 
1206  // New indices in event record
1207  hsp.i1.second = iNew1;
1208  hsp.i2.second = iNew2;
1209 
1210  if (doSwap) swap(hsp.i1, hsp.i2);
1211  return true;
1212 }
1213 
1214 
1215 //--------------------------------------------------------------------------
1216 
1217 // Calculate pair interaction probabilities in nearest-neighbour tiles
1218 // (yt1, pt1) represents centre cell (8):
1219 // 7 | 0 | 1
1220 // -----------
1221 // 6 | 8 | 2
1222 // -----------
1223 // 5 | 4 | 3
1224 
1225 bool HadronScatter::tileIntProb(vector < HadronScatterPair > &hsp,
1226  Event &event, const HSIndex &i1, int yt1, int pt1, bool doAll) {
1227  // Track if a new pair is added
1228  bool pairAdded = false;
1229 
1230  // Special handling for pairing in own tile
1231  if (!doAll) {
1232  set < HSIndex >::iterator si2 = tile[yt1][pt1].find(i1);
1233  while (++si2 != tile[yt1][pt1].end())
1234  // Calculate if scatters
1235  if (doesScatter(event, i1, *si2)) {
1236  double m = measure(event, i1.second, si2->second);
1237  hsp.push_back(HadronScatterPair(i1, yt1, pt1, *si2, yt1, pt1, m));
1238  }
1239  }
1240 
1241  // And the rest
1242  int tileMax = (doAll) ? 9 : 4;
1243  for (int tileNow = 0; tileNow < tileMax; tileNow++) {
1244  // New (yt, pt) coordinate
1245  int yt2 = yt1, pt2 = pt1;
1246  switch (tileNow) {
1247  case 0: ++pt2; break;
1248  case 1: ++yt2; ++pt2; break;
1249  case 2: ++yt2; break;
1250  case 3: ++yt2; --pt2; break;
1251  case 4: --pt2; break;
1252  case 5: --yt2; --pt2; break;
1253  case 6: --yt2; break;
1254  case 7: --yt2; ++pt2; break;
1255  }
1256 
1257  // Limit in rapidity tiles
1258  if (yt2 < 0 || yt2 >= ytMax) continue;
1259  // Wraparound for phi tiles
1260  if (pt2 < 0) {
1261  pt2 = ptMax - 1;
1262  if (pt2 == pt1 || pt2 == pt1 + 1) continue;
1263 
1264  } else if (pt2 >= ptMax) {
1265  pt2 = 0;
1266  if (pt2 == pt1 || pt2 == pt1 - 1) continue;
1267  }
1268 
1269  // Interaction probability
1270  for (set < HSIndex >::iterator si2 = tile[yt2][pt2].begin();
1271  si2 != tile[yt2][pt2].end(); si2++) {
1272  // Calculate if scatters
1273  if (doesScatter(event, i1, *si2)) {
1274  double m = measure(event, i1.second, si2->second);
1275  hsp.push_back(HadronScatterPair(i1, yt1, pt1, *si2, yt2, pt2, m));
1276  pairAdded = true;
1277  }
1278  }
1279  }
1280 
1281  return pairAdded;
1282 }
1283 
1284 //--------------------------------------------------------------------------
1285 
1286 // Functions for presorting the hadrons for collective flow.
1287 
1288 void HadronScatter::mergeSortCollFlow(vector< pair<int,double> >& sort,
1289  int iStart, int iEnd) {
1290 
1291  // For default arguments, use the range of the whole vector.
1292  if (iEnd < 0) {
1293  iStart = 1;
1294  iEnd = int(sort.size());
1295  }
1296 
1297  // Only need sorting if more than one entry.
1298  if (iStart < iEnd) {
1299  // Divide into two pieces, sort both iteratively and merge afterwards.
1300  int iDivide = (iEnd-iStart)/2;
1301  mergeSortCollFlow( sort, iStart, iStart + iDivide);
1302  mergeSortCollFlow( sort, iStart + iDivide + 1, iEnd);
1303  mergeCollFlow( sort, iStart, iDivide, iEnd);
1304  }
1305 }
1306 
1307 void HadronScatter::mergeCollFlow(vector< pair<int,double> >& sort,
1308  int iStart, int iDivide, int iEnd) {
1309 
1310  // Set both starting and ending points.
1311  int iStart1 = iStart - 1;
1312  int iEnd1 = iStart + iDivide - 1;
1313  int iStart2 = iStart + iDivide;
1314  int iEnd2 = iEnd - 1;
1315  // New, merged vector.
1316  vector< pair<int,double> > out;
1317 
1318  // Add in case we do not start with the first entry.
1319  for (int i = 0; i < iStart - 1; i++) out.push_back( sort[i] );
1320 
1321  // Merge two sequences.
1322  int iNow1 = iStart1;
1323  int iNow2 = iStart2;
1324  while ( (iNow1 <= iEnd1) && (iNow2 <= iEnd2) ) {
1325  if (sort[iNow1].second < sort[iNow2].second) {
1326  out.push_back(sort[iNow1]);
1327  iNow1++;
1328  } else {
1329  out.push_back(sort[iNow2]);
1330  iNow2++;
1331  }
1332  }
1333 
1334  // Add the leftover entries.
1335  if (iNow1 <= iEnd1) {
1336  for (int i = iNow1; i <= iEnd1; i++) out.push_back( sort[i] );
1337  } else if (iNow2 <= iEnd2) {
1338  for (int i = iNow2; i <= iEnd2; i++) out.push_back( sort[i] );
1339  }
1340 
1341  // Add in case we do not end with the last entry.
1342  for (int i = iEnd; i < int(sort.size()); i++) out.push_back( sort[i] );
1343 
1344  // Overwrite input.
1345  sort = out;
1346 }
1347 
1348 //==========================================================================
1349 
1350 } // namespace Pythia8
Definition: AgUStep.h:26