StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
SigmaTotal.cc
1 // SigmaTotal.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 SigmaTotal class,
7 // and the auxiliary classes SigmaTotAux, SigmaTotOwn, SigmaSaSDL, SigmaMBR,
8 // SigmaABMST and SigmaRPP.
9 
10 #include "Pythia8/SigmaTotal.h"
11 
12 namespace Pythia8 {
13 
14 //==========================================================================
15 
16 // The SigmaTotAux class.
17 // Base class for the individual implementations.
18 
19 //--------------------------------------------------------------------------
20 
21 // alpha_em(0).
22 const double SigmaTotAux::ALPHAEM = 0.00729353;
23 
24 // Conversion coefficients = 1/(16pi) * (mb <-> GeV^2).
25 const double SigmaTotAux::CONVERTEL = 0.0510925;
26 
27 // Proton and pion masses, and their squares. Euler's constant.
28 const double SigmaTotAux::MPROTON = 0.9382720;
29 const double SigmaTotAux::SPROTON = 0.8803544;
30 const double SigmaTotAux::MPION = 0.1349766;
31 const double SigmaTotAux::SPION = 0.0182187;
32 const double SigmaTotAux::GAMMAEUL = 0.577215665;
33 
34 // Reference scale for nominal definition of t slope.
35 const double SigmaTotAux::TABSREF = 2e-3;
36 
37 // Numerical integration parameters.
38 const int SigmaTotAux::NPOINTS = 1000;
39 const double SigmaTotAux::TABSMAX = 1.;
40 const double SigmaTotAux::MINSLOPEEL = 10.;
41 
42 //--------------------------------------------------------------------------
43 
44 // Initialize Coulomb correction parameters.
45 
46 bool SigmaTotAux::initCoulomb(Settings& settings,
47  ParticleData* particleDataPtrIn) {
48 
49  // Save pointer to particle database.
50  particleDataPtr = particleDataPtrIn,
51 
52  // User-set values for total and elastic cross section.
53  tryCoulomb = settings.flag("SigmaElastic:Coulomb");
54  rhoOwn = settings.parm("SigmaElastic:rho");
55  tAbsMin = settings.parm("SigmaElastic:tAbsMin");
56  lambda = settings.parm("SigmaElastic:lambda");
57  phaseCst = settings.parm("SigmaElastic:phaseConst");
58 
59  return true;
60 
61 }
62 
63 //--------------------------------------------------------------------------
64 
65 // Add Coulomb corrections to the elastic and total cross sections.
66 
67 bool SigmaTotAux::addCoulomb() {
68 
69  // Trivial case when there should be no Coulomb contribution.
70  hasCou = false;
71  sigTotCou = sigTot;
72  sigElCou = sigEl;
73 
74  // Relative sign (or zero) for Coulomb term in elastic scattering.
75  int iChA = particleDataPtr->chargeType(idA);
76  int iChB = particleDataPtr->chargeType(idB);
77  chgSgn = 0.;
78  if (iChA * iChB > 0) chgSgn = 1.;
79  if (iChA * iChB < 0) chgSgn = -1.;
80 
81  // Done if no Coulomb corrections.
82  if (!tryCoulomb || iChA * iChB == 0) return false;
83 
84  // Reduce hadronic part of elastic cross section by tMin cut.
85  sigElCou = sigEl * exp( - bEl * tAbsMin);
86  if (tAbsMin < 0.9 * TABSMAX) {
87 
88  // Loop through t range according to dt/t^2.
89  double sigCou = 0.;
90  double sigInt = 0.;
91  double xRel, tAbs, form2, phase;
92  for (int i = 0; i < NPOINTS; ++i) {
93  xRel = (i + 0.5) / NPOINTS;
94  tAbs = tAbsMin * TABSMAX / (tAbsMin + xRel * (TABSMAX - tAbsMin));
95 
96  // Evaluate Coulomb and interference terms.
97  form2 = pow4(lambda/(lambda + tAbs));
98  sigCou += pow2(form2);
99  phase = chgSgn * ALPHAEM * (-phaseCst - log(0.5 * bEl * tAbs));
100  sigInt += form2 * exp(-0.5 * bEl * tAbs) * tAbs
101  * (rhoOwn * cos(phase) + sin(phase));
102  }
103 
104  // Include common factors to give new elastic and total cross sections.
105  sigCou *= pow2(ALPHAEM) / (4. * CONVERTEL * tAbsMin) ;
106  sigInt *= - chgSgn * ALPHAEM * sigTot / tAbsMin;
107  sigElCou += (sigCou + sigInt) / NPOINTS;
108  hasCou = true;
109  }
110  sigTotCou = sigTot - sigEl + sigElCou;
111 
112  // Done.
113  return true;
114 
115 }
116 
117 //--------------------------------------------------------------------------
118 
119 // Coulomb contribution to the differential elastic cross sections.
120 
121 double SigmaTotAux::dsigmaElCoulomb( double t) {
122 
123  // Coulomb contribution and interference.
124  double form2 = pow4(lambda/(lambda - t));
125  double phase = chgSgn * ALPHAEM * (-phaseCst - log(-0.5 * bEl * t));
126  return pow2(chgSgn * ALPHAEM * form2) / (4. * CONVERTEL * t*t)
127  - chgSgn * ALPHAEM * form2 * sigTot * exp(0.5 * bEl * t)
128  * (rhoOwn * cos(phase) + sin(phase)) / (-t);
129 
130 }
131 
132 //==========================================================================
133 
134 // The SigmaTotal class.
135 // Parametrizes total, elastic and diffractive cross sections,
136 // making use of the other clases below.
137 
138 //--------------------------------------------------------------------------
139 
140 // Definitions of static variables.
141 
142 // Minimum threshold below which no cross sections will be defined.
143 const double SigmaTotal::MMIN = 2.;
144 
145 //--------------------------------------------------------------------------
146 
147 // Store pointer to Info and initialize data members.
148 
149 void SigmaTotal::init() {
150 
151  // Choice of mode.
152  modeTotEl = mode("SigmaTotal:mode");
153  modeDiff = mode("SigmaDiffractive:mode");
154 
155 }
156 
157 //--------------------------------------------------------------------------
158 
159 // Calculate, or recalculate for new beams or new energy.
160 
161 bool SigmaTotal::calc(int idA, int idB, double eCM) {
162 
163  // Initial values.
164  isCalc = ispp = false;
165  s = eCM * eCM;
166 
167  // Find hadron masses and check that energy is enough.
168  // For mesons use the corresponding vector meson masses.
169  idAbsA = abs(idA);
170  idAbsB = abs(idB);
171  int idModA = (idAbsA < 100 || idAbsA > 1000) ? idAbsA : 10 * (idAbsA/10) + 3;
172  int idModB = (idAbsB < 100 || idAbsB > 1000) ? idAbsB : 10 * (idAbsB/10) + 3;
173  if (idAbsA == 22) idModA = 113;
174  if (idAbsB == 22) idModB = 113;
175  if (idAbsA == 990) idModA = idAbsA;
176  if (idAbsB == 990) idModB = idAbsB;
177  double mA = particleDataPtr->m0(idModA);
178  double mB = particleDataPtr->m0(idModB);
179  if (eCM < mA + mB + MMIN) {
180  infoPtr->errorMsg("Error in SigmaTotal::calc: too low energy");
181  return false;
182  }
183 
184  // Most options only work for pp/ppbar, so may need to modify choice.
185  // Treat a neutron like a proton (except no Coulomb term).
186  modeTotElNow = modeTotEl;
187  modeDiffNow = modeDiff;
188  if (idAbsA == 2112) idAbsA = 2212;
189  if (idAbsB == 2112) idAbsB = 2212;
190  if (idAbsA != 2212 || idAbsB != 2212) {
191  modeTotElNow = min(1, modeTotEl);
192  modeDiffNow = min(1, modeDiff);
193  }
194  ispp = (idAbsA == 2212 && idAbsB == 2212 && idA * idB > 0);
195 
196  // Set up pointer to class that handles total and elastic cross sections.
197  if (sigTotElPtr) delete sigTotElPtr;
198  if (modeTotElNow == 0) sigTotElPtr = new SigmaTotOwn();
199  else if (modeTotElNow == 1) sigTotElPtr = new SigmaSaSDL();
200  else if (modeTotElNow == 2) sigTotElPtr = new SigmaMBR();
201  else if (modeTotElNow == 3) sigTotElPtr = new SigmaABMST();
202  else sigTotElPtr = new SigmaRPP();
203 
204  // Initialize and calculate for selected total/elastic class.
205  sigTotElPtr->init(infoPtr);
206  if ( !sigTotElPtr->calcTotEl( idA, idB, s, mA, mB) ) return false;
207 
208  // Set up pointer to class that handles diffractive cross sections.
209  if (sigDiffPtr) delete sigDiffPtr;
210  if (modeDiffNow == 0) sigDiffPtr = new SigmaTotOwn();
211  else if (modeDiffNow == 1) sigDiffPtr = new SigmaSaSDL();
212  else if (modeDiffNow == 2) sigDiffPtr = new SigmaMBR();
213  else sigDiffPtr = new SigmaABMST();
214 
215  // Initialize and calculate for selected diffractive class.
216  sigDiffPtr->init(infoPtr);
217  if ( !sigDiffPtr->calcDiff( idA, idB, s, mA, mB) ) return false;
218 
219  // Inelastic nondiffractive by unitarity.
220  double sigTotTmp = sigTotElPtr->sigTot;
221  sigND = sigTotTmp - sigTotElPtr->sigEl - sigDiffPtr->sigXB
222  - sigDiffPtr->sigAX - sigDiffPtr->sigXX - sigDiffPtr->sigAXB;
223  if (sigND < 0.) {
224  infoPtr->errorMsg("Error in SigmaTotal::init: sigND < 0");
225  return false;
226  } else if (sigND < 0.4 * sigTotTmp) infoPtr->errorMsg("Warning in "
227  "SigmaTotal::init: sigND suspiciously low");
228 
229  // Done.
230  isCalc = true;
231  return true;
232 
233 }
234 
235 //--------------------------------------------------------------------------
236 
237 // Sample the VMD states for resolved photons.
238 
239 void SigmaTotal::chooseVMDstates(int idA, int idB, double eCM,
240  int processCode) {
241 
242  // Constants and initial values.
243  double gammaFac[4] = {2.2, 23.6, 18.4, 11.5};
244  double alphaEM = 0.00729353;
245  double idVMD[4] = {113, 223, 333, 443};
246  double pVP[4] = {0.};
247  double pVV[4][4] = {{0.}};
248  double pSum = 0.;
249  int nVMD = 4;
250 
251  // Values to start with.
252  pair<int, int> idAB = make_pair(idA, idB);
253 
254  // gamma-gamma.
255  if (idA == 22 && idB == 22) {
256  for (int i = 0; i < nVMD; ++i)
257  for (int j = 0; j < nVMD; ++j) {
258  // Evaluate the cross sections individually.
259  calc(idVMD[i], idVMD[j], eCM);
260  pVV[i][j] = pow2(alphaEM) / (gammaFac[i] * gammaFac[j]);
261  if (processCode == 101) pVV[i][j] *= sigmaND();
262  else if (processCode == 102) pVV[i][j] *= sigmaEl();
263  else if (processCode == 103) pVV[i][j] *= sigmaXB();
264  else if (processCode == 104) pVV[i][j] *= sigmaAX();
265  else if (processCode == 105) pVV[i][j] *= sigmaXX();
266  pSum += pVV[i][j];
267  }
268 
269  // Choose VMD states based on relative fractions.
270  double pickMode = rndmPtr->flat() * pSum;
271  bool pairFound = false;
272  for (int i = 0; i < nVMD; ++i) {
273  for (int j = 0; j < nVMD; ++j) {
274  pickMode -= pVV[i][j];
275  if (pickMode < 0.) {
276  idAB = make_pair(113 + 110 * i, 113 + 110 * j);
277  pairFound = true;
278  break;
279  }
280  }
281  if (pairFound) break;
282  }
283 
284  // gamma + p.
285  } else if (idA == 22 && idB == 2212) {
286  for (int i = 0; i < nVMD; ++i) {
287  // Evaluate the cross sections individually.
288  calc(idVMD[i], 2212, eCM);
289  pVP[i] = alphaEM / gammaFac[i];
290  if (processCode == 101) pVP[i] *= sigmaND();
291  else if (processCode == 102) pVP[i] *= sigmaEl();
292  else if (processCode == 103) pVP[i] *= sigmaXB();
293  else if (processCode == 104) pVP[i] *= sigmaAX();
294  else if (processCode == 105) pVP[i] *= sigmaXX();
295  pSum += pVP[i];
296  }
297 
298  // Choose VMD state based on relative fractions.
299  double pickMode = rndmPtr->flat() * pSum;
300  for (int i = 0; i < nVMD; ++i){
301  pickMode -= pVP[i];
302  if (pickMode < 0.){
303  idAB = make_pair(113 + 110 * i, 2212);
304  break;
305  }
306  }
307 
308  // p + gamma.
309  } else if (idA == 2212 && idB == 22) {
310  for (int i = 0; i < nVMD; ++i) {
311  // Evaluate the cross sections individually.
312  calc(2212, idVMD[i], eCM);
313  pVP[i] = alphaEM / gammaFac[i];
314  if (processCode == 101) pVP[i] *= sigmaND();
315  else if (processCode == 102) pVP[i] *= sigmaEl();
316  else if (processCode == 103) pVP[i] *= sigmaXB();
317  else if (processCode == 104) pVP[i] *= sigmaAX();
318  else if (processCode == 105) pVP[i] *= sigmaXX();
319  pSum += pVP[i];
320  }
321 
322  // Choose VMD state based on relative fractions.
323  double pickMode = rndmPtr->flat() * pSum;
324  for (int i = 0; i < nVMD; ++i){
325  pickMode -= pVP[i];
326  if (pickMode < 0.){
327  idAB = make_pair(2212, 113 + 110 * i);
328  break;
329  }
330  }
331  }
332 
333  // Reset to the original cross section.
334  calc(idA, idB, eCM);
335 
336  // Propagate the selected states to Info class for further usage.
337  if (idAB.first == 113 || idAB.first == 223 || idAB.first == 333
338  || idAB.first == 443) {
339  double mA = particleDataPtr->mSel(idAB.first);
340  double scA = alphaEM / gammaFac[idAB.first/100 - 1];
341  infoPtr->setVMDstateA(true, idAB.first, mA, scA);
342  }
343  if (idAB.second == 113 || idAB.second == 223 || idAB.second == 333
344  || idAB.second == 443) {
345  double mB = particleDataPtr->mSel(idAB.second);
346  double scB = alphaEM / gammaFac[idAB.second/100 - 1];
347  infoPtr->setVMDstateB(true, idAB.second, mB, scB);
348  }
349 }
350 
351 //==========================================================================
352 
353 // The SigmaTotOwn class.
354 // Parametrizes total, elastic and diffractive cross sections
355 // by user settings.
356 
357 //--------------------------------------------------------------------------
358 
359 // Initialize data members.
360 
361 void SigmaTotOwn::init(Info* infoPtrIn) {
362 
363  // Use shorthand for settings
364  Settings& settings = *infoPtrIn->settingsPtr;
365 
366  // Main user-set values for total and elastic cross sections.
367  sigTot = settings.parm("SigmaTotal:sigmaTot");
368  sigEl = settings.parm("SigmaTotal:sigmaEl");
369  bEl = settings.parm("SigmaElastic:bSlope");
370 
371  // Initialize parameters for Coulomb corrections to elastic scattering.
372  initCoulomb( settings, infoPtrIn->particleDataPtr);
373 
374  // User-set values for diffractive cross sections.
375  sigXB = settings.parm("SigmaTotal:sigmaXB");
376  sigAX = settings.parm("SigmaTotal:sigmaAX");
377  sigXX = settings.parm("SigmaTotal:sigmaXX");
378  sigAXB = settings.parm("SigmaTotal:sigmaAXB");
379 
380  // Set diffraction parameters.
381  pomFlux = settings.mode("SigmaDiffractive:PomFlux");
382 
383  // Set up Pomeron flux constants, see HardDiffraction::init.
384  a0 = 1. + settings.parm("SigmaDiffractive:PomFluxEpsilon");
385  ap = settings.parm("SigmaDiffractive:PomFluxAlphaPrime");
386 
387  // Schuler-Sj�strand.
388  if (pomFlux == 1) {
389  b0 = 2.3;
390 
391  // Bruni-Ingelman.
392  } else if (pomFlux == 2) {
393  A1 = 6.38;
394  A2 = 0.424;
395  a1 = 8.;
396  a2 = 3.;
397 
398  // Streng-Berger.
399  } else if (pomFlux == 3) {
400  a1 = 4.7;
401 
402  // Donnachie-Landshoff.
403  } else if (pomFlux == 4) {
404  A1 = 0.27;
405  a1 = 8.38;
406  A2 = 0.56;
407  a2 = 3.78;
408  A3 = 0.18;
409  a3 = 1.36;
410 
411  // MBR.
412  } else if (pomFlux == 5) {
413  A1 = 0.9;
414  a1 = 4.6;
415  A2 = 0.1;
416  a2 = 0.6;
417  a0 = 1. + settings.parm("SigmaDiffractive:MBRepsilon");
418  ap = settings.parm("SigmaDiffractive:MBRalpha");
419 
420  // H1 Fit A, B.
421  } else if (pomFlux == 6 || pomFlux == 7) {
422  ap = 0.06;
423  b0 = 5.5;
424  a0 = (pomFlux == 6) ? 1.1182 : 1.1110;
425  }
426 
427  // b_min for double diffraction, suppression of small gaps, minimal CD mass.
428  bMinDD = settings.parm("SigmaDiffractive:OwnbMinDD");
429  dampenGap = settings.flag("SigmaDiffractive:OwndampenGap");
430  ygap = settings.parm("SigmaDiffractive:Ownygap");
431  ypow = settings.parm("SigmaDiffractive:Ownypow");
432  expPygap = exp(ypow * ygap);
433  mMinCDnow = settings.parm("SigmaDiffractive:OwnmMinCD");
434 
435 }
436 
437 //--------------------------------------------------------------------------
438 
439 // With total and elastic cross section already set, only add Coulomb.
440 
441 bool SigmaTotOwn::calcTotEl( int idAin, int idBin, double , double , double) {
442 
443  // Save some input.
444  idA = idAin;
445  idB = idBin;
446  isExpEl = true;
447 
448  // Possibly allow Coulomb correction + interference.
449  addCoulomb();
450 
451  // Done.
452  return true;
453 
454 }
455 
456 //--------------------------------------------------------------------------
457 
458 // Differential elastic cross section.
459 
460 double SigmaTotOwn::dsigmaEl( double t, bool useCoulomb, bool ) {
461 
462  // Hadronic contribution: simple exponential.
463  double dsig = CONVERTEL * pow2(sigTot) * (1. + pow2(rhoOwn)) * exp(bEl * t);
464 
465  // Possibly add Coulomb contribution and interference.
466  if (useCoulomb && hasCou) dsig += dsigmaElCoulomb(t);
467 
468  // Done.
469  return dsig;
470 
471 }
472 
473 //--------------------------------------------------------------------------
474 
475 // Differential single diffractive cross sections as provided by the
476 // x-weighted Pomeron flux, see HardDiffraction::xfPom for details.
477 
478 double SigmaTotOwn::dsigmaSD(double xi, double t, bool , int ) {
479 
480  // Common setup.
481  wtNow = 1.;
482  yNow = -log(xi);
483 
484  // Schuler-Sj�strand.
485  if (pomFlux == 1) {
486  b = 2. * b0 + 2. * ap * yNow;
487  wtNow = exp(b * t);
488 
489  // Bruni-Ingelman.
490  } else if (pomFlux == 2) {
491  wtNow = A1 * exp(a1 * t) + A2 * exp(a2 * t);
492 
493  // Streng-Berger.
494  } else if (pomFlux == 3) {
495  b = a1 + 2. * ap * yNow;
496  wtNow = pow( xi, 2. - 2. * a0) * exp(b * t);
497 
498  // Donnachie-Landshoff.
499  } else if (pomFlux == 4) {
500  Q = 2. * ap * yNow;
501  wtNow = pow( xi, 2. - 2. * a0) * ( A1 * exp((Q + a1) * t)
502  + A2 * exp((Q + a2) * t) + A3 * exp((Q + a3) * t) );
503 
504  // MBR.
505  } else if (pomFlux == 5) {
506  Q = 2. * ap * yNow;
507  wtNow = pow( xi, 2. - 2. * a0)
508  * (A1 * exp((Q + a1) * t) + A2 * exp((Q + a2) * t) );
509 
510  // H1 Fit A, B.
511  } else if (pomFlux == 6 || pomFlux == 7) {
512  b = b0 + 2. * ap * yNow;
513  wtNow = pow( xi, 2. - 2. * a0) * exp(b * t);
514  }
515  // Optionally dampen with 1 / (1 + exp( -p * (y - y_gap))).
516  if (dampenGap) wtNow /= 1. + expPygap * pow( xi, ypow);
517 
518  // Done.
519  return wtNow;
520 
521 }
522 
523 //--------------------------------------------------------------------------
524 
525 // Differential double diffractive cross sections.
526 // Naive non-authorized generalization of the simple Pomeron fluxes above.
527 
528 double SigmaTotOwn::dsigmaDD(double xi1, double xi2, double t, int ) {
529 
530  // Common setup.
531  wtNow = 1.;
532  yNow = - log(xi1 * xi2 * s / SPROTON);
533 
534  // Schuler-Sj�strand.
535  if (pomFlux == 1) {
536  b = max( bMinDD, 2. * ap * yNow);
537  wtNow = exp(b * t);
538 
539  // Bruni-Ingelman.
540  } else if (pomFlux == 2) {
541  wtNow = A1 * exp(a1 * t) + A2 * exp(a2 * t);
542 
543  // Streng-Berger.
544  } else if (pomFlux == 3) {
545  b = max( bMinDD, 2. * ap * yNow);
546  wtNow = pow( xi1 * xi2, 2. - 2. * a0) * exp(b * t);
547 
548  // Donnachie-Landshoff.
549  } else if (pomFlux == 4) {
550  Q = max( bMinDD, 2. * ap * yNow);
551  wtNow = pow( xi1 * xi2, 2. - 2. * a0) * exp(Q * t);
552 
553  // MBR.
554  } else if (pomFlux == 5) {
555  Q = max( bMinDD, 2. * ap * yNow);
556  wtNow = pow( xi1 * xi2, 2. - 2. * a0) * exp(Q * t);
557 
558  // H1 Fit A, B.
559  } else if (pomFlux == 6 || pomFlux == 7) {
560  b = max( bMinDD, 2. * ap * yNow);
561  wtNow = pow( xi1 * xi2, 2. - 2. * a0) * exp(b * t);
562  }
563 
564  // Optionally dampen with 1 / (1 + exp( -p * (y - y_gap))).
565  if (dampenGap) wtNow /= 1. + expPygap * pow( xi1 * xi2 * s / SPROTON, ypow);
566 
567  // Done.
568  return wtNow;
569 
570 }
571 
572 //--------------------------------------------------------------------------
573 
574 // Differential central diffractive cross section.
575 // Naive non-authorized generalization of the simple Pomeron fluxes above.
576 
577 double SigmaTotOwn::dsigmaCD( double xi1, double xi2, double t1, double t2,
578  int ) {
579 
580  // Common setup.
581  wtNow = 1.;
582  yNow1 = -log(xi1);
583  yNow2 = -log(xi2);
584 
585  // Schuler-Sj�strand.
586  if (pomFlux == 1) {
587  b1 = 2. * b0 + 2. * ap * yNow1;
588  b2 = 2. * b0 + 2. * ap * yNow2;
589  wtNow = exp(b1 * t1 + b2 * t2);
590 
591  // Bruni-Ingelman.
592  } else if (pomFlux == 2) {
593  wtNow = (A1 * exp(a1 * t1) + A2 * exp(a2 * t1))
594  * (A1 * exp(a1 * t2) + A2 * exp(a2 * t2));
595 
596  // Streng-Berger.
597  } else if (pomFlux == 3) {
598  b1 = a1 + 2. * ap * yNow1;
599  b2 = a1 + 2. * ap * yNow2;
600  wtNow = pow( xi1 * xi2, 2. - 2. * a0) * exp(b1 * t1 + b2 * t2);
601 
602  // Donnachie-Landshoff.
603  } else if (pomFlux == 4) {
604  Q1 = 2. * ap * yNow1;
605  Q2 = 2. * ap * yNow2;
606  wtNow = pow( xi1 * xi2, 2. - 2. * a0) * ( A1 * exp((Q1 + a1) * t1)
607  + A2 * exp((Q1 + a2) * t1) + A3 * exp((Q1 + a3) * t1) )
608  * ( A1 * exp((Q2 + a1) * t2) + A2 * exp((Q2 + a2) * t2)
609  + A3 * exp((Q2 + a3) * t2) );
610 
611  // MBR.
612  } else if (pomFlux == 5) {
613  Q1 = 2. * ap * yNow1;
614  Q2 = 2. * ap * yNow2;
615  wtNow = pow( xi1 * xi2, 2. - 2. * a0)
616  * (A1 * exp((Q1 + a1) * t1) + A2 * exp((Q1 + a2) * t1) )
617  * (A1 * exp((Q2 + a1) * t2) + A2 * exp((Q2 + a2) * t2) );
618 
619  // H1 Fit A, B.
620  } else if (pomFlux == 6 || pomFlux == 7) {
621  b1 = b0 + 2. * ap * yNow1;
622  b2 = b0 + 2. * ap * yNow2;
623  wtNow = pow( xi1 * xi2, 2. - 2. * a0) * exp(b1 * t1 + b2 * t2);
624  }
625 
626  // Optionally dampen with 1 / (1 + exp( -p * (y - y_gap))) for both gaps.
627  if (dampenGap) wtNow /= (1. + expPygap * pow( xi1, ypow))
628  * (1. + expPygap * pow( xi2, ypow));
629 
630  // Done.
631  return wtNow;
632 
633 }
634 
635 //==========================================================================
636 
637 // The SigmaSaSDL class.
638 // Formulae are taken from:
639 // G.A. Schuler and T. Sjostrand, Phys. Rev. D49 (1994) 2257,
640 // Z. Phys. C73 (1997) 677
641 // which borrows some total cross sections from
642 // A. Donnachie and P.V. Landshoff, Phys. Lett. B296 (1992) 227.
643 
644 // Implemented processes with their process number iProc:
645 // = 0 : p + p; = 1 : pbar + p;
646 // = 2 : pi+ + p; = 3 : pi- + p; = 4 : pi0/rho0 + p;
647 // = 5 : phi + p; = 6 : J/psi + p;
648 // = 7 : rho + rho; = 8 : rho + phi; = 9 : rho + J/psi;
649 // = 10 : phi + phi; = 11 : phi + J/psi; = 12 : J/psi + J/psi.
650 // = 13 : gamma + p (preliminary); 14 : gamma + gamma (preliminary);
651 // = 15 : Pom + p (preliminary).
652 // For now a neutron is treated like a proton.
653 
654 //--------------------------------------------------------------------------
655 
656 // Definitions of static variables.
657 // Note that a lot of parameters are hardcoded as const here, rather
658 // than being interfaced for public change, since any changes would
659 // have to be done in a globally consistent manner. Which basically
660 // means a rewrite/replacement of the whole class.
661 
662 // General constants in total cross section parametrization:
663 // sigmaTot = X * s^epsilon + Y * s^eta (pomeron + reggeon).
664 // Christine added Pom + p, gamma + gamma and gamma + p.
665 const double SigmaSaSDL::EPSILON = 0.0808;
666 const double SigmaSaSDL::ETA = -0.4525;
667 const double SigmaSaSDL::X[] = { 21.70, 21.70, 13.63, 13.63, 13.63,
668  10.01, 0.970, 8.56, 6.29, 0.609, 4.62, 0.447, 0.0434, 67.7e-3, 211e-6};
669 const double SigmaSaSDL::Y[] = { 56.08, 98.39, 27.56, 36.02, 31.79,
670  1.51, -0.146, 13.08, -0.62, -0.060, 0.030, -0.0028, 0.00028, 129e-3,
671  215e-6};
672 
673 // Type of the two incoming hadrons as function of the process number:
674 // = 0 : p/n ; = 1 : pi/rho/omega; = 2 : phi; = 3 : J/psi.
675 const int SigmaSaSDL::IHADATABLE[] = { 0, 0, 1, 1, 1, 2, 3, 1, 1,
676  1, 2, 2, 3};
677 const int SigmaSaSDL::IHADBTABLE[] = { 0, 0, 0, 0, 0, 0, 0, 1, 2,
678  3, 2, 3, 3};
679 
680 // Hadron-Pomeron coupling beta(t) = beta(0) * exp(b*t).
681 // 0 = Pom + p, 1 = Pom + pi/rho/omega, 2 = Pom + phi, 3 = Pom + J/psi.
682 const double SigmaSaSDL::BETA0[] = { 4.658, 2.926, 2.149, 0.208};
683 const double SigmaSaSDL::BHAD[] = { 2.3, 1.4, 1.4, 0.23};
684 
685 // Pomeron trajectory alpha(t) = 1 + epsilon + alpha' * t
686 const double SigmaSaSDL::ALPHAPRIME = 0.25;
687 
688 // Conversion coefficients = 1/(16pi) * (mb <-> GeV^2) * (G_3P)^n,
689 // with n = 0 elastic, n = 1 single and n = 2 double diffractive.
690 const double SigmaSaSDL::CONVERTSD = 0.0336;
691 const double SigmaSaSDL::CONVERTDD = 0.0084;
692 
693 // Factors related to VMD processes in gamma+gamma and gamma+p
694 // Gammafac = f_V^2 / (4 pi) [cf. Schuler-Sjostrand 1996)
695 const int SigmaSaSDL::NVMD = 4;
696 const double SigmaSaSDL::GAMMAFAC[4] = {2.2, 23.6, 18.4, 11.5};
697 const double SigmaSaSDL::VMDMASS[4] = {0.77549, 0.78265, 1.01946,
698  3.09692};
699 
700 // Parameters and coefficients for single diffractive scattering.
701 const int SigmaSaSDL::ISDTABLE[] = { 0, 0, 1, 1, 1, 2, 3, 4, 5,
702  6, 7, 8, 9};
703 const double SigmaSaSDL::CSD[10][8] = {
704  { 0.213, 0.0, -0.47, 150., 0.213, 0.0, -0.47, 150., } ,
705  { 0.213, 0.0, -0.47, 150., 0.267, 0.0, -0.47, 100., } ,
706  { 0.213, 0.0, -0.47, 150., 0.232, 0.0, -0.47, 110., } ,
707  { 0.213, 7.0, -0.55, 800., 0.115, 0.0, -0.47, 110., } ,
708  { 0.267, 0.0, -0.46, 75., 0.267, 0.0, -0.46, 75., } ,
709  { 0.232, 0.0, -0.46, 85., 0.267, 0.0, -0.48, 100., } ,
710  { 0.115, 0.0, -0.50, 90., 0.267, 6.0, -0.56, 420., } ,
711  { 0.232, 0.0, -0.48, 110., 0.232, 0.0, -0.48, 110., } ,
712  { 0.115, 0.0, -0.52, 120., 0.232, 6.0, -0.56, 470., } ,
713  { 0.115, 5.5, -0.58, 570., 0.115, 5.5, -0.58, 570. } };
714 
715 // Parameters and coefficients for double diffractive scattering.
716 const int SigmaSaSDL::IDDTABLE[] = { 0, 0, 1, 1, 1, 2, 3, 4, 5,
717  6, 7, 8, 9};
718 const double SigmaSaSDL::CDD[10][9] = {
719  { 3.11, -7.34, 9.71, 0.068, -0.42, 1.31, -1.37, 35.0, 118., } ,
720  { 3.11, -7.10, 10.6, 0.073, -0.41, 1.17, -1.41, 31.6, 95., } ,
721  { 3.12, -7.43, 9.21, 0.067, -0.44, 1.41, -1.35, 36.5, 132., } ,
722  { 3.13, -8.18, -4.20, 0.056, -0.71, 3.12, -1.12, 55.2, 1298., } ,
723  { 3.11, -6.90, 11.4, 0.078, -0.40, 1.05, -1.40, 28.4, 78., } ,
724  { 3.11, -7.13, 10.0, 0.071, -0.41, 1.23, -1.34, 33.1, 105., } ,
725  { 3.12, -7.90, -1.49, 0.054, -0.64, 2.72, -1.13, 53.1, 995., } ,
726  { 3.11, -7.39, 8.22, 0.065, -0.44, 1.45, -1.36, 38.1, 148., } ,
727  { 3.18, -8.95, -3.37, 0.057, -0.76, 3.32, -1.12, 55.6, 1472., } ,
728  { 4.18, -29.2, 56.2, 0.074, -1.36, 6.67, -1.14, 116.2, 6532. } };
729 
730 //--------------------------------------------------------------------------
731 
732 // Store pointer to Info and initialize data members.
733 
734 void SigmaSaSDL::init(Info* infoPtrIn) {
735 
736  // Store pointer.
737  infoPtr = infoPtrIn;
738 
739  // Use shorthand for settings
740  Settings& settings = *infoPtrIn->settingsPtr;
741 
742  // Initialize parameters for Coulomb corrections to elastic scattering.
743  initCoulomb( settings, infoPtrIn->particleDataPtr);
744 
745  // User-set values to dampen diffractive cross sections.
746  doDampen = settings.flag("SigmaDiffractive:dampen");
747  maxXBOwn = settings.parm("SigmaDiffractive:maxXB");
748  maxAXOwn = settings.parm("SigmaDiffractive:maxAX");
749  maxXXOwn = settings.parm("SigmaDiffractive:maxXX");
750  maxAXBOwn = settings.parm("SigmaDiffractive:maxAXB");
751 
752  // Parameters for diffractive systems.
753  epsSaS = settings.parm("SigmaDiffractive:SaSepsilon");
754  sigmaPomP = settings.parm("Diffraction:sigmaRefPomP");
755  mPomP = settings.parm("Diffraction:mRefPomP");
756  pPomP = settings.parm("Diffraction:mPowPomP");
757  zeroAXB = settings.flag("SigmaTotal:zeroAXB");
758  sigAXB2TeV = settings.parm("SigmaTotal:sigmaAXB2TeV");
759 
760  // Diffractive mass spectrum starts at m + mMin0 and has a low-mass
761  // enhancement, factor cRes, up to around m + mRes0. Special for CD.
762  mMin0 = settings.parm("SigmaDiffractive:mMin");
763  cRes = settings.parm("SigmaDiffractive:lowMEnhance");
764  mRes0 = settings.parm("SigmaDiffractive:mResMax");
765  mMinCDnow = settings.parm("SigmaDiffractive:mMinCD");
766 
767  // Derived quantities.
768  alP2 = 2. * ALPHAPRIME;
769  s0 = 1. / ALPHAPRIME;
770 
771 }
772 
773 //--------------------------------------------------------------------------
774 
775 // Calculate total and (integrated) elastic cross sections.
776 
777 bool SigmaSaSDL::calcTotEl( int idAin, int idBin, double sIn, double mAin,
778  double mBin) {
779 
780  // Find appropriate combination of incoming beams.
781  idA = idAin;
782  idB = idBin;
783  s = sIn;
784  isExpEl = true;
785  if (!findBeamComb( idA, idB, mAin, mBin)) return false;
786  double sEps = pow( s, EPSILON);
787  double sEta = pow( s, ETA);
788 
789  // Ordinary hadron-hadron collisions. Total cross section.
790  if (iProc < 13) {
791  sigTot = X[iProc] * sEps + Y[iProc] * sEta;
792 
793  // Elastic slope parameter and cross section.
794  bEl = 2. * bA + 2. * bB + 4. * sEps - 4.2;
795  sigEl = CONVERTEL * pow2(sigTot) * (1. + pow2(rhoOwn)) / bEl;
796 
797  // gamma + p and p + gamma.
798  } else if (iProc == 13){
799  sigTot = X[iProc] * sEps + Y[iProc] * sEta;
800  double sigElNow = 0.;
801 
802  // Loop over VMD states on side A for elastic cross section.
803  for (int iA = 0; iA < NVMD; ++iA){
804  double bANow = BHAD[iHadAtmp[iA]];
805  double bBNow = BHAD[iHadBtmp[iA]];
806  double bElNow = 2. * bANow + 2. * bBNow + 4. * sEps - 4.2;
807  double tmpTot = X[iProcVP[iA]] * sEps
808  + Y[iProcVP[iA]] * sEta;
809  sigElNow += multVP[iA] * CONVERTEL * pow2(tmpTot)
810  * (1. + pow2(rhoOwn)) / bElNow;
811  }
812  sigEl = sigElNow;
813 
814  // gamma + gamma
815  } else if (iProc == 14){
816  sigTot = X[iProc] * sEps + Y[iProc] * sEta;
817  double sigElNow = 0.;
818 
819  // Loop over VMD states on side A and B for elastic cross section.
820  for (int iA = 0; iA < NVMD; ++iA)
821  for (int iB = 0; iB < NVMD; ++iB) {
822  double bANow = BHAD[iHadAtmp[iA]];
823  double bBNow = BHAD[iHadBtmp[iB]];
824  double bElNow = 2. * bANow + 2. * bBNow + 4. * sEps - 4.2;
825  double tmpTot = X[iProcVV[iA][iB]] * sEps
826  + Y[iProcVV[iA][iB]] * sEta;
827  sigElNow += multVV[iA][iB] * CONVERTEL * pow2(tmpTot)
828  * (1. + pow2(rhoOwn)) / bElNow;
829  }
830  sigEl = sigElNow;
831 
832  // Primitive implementation of Pomeron + p. No elastic scattering.
833  } else if (iProc == 15) {
834  sigTot = sigmaPomP * pow( sqrt(s) / mPomP, pPomP);
835  sigEl = 0.;
836  }
837 
838  // Possibly add Coulomb correction and interference.
839  addCoulomb();
840 
841  // Done.
842  return true;
843 
844 }
845 
846 //--------------------------------------------------------------------------
847 
848 // Differential elastic cross section.
849 
850 double SigmaSaSDL::dsigmaEl( double t, bool useCoulomb, bool ) {
851 
852  // Ordinary hadron-hadron collisions.
853  double dsig = 0.;
854  if (iProc < 13) {
855  dsig = CONVERTEL * pow2(sigTot) * (1. + pow2(rhoOwn)) * exp(bEl * t);
856 
857  // gamma + p and p + gamma: loop over VMD states on side A.
858  } else if (iProc == 13) {
859  double sEps = pow( s, EPSILON);
860  double sEta = pow( s, ETA);
861  double dsigNow = 0.;
862  for (int iA = 0; iA < NVMD; ++iA){
863  // Elastic slope parameter and cross section.
864  double bANow = BHAD[iHadAtmp[iA]];
865  double bBNow = BHAD[iHadBtmp[iA]];
866  double bElNow = 2. * bANow + 2. * bBNow + 4. * sEps - 4.2;
867  double tmpTot = X[iProcVP[iA]] * sEps
868  + Y[iProcVP[iA]] * sEta;
869  // Hadronic contribution: simple exponential.
870  dsigNow += multVP[iA] * CONVERTEL * pow2(tmpTot)
871  * (1. + pow2(rhoOwn)) * exp(bElNow * t);
872  }
873  dsig = dsigNow;
874 
875  // gamma + gamma: loop over VMD states on side A and B.
876  } else if (iProc == 14) {
877  double sEps = pow( s, EPSILON);
878  double sEta = pow( s, ETA);
879  double dsigNow = 0.;
880  for (int iA = 0; iA < NVMD; ++iA)
881  for (int iB = 0; iB < NVMD; ++iB){
882  // Elastic slope parameter and cross section.
883  double bANow = BHAD[iHadAtmp[iA]];
884  double bBNow = BHAD[iHadBtmp[iB]];
885  double bElNow = 2. * bANow + 2. * bBNow + 4. * sEps - 4.2;
886  double tmpTot = X[iProcVV[iA][iB]] * sEps
887  + Y[iProcVV[iA][iB]] * sEta;
888  // Hadronic contribution: simple exponential.
889  dsigNow += multVV[iA][iB] * CONVERTEL * pow2(tmpTot)
890  * (1. + pow2(rhoOwn)) * exp(bElNow * t);
891  }
892  dsig = dsigNow;
893 
894  // No elastic scattering for Pomeron + p.
895  } else dsig = 0.;
896 
897  // Possibly add Coulomb contribution and interference.
898  if (useCoulomb && hasCou) dsig += dsigmaElCoulomb(t);
899 
900  // Done.
901  return dsig;
902 
903 }
904 
905 //--------------------------------------------------------------------------
906 
907 // Diffractive cross sections.
908 
909 bool SigmaSaSDL::calcDiff( int idAin, int idBin, double sIn, double mAin,
910  double mBin) {
911 
912  // Find appropriate combination of incoming beams.
913  s = sIn;
914  idA = idAin;
915  idB = idBin;
916  mA = mAin;
917  mB = mBin;
918  if (!findBeamComb( idAin, idBin, mAin, mBin)) return false;
919  sigXB = sigAX = sigXX = sigAXB = 0.;
920 
921  // Ordinary hadron-hadron collisions.
922  if (iProc < 13) {
923  // Lookup coefficients for single and double diffraction.
924  int iSD = ISDTABLE[iProc];
925  int iDD = IDDTABLE[iProc];
926  double eCM = sqrt(s);
927  double sum1, sum2, sum3, sum4;
928 
929  // Single diffractive scattering A + B -> X + B cross section.
930  mMinXB = mA + mMin0;
931  double sMinXB = pow2(mMinXB);
932  mResXB = mA + mRes0;
933  sResXB = pow2(mResXB);
934  double sRMavgXB = mResXB * mMinXB;
935  double sRMlogXB = log(1. + sResXB/sMinXB);
936  double sMaxXB = CSD[iSD][0] * s + CSD[iSD][1];
937  double BcorrXB = CSD[iSD][2] + CSD[iSD][3] / s;
938  sum1 = log( (2.*bB + alP2 * log(s/sMinXB))
939  / (2.*bB + alP2 * log(s/sMaxXB)) ) / alP2;
940  sum2 = cRes * sRMlogXB / (2.*bB + alP2 * log(s/sRMavgXB) + BcorrXB) ;
941  sigXB = CONVERTSD * X[iProc] * BETA0[iHadB] * max( 0., sum1 + sum2);
942 
943  // Single diffractive scattering A + B -> A + X cross section.
944  mMinAX = mB + mMin0;
945  double sMinAX = pow2(mMinAX);
946  mResAX = mB + mRes0;
947  sResAX = pow2(mResAX);
948  double sRMavgAX = mResAX * mMinAX;
949  double sRMlogAX = log(1. + sResAX/sMinAX);
950  double sMaxAX = CSD[iSD][4] * s + CSD[iSD][5];
951  double BcorrAX = CSD[iSD][6] + CSD[iSD][7] / s;
952  sum1 = log( (2.*bA + alP2 * log(s/sMinAX))
953  / (2.*bA + alP2 * log(s/sMaxAX)) ) / alP2;
954  sum2 = cRes * sRMlogAX / (2.*bA + alP2 * log(s/sRMavgAX) + BcorrAX) ;
955  sigAX = CONVERTSD * X[iProc] * BETA0[iHadA] * max( 0., sum1 + sum2);
956 
957  // Order single diffractive correctly.
958  if (swapped) {
959  swap( bB, bA);
960  swap( sigXB, sigAX);
961  swap( mMinXB, mMinAX);
962  swap( mResXB, mResAX);
963  swap( iHadA, iHadB);
964  }
965 
966  // Double diffractive scattering A + B -> X1 + X2 cross section.
967  double y0min = log( s * SPROTON / (sMinXB * sMinAX) ) ;
968  double sLog = log(s);
969  double Delta0 = CDD[iDD][0] + CDD[iDD][1] / sLog
970  + CDD[iDD][2] / pow2(sLog);
971  sum1 = (y0min * (log( max( 1e-10, y0min/Delta0) ) - 1.) + Delta0)/ alP2;
972  if (y0min < 0.) sum1 = 0.;
973  double sMaxXX = s * ( CDD[iDD][3] + CDD[iDD][4] / sLog
974  + CDD[iDD][5] / pow2(sLog) );
975  double sLogUp = log( max( 1.1, s * s0 / (sMinXB * sRMavgAX) ));
976  double sLogDn = log( max( 1.1, s * s0 / (sMaxXX * sRMavgAX) ));
977  sum2 = cRes * log( sLogUp / sLogDn ) * sRMlogAX / alP2;
978  sLogUp = log( max( 1.1, s * s0 / (sMinAX * sRMavgXB) ));
979  sLogDn = log( max( 1.1, s * s0 / (sMaxXX * sRMavgXB) ));
980  sum3 = cRes * log(sLogUp / sLogDn) * sRMlogXB / alP2;
981  double BcorrXX = CDD[iDD][6] + CDD[iDD][7] / eCM + CDD[iDD][8] / s;
982  sum4 = pow2(cRes) * sRMlogAX * sRMlogXB
983  / max( 0.1, alP2 * log( s * s0 / (sRMavgAX * sRMavgXB) ) + BcorrXX);
984  sigXX = CONVERTDD * X[iProc] * max( 0., sum1 + sum2 + sum3 + sum4);
985 
986  // Central diffractive scattering A + B -> A + X + B, only p and pbar.
987  mMinAXB = 1.;
988  if ( (idAbsA == 2212 || idAbsA == 2112)
989  && (idAbsB == 2212 || idAbsB == 2112) && !zeroAXB) {
990  double sMinAXB = pow2(mMinAXB);
991  double sRefAXB = pow2(2000.);
992  sigAXB = sigAXB2TeV * pow( log(0.06 * s / sMinAXB), 1.5 )
993  / pow( log(0.06 * sRefAXB / sMinAXB), 1.5 );
994  }
995 
996  // Option with user-requested damping of diffractive cross sections.
997  if (doDampen) {
998  sigXB = sigXB * maxXBOwn / (sigXB + maxXBOwn);
999  sigAX = sigAX * maxAXOwn / (sigAX + maxAXOwn);
1000  sigXX = sigXX * maxXXOwn / (sigXX + maxXXOwn);
1001  sigAXB = (maxAXBOwn > 0.) ? sigAXB * maxAXBOwn / (sigAXB + maxAXBOwn)
1002  : 0.;
1003  }
1004 
1005  // gamma + p: loop over VMD states on side A.
1006  } else if (iProc == 13) {
1007  double sigAXNow = 0.;
1008  double sigXBNow = 0.;
1009  double sigXXNow = 0.;
1010 
1011  for (int iA = 0; iA < NVMD; ++iA){
1012 
1013  // Lookup coefficients for single and double diffraction.
1014  int iSD = ISDTABLE[iProcVP[iA]];
1015  int iDD = IDDTABLE[iProcVP[iA]];
1016  double eCM = sqrt(s);
1017  double sum1, sum2, sum3, sum4;
1018 
1019  // Single diffractive scattering A + B -> X + B cross section.
1020  mMinXB = mAtmp[iA] + mMin0;
1021  double sMinXB = pow2(mMinXB);
1022  mResXB = mAtmp[iA] + mRes0;
1023  sResXB = pow2(mResXB);
1024  double sRMavgXB = mResXB * mMinXB;
1025  double sRMlogXB = log(1. + sResXB/sMinXB);
1026  double sMaxXB = CSD[iSD][0] * s + CSD[iSD][1];
1027  double BcorrXB = CSD[iSD][2] + CSD[iSD][3] / s;
1028  double bBNow = BHAD[iHadBtmp[iA]];
1029  sum1 = log( (2.*bBNow + alP2 * log(s/sMinXB))
1030  / (2.*bBNow + alP2 * log(s/sMaxXB)) ) / alP2;
1031  sum2 = cRes * sRMlogXB
1032  / (2.*bBNow + alP2 * log(s/sRMavgXB) + BcorrXB) ;
1033  sigXBNow += multVP[iA] * CONVERTSD * X[iProcVP[iA]]
1034  * BETA0[iHadBtmp[iA]] * max( 0., sum1 + sum2);
1035 
1036  // Single diffractive scattering A + B -> A + X cross section.
1037  mMinAX = mBtmp[iA] + mMin0;
1038  double sMinAX = pow2(mMinAX);
1039  mResAX = mBtmp[iA] + mRes0;
1040  sResAX = pow2(mResAX);
1041  double sRMavgAX = mResAX * mMinAX;
1042  double sRMlogAX = log(1. + sResAX/sMinAX);
1043  double sMaxAX = CSD[iSD][4] * s + CSD[iSD][5];
1044  double BcorrAX = CSD[iSD][6] + CSD[iSD][7] / s;
1045  double bANow = BHAD[iHadAtmp[iA]];
1046  sum1 = log( (2.*bANow + alP2 * log(s/sMinAX))
1047  / (2.*bANow + alP2 * log(s/sMaxAX)) ) / alP2;
1048  sum2 = cRes * sRMlogAX
1049  / (2.*bANow + alP2 * log(s/sRMavgAX) + BcorrAX) ;
1050  sigAXNow += multVP[iA] * CONVERTSD * X[iProcVP[iA]]
1051  * BETA0[iHadAtmp[iA]] * max( 0., sum1 + sum2);
1052 
1053  // Double diffractive scattering A + B -> X1 + X2 cross section.
1054  double y0min = log( s * SPROTON / (sMinXB * sMinAX) ) ;
1055  double sLog = log(s);
1056  double Delta0 = CDD[iDD][0] + CDD[iDD][1] / sLog
1057  + CDD[iDD][2] / pow2(sLog);
1058  sum1 = (y0min * (log( max( 1e-10, y0min/Delta0) ) - 1.) + Delta0)/ alP2;
1059  if (y0min < 0.) sum1 = 0.;
1060  double sMaxXX = s * ( CDD[iDD][3] + CDD[iDD][4] / sLog
1061  + CDD[iDD][5] / pow2(sLog) );
1062  double sLogUp = log( max( 1.1, s * s0 / (sMinXB * sRMavgAX) ));
1063  double sLogDn = log( max( 1.1, s * s0 / (sMaxXX * sRMavgAX) ));
1064  sum2 = cRes * log( sLogUp / sLogDn ) * sRMlogAX / alP2;
1065  sLogUp = log( max( 1.1, s * s0 / (sMinAX * sRMavgXB) ));
1066  sLogDn = log( max( 1.1, s * s0 / (sMaxXX * sRMavgXB) ));
1067  sum3 = cRes * log(sLogUp / sLogDn) * sRMlogXB / alP2;
1068  double BcorrXX = CDD[iDD][6] + CDD[iDD][7] / eCM + CDD[iDD][8] / s;
1069  sum4 = pow2(cRes) * sRMlogAX * sRMlogXB
1070  /max( 0.1, alP2 * log( s * s0 / (sRMavgAX * sRMavgXB) ) + BcorrXX);
1071  sigXXNow += multVP[iA] * CONVERTDD * X[iProcVP[iA]]
1072  * max( 0., sum1 + sum2 + sum3 + sum4);
1073 
1074  // End of VMD loop.
1075  }
1076 
1077  // Order single diffractive correctly.
1078  if (swapped) {
1079  swap( bB, bA);
1080  swap( sigXB, sigAX);
1081  swap( mMinXB, mMinAX);
1082  swap( mResXB, mResAX);
1083  swap( iHadA, iHadB);
1084  swap( sigXBNow, sigAXNow);
1085  for (int i = 0; i < NVMD; ++i){
1086  swap( iHadAtmp[i], iHadBtmp[i]);
1087  swap( mAtmp[i], mBtmp[i]);
1088  }
1089  }
1090 
1091  // Option with user-requested damping of diffractive cross sections.
1092  if (doDampen) {
1093  sigXBNow = sigXBNow * maxXBOwn / (sigXBNow + maxXBOwn);
1094  sigAXNow = sigAXNow * maxAXOwn / (sigAXNow + maxAXOwn);
1095  sigXXNow = sigXXNow * maxXXOwn / (sigXXNow + maxXXOwn);
1096  }
1097  sigAX = sigAXNow;
1098  sigXB = sigXBNow;
1099  sigXX = sigXXNow;
1100  sigAXB = 0.;
1101 
1102  // gamma + gamma: loop over VMD states on sides A and B.
1103  } else if (iProc == 14) {
1104  double sigAXNow = 0.;
1105  double sigXBNow = 0.;
1106  double sigXXNow = 0.;
1107  for (int iA = 0; iA < NVMD; ++iA)
1108  for (int iB = 0; iB < NVMD; ++iB){
1109 
1110  // Lookup coefficients for single and double diffraction.
1111  int iSD = ISDTABLE[iProcVV[iA][iB]];
1112  int iDD = IDDTABLE[iProcVV[iA][iB]];
1113  double eCM = sqrt(s);
1114  double sum1, sum2, sum3, sum4;
1115 
1116  // Single diffractive scattering A + B -> X + B cross section.
1117  mMinXB = mAtmp[iA] + mMin0;
1118  double sMinXB = pow2(mMinXB);
1119  mResXB = mAtmp[iA] + mRes0;
1120  sResXB = pow2(mResXB);
1121  double sRMavgXB = mResXB * mMinXB;
1122  double sRMlogXB = log(1. + sResXB/sMinXB);
1123  double sMaxXB = CSD[iSD][0] * s + CSD[iSD][1];
1124  double BcorrXB = CSD[iSD][2] + CSD[iSD][3] / s;
1125  double bBNow = BHAD[iHadBtmp[iB]];
1126  sum1 = log( (2.*bBNow + alP2 * log(s/sMinXB))
1127  / (2.*bBNow + alP2 * log(s/sMaxXB)) ) / alP2;
1128  sum2 = cRes * sRMlogXB
1129  / (2.*bBNow + alP2 * log(s/sRMavgXB) + BcorrXB) ;
1130  sigXBNow += multVV[iA][iB] * CONVERTSD * X[iProcVV[iA][iB]]
1131  * BETA0[iHadBtmp[iB]] * max( 0., sum1 + sum2);
1132 
1133  // Single diffractive scattering A + B -> A + X cross section.
1134  mMinAX = mBtmp[iB] + mMin0;
1135  double sMinAX = pow2(mMinAX);
1136  mResAX = mBtmp[iB] + mRes0;
1137  sResAX = pow2(mResAX);
1138  double sRMavgAX = mResAX * mMinAX;
1139  double sRMlogAX = log(1. + sResAX/sMinAX);
1140  double sMaxAX = CSD[iSD][4] * s + CSD[iSD][5];
1141  double BcorrAX = CSD[iSD][6] + CSD[iSD][7] / s;
1142  double bANow = BHAD[iHadAtmp[iA]];
1143  sum1 = log( (2.*bANow + alP2 * log(s/sMinAX))
1144  / (2.*bANow + alP2 * log(s/sMaxAX)) ) / alP2;
1145  sum2 = cRes * sRMlogAX
1146  / (2.*bANow + alP2 * log(s/sRMavgAX) + BcorrAX) ;
1147  sigAXNow += multVV[iA][iB] * CONVERTSD * X[iProcVV[iA][iB]]
1148  * BETA0[iHadAtmp[iA]] * max( 0., sum1 + sum2);
1149 
1150  // Double diffractive scattering A + B -> X1 + X2 cross section.
1151  double y0min = log( s * SPROTON / (sMinXB * sMinAX) ) ;
1152  double sLog = log(s);
1153  double Delta0 = CDD[iDD][0] + CDD[iDD][1] / sLog
1154  + CDD[iDD][2] / pow2(sLog);
1155  sum1 = (y0min * (log( max( 1e-10, y0min/Delta0) ) - 1.) + Delta0)/ alP2;
1156  if (y0min < 0.) sum1 = 0.;
1157  double sMaxXX = s * ( CDD[iDD][3] + CDD[iDD][4] / sLog
1158  + CDD[iDD][5] / pow2(sLog) );
1159  double sLogUp = log( max( 1.1, s * s0 / (sMinXB * sRMavgAX) ));
1160  double sLogDn = log( max( 1.1, s * s0 / (sMaxXX * sRMavgAX) ));
1161  sum2 = cRes * log( sLogUp / sLogDn ) * sRMlogAX / alP2;
1162  sLogUp = log( max( 1.1, s * s0 / (sMinAX * sRMavgXB) ));
1163  sLogDn = log( max( 1.1, s * s0 / (sMaxXX * sRMavgXB) ));
1164  sum3 = cRes * log(sLogUp / sLogDn) * sRMlogXB / alP2;
1165  double BcorrXX = CDD[iDD][6] + CDD[iDD][7] / eCM + CDD[iDD][8] / s;
1166  sum4 = pow2(cRes) * sRMlogAX * sRMlogXB
1167  /max( 0.1, alP2 * log( s * s0 / (sRMavgAX * sRMavgXB) ) + BcorrXX);
1168  sigXXNow += multVV[iA][iB] * CONVERTDD * X[iProcVV[iA][iB]]
1169  * max( 0., sum1 + sum2 + sum3 + sum4);
1170 
1171  // End of VMD loop.
1172  }
1173 
1174  // Option with user-requested damping of diffractive cross sections.
1175  if (doDampen) {
1176  sigXBNow = sigXBNow * maxXBOwn / (sigXBNow + maxXBOwn);
1177  sigAXNow = sigAXNow * maxAXOwn / (sigAXNow + maxAXOwn);
1178  sigXXNow = sigXXNow * maxXXOwn / (sigXXNow + maxXXOwn);
1179  }
1180  sigAX = sigAXNow;
1181  sigXB = sigXBNow;
1182  sigXX = sigXXNow;
1183  sigAXB = 0.;
1184 
1185  // No diffractive scattering for Pomeron + p.
1186  } else return false;
1187 
1188  // Done.
1189  return true;
1190 
1191 }
1192 
1193 //--------------------------------------------------------------------------
1194 
1195 // Differential single diffractive cross sections.
1196 
1197 double SigmaSaSDL::dsigmaSD(double xi, double t, bool isXB, int ) {
1198 
1199  // Calculate mass; later checked to be above threshold. Optional weight.
1200  double m2X = xi * s;
1201  double mX = sqrt(m2X);
1202  double epsWt = pow( m2X, -epsSaS);
1203 
1204  // Ordinary hadron-hadron collisions.
1205  if (iProc < 13) {
1206 
1207  // Separate XB and AX cases since A and B masses/couplings may differ.
1208  if (isXB) {
1209  if (mX < mMinXB || pow2(mX + mMinAX) > s) return 0.;
1210 
1211  // Return differential AB -> XB cross section value.
1212  double bXB = 2. * bB + alP2 * log(1. / xi) ;
1213  return CONVERTSD * X[iProc] * BETA0[iHadB] * exp(bXB * t) * (1. - xi)
1214  * ( 1. + cRes * sResXB / (sResXB + m2X) ) * epsWt;
1215 
1216  } else {
1217  if (mX < mMinAX || pow2(mX + mMinXB) > s) return 0.;
1218 
1219  // Return differential AB -> AX cross section value.
1220  double bAX = 2. * bA + alP2 * log(1. / xi) ;
1221  return CONVERTSD * X[iProc] * BETA0[iHadA] * exp(bAX * t) * (1. - xi)
1222  * ( 1. + cRes * sResAX / (sResAX + m2X) ) * epsWt;
1223  }
1224 
1225  // gamma + p: loop over VMD states on side A.
1226  } else if (iProc == 13) {
1227  double sigNow = 0.;
1228  for (int iA = 0; iA < NVMD; ++iA){
1229 
1230  // Mass thresholds depend on VMD state.
1231  mMinXB = mAtmp[iA] + mMin0;
1232  mResXB = mAtmp[iA] + mRes0;
1233  sResXB = pow2(mResXB);
1234  mMinAX = mBtmp[iA] + mMin0;
1235  mResAX = mBtmp[iA] + mRes0;
1236  sResAX = pow2(mResAX);
1237 
1238  // Calculate and sum differential AB -> XB cross section value.
1239  if (isXB && mX > mMinXB && pow2(mX + mMinAX) < s) {
1240  double bBNow = BHAD[iHadBtmp[iA]];
1241  double bXBNow = 2. * bBNow + alP2 * log(1. / xi) ;
1242  sigNow += multVP[iA] * CONVERTSD * X[iProcVP[iA]]
1243  * BETA0[iHadBtmp[iA]] * exp(bXBNow * t) * (1. - xi)
1244  * ( 1. + cRes * sResXB / (sResXB + m2X) );
1245 
1246  // Calculate and sum differential AB -> AX cross section value.
1247  } else if (!isXB && mX > mMinAX && pow2(mX + mMinXB) < s) {
1248  double bANow = BHAD[iHadAtmp[iA]];
1249  double bAXNow = 2. * bANow + alP2 * log(1. / xi) ;
1250  sigNow += multVP[iA] * CONVERTSD * X[iProcVP[iA]]
1251  * BETA0[iHadAtmp[iA]] * exp(bAXNow * t) * (1. - xi)
1252  * ( 1. + cRes * sResAX / (sResAX + m2X) );
1253  }
1254  }
1255  return sigNow * epsWt;
1256 
1257  // gamma + gamma: loop over VMD states on side A and B.
1258  } else if (iProc == 14) {
1259  double sigNow = 0.;
1260  for (int iA = 0; iA < NVMD; ++iA)
1261  for (int iB = 0; iB < NVMD; ++iB){
1262 
1263  // Mass thresholds depend on VMD state.
1264  mMinXB = mAtmp[iA] + mMin0;
1265  mResXB = mAtmp[iA] + mRes0;
1266  sResXB = pow2(mResXB);
1267  mMinAX = mBtmp[iB] + mMin0;
1268  mResAX = mBtmp[iB] + mRes0;
1269  sResAX = pow2(mResAX);
1270 
1271  // Calculate and sum differential AB -> XB cross section value.
1272  if (isXB && mX > mMinXB && pow2(mX + mMinAX) < s) {
1273  double bBNow = BHAD[iHadBtmp[iB]];
1274  double bXBNow = 2. * bBNow + alP2 * log(1. / xi) ;
1275  sigNow += multVV[iA][iB] * CONVERTSD * X[iProcVV[iA][iB]]
1276  * BETA0[iHadBtmp[iB]] * exp(bXBNow * t) * (1. - xi)
1277  * ( 1. + cRes * sResXB / (sResXB + m2X) );
1278 
1279  // Calculate and sum differential AB -> AX cross section value.
1280  } else if (!isXB && mX > mMinAX && pow2(mX + mMinXB) < s) {
1281  double bANow = BHAD[iHadAtmp[iA]];
1282  double bAXNow = 2. * bANow + alP2 * log(1. / xi) ;
1283  sigNow += multVV[iA][iB] * CONVERTSD * X[iProcVV[iA][iB]]
1284  * BETA0[iHadAtmp[iA]] * exp(bAXNow * t) * (1. - xi)
1285  * ( 1. + cRes * sResAX / (sResAX + m2X) );
1286  }
1287  }
1288  return sigNow * epsWt;
1289 
1290  // No diffractive scattering for Pomeron + p.
1291  } else return 0.;
1292 
1293 }
1294 
1295 //--------------------------------------------------------------------------
1296 
1297 // Differential double diffractive cross section.
1298 
1299 double SigmaSaSDL::dsigmaDD(double xi1, double xi2, double t, int ) {
1300 
1301  // Calculate masses and check that they are above threshold. Optional weight.
1302  double m2X1 = xi1 * s;
1303  double mX1 = sqrt(m2X1);
1304  double m2X2 = xi2 * s;
1305  double mX2 = sqrt(m2X2);
1306  double epsWt = pow( m2X1 * m2X2, -epsSaS);
1307 
1308  // Ordinary hadron-hadron collisions.
1309  if (iProc < 13) {
1310  if (mX1 < mMinXB || mX2 < mMinAX) return 0.;
1311 
1312  // Return differential AB -> X1X2 cross section value.
1313  double bXX = alP2 * log( exp(4.) + s * s0 / (m2X1 * m2X2) );
1314  return CONVERTDD * BETA0[iHadA] * BETA0[iHadB] * exp(bXX * t)
1315  * (1. - pow2(mX1 + mX2) / s)
1316  * (s * SPROTON / (s * SPROTON + m2X1 * m2X2))
1317  * ( 1. + cRes * sResXB / (sResXB + m2X1) )
1318  * ( 1. + cRes * sResAX / (sResAX + m2X2) ) * epsWt;
1319 
1320  // gamma + p: loop over VMD states on side A.
1321  } else if (iProc == 13){
1322  double sigNow = 0.;
1323  for (int iA = 0; iA < NVMD; ++iA){
1324 
1325  // Mass thresholds depend on VMD state.
1326  mMinXB = mAtmp[iA] + mMin0;
1327  mResXB = mAtmp[iA] + mRes0;
1328  sResXB = pow2(mResXB);
1329  mMinAX = mBtmp[iA] + mMin0;
1330  mResAX = mBtmp[iA] + mRes0;
1331  sResAX = pow2(mResAX);
1332 
1333  // Calculate and sum differential AB -> X1X2 cross section value.
1334  if (mX1 > mMinXB && mX2 > mMinAX) {
1335  double bXX = alP2 * log( exp(4.) + s * s0 / (m2X1 * m2X2) );
1336  sigNow += multVP[iA] * CONVERTDD * BETA0[iHadAtmp[iA]]
1337  * BETA0[iHadBtmp[iA]] * exp(bXX * t)
1338  * (1. - pow2(mX1 + mX2) / s)
1339  * (s * SPROTON / (s * SPROTON + m2X1 * m2X2))
1340  * ( 1. + cRes * sResXB / (sResXB + m2X1) )
1341  * ( 1. + cRes * sResAX / (sResAX + m2X2) );
1342  }
1343  }
1344  return sigNow * epsWt;
1345 
1346  // gamma + gamma: loop over VMD states on side A and B.
1347  } else if (iProc == 14){
1348  double sigNow = 0.;
1349  for (int iA = 0; iA < NVMD; ++iA)
1350  for (int iB = 0; iB < NVMD; ++iB){
1351 
1352  // Mass thresholds depend on VMD state.
1353  mMinXB = mAtmp[iA] + mMin0;
1354  mResXB = mAtmp[iA] + mRes0;
1355  sResXB = pow2(mResXB);
1356  mMinAX = mBtmp[iB] + mMin0;
1357  mResAX = mBtmp[iB] + mRes0;
1358  sResAX = pow2(mResAX);
1359 
1360  // Calculate and sum differential AB -> X1X2 cross section value.
1361  if (mX1 > mMinXB && mX2 > mMinAX) {
1362  double bXX = alP2 * log( exp(4.) + s * s0 / (m2X1 * m2X2) );
1363  sigNow += multVV[iA][iB] * CONVERTDD * BETA0[iHadAtmp[iA]]
1364  * BETA0[iHadBtmp[iB]] * exp(bXX * t)
1365  * (1. - pow2(mX1 + mX2) / s)
1366  * (s * SPROTON / (s * SPROTON + m2X1 * m2X2))
1367  * ( 1. + cRes * sResXB / (sResXB + m2X1) )
1368  * ( 1. + cRes * sResAX / (sResAX + m2X2) );
1369  }
1370  }
1371  return sigNow * epsWt;
1372 
1373  // No diffractive scattering for Pomeron + p.
1374  } else return 0.;
1375 
1376 }
1377 
1378 //--------------------------------------------------------------------------
1379 
1380 // Differential central diffractive cross sections.
1381 // Simple extension of single diffraction, but without normalization.
1382 
1383 double SigmaSaSDL::dsigmaCD( double xi1, double xi2, double t1, double t2,
1384  int ) {
1385 
1386  // Ordinary hadron-hadron collisions.
1387  if (iProc < 13) {
1388 
1389  // Calculate mass; checked to be above threshold.
1390  double m2X = xi1 * xi2 * s;
1391  double mX = sqrt(m2X);
1392  if (mX < mMinCDnow || pow2(mX + mA + mB) > s) return 0.;
1393  wtNow = 1.;
1394 
1395  // Weight associated with differential AB -> AX cross section.
1396  double bAX = 2. * bA + alP2 * log(1. / xi1) ;
1397  wtNow *= CONVERTSD * X[iProc] * BETA0[iHadA] * exp(bAX * t1)
1398  * (1. - xi1);
1399 
1400  // Weight associated with differential AB -> XB cross section.
1401  double bXB = 2. * bB + alP2 * log(1. / xi2) ;
1402  wtNow *= CONVERTSD * X[iProc] * BETA0[iHadB] * exp(bXB * t2)
1403  * (1. - xi2);
1404 
1405  // Optional weight to tilt the mass spectrum.
1406  wtNow *= pow( m2X, -epsSaS);
1407 
1408  // Done.
1409  return wtNow;
1410 
1411  // No central diffraction for gamma + p, gamma + gamma or Pomeron + p.
1412  } else return 0.;
1413 
1414 }
1415 
1416 //--------------------------------------------------------------------------
1417 
1418 // Find beam combination.
1419 
1420 bool SigmaSaSDL::findBeamComb( int idAin, int idBin, double mAin,
1421  double mBin) {
1422 
1423  // Order flavour of incoming hadrons: idAbsA < idAbsB (restore later).
1424  idAbsA = abs(idAin);
1425  idAbsB = abs(idBin);
1426  mA = mAin;
1427  mB = mBin;
1428  swapped = false;
1429  if (idAbsA > idAbsB) {
1430  swap( idAbsA, idAbsB);
1431  swap( mA, mB);
1432  swapped = true;
1433  }
1434  sameSign = (idAin * idBin > 0);
1435 
1436  // Find process number.
1437  iProc = -1;
1438  if (idAbsA > 1000) {
1439  iProc = (sameSign) ? 0 : 1;
1440  } else if (idAbsA > 100 && idAbsB > 1000) {
1441  iProc = (sameSign) ? 2 : 3;
1442  if (idAbsA/10 == 11 || idAbsA/10 == 22) iProc = 4;
1443  if (idAbsA > 300) iProc = 5;
1444  if (idAbsA > 400) iProc = 6;
1445  if (idAbsA > 900) iProc = 15;
1446  } else if (idAbsA > 100) {
1447  iProc = 7;
1448  if (idAbsB > 300) iProc = 8;
1449  if (idAbsB > 400) iProc = 9;
1450  if (idAbsA > 300) iProc = 10;
1451  if (idAbsA > 300 && idAbsB > 400) iProc = 11;
1452  if (idAbsA > 400) iProc = 12;
1453  } else if (idAbsA == 22 || idAbsB == 22) {
1454  if (idAbsA == idAbsB) iProc = 14;
1455  if (idAbsB > 1000) iProc = 13;
1456  }
1457  if (iProc == -1) return false;
1458 
1459  // Set up global variables.
1460  if (iProc < 13) {
1461  iHadA = IHADATABLE[iProc];
1462  iHadB = IHADBTABLE[iProc];
1463  bA = BHAD[iHadA];
1464  bB = BHAD[iHadB];
1465 
1466  // Set up VMD global variables for gamma + p.
1467  } else if (iProc == 13){
1468  for (int i = 0; i < NVMD; ++i){
1469  // VMD always on side a
1470  mAtmp[i] = VMDMASS[i];
1471  mBtmp[i] = mB;
1472  iHadAtmp[i] = (i < 2) ? 1 : i;
1473  iHadBtmp[i] = 0;
1474  multVP[i] = ALPHAEM / GAMMAFAC[i];
1475  if (i < 2) iProcVP[i] = 4;
1476  else if (i == 2) iProcVP[i] = 5;
1477  else if (i == 3) iProcVP[i] = 6;
1478  }
1479 
1480  // Set up VMD global variables for gamma + gamma.
1481  } else if (iProc == 14){
1482  for (int i = 0; i < NVMD; ++i){
1483  mAtmp[i] = VMDMASS[i];
1484  mBtmp[i] = VMDMASS[i];
1485  iHadAtmp[i] = (i < 2) ? 1 : i;
1486  iHadBtmp[i] = (i < 2) ? 1 : i;
1487  for (int j = 0; j < NVMD; ++j){
1488  multVV[i][j] = pow2(ALPHAEM) / (GAMMAFAC[i] * GAMMAFAC[j]);
1489  if ( i < 2 ) {
1490  if ( j < 2) iProcVV[i][j] = 7;
1491  else if ( j == 2) iProcVV[i][j] = 8;
1492  else if ( j == 3) iProcVV[i][j] = 9;
1493  } else if (i == 2) {
1494  if ( j < 2) iProcVV[i][j] = 8;
1495  else if ( j == 2) iProcVV[i][j] = 10;
1496  else if ( j == 3) iProcVV[i][j] = 11;
1497  } else if ( i == 3) {
1498  if ( j < 2) iProcVV[i][j] = 9;
1499  else if ( j == 2) iProcVV[i][j] = 11;
1500  else if ( j == 3) iProcVV[i][j] = 12;
1501  }
1502  }
1503  }
1504  }
1505 
1506  // Done.
1507  return true ;
1508 
1509 }
1510 
1511 //==========================================================================
1512 
1513 // The SigmaMBR class.
1514 // It parametrizes pp/ppbar total, elastic and diffractive cross sections
1515 // according to the Minimum Bias Rockefeller (MBR) model.
1516 
1517 // Integration of MBR cross sections.
1518 const int SigmaMBR::NINTEG = 1000;
1519 const int SigmaMBR::NINTEG2 = 40;
1520 
1521 // Proton form factor appoximation with two exponents, [FFB1,FFB2] = GeV^-2.
1522 // Used for quick t-integration, while full expression used for t selection.
1523 const double SigmaMBR::FFA1 = 0.9;
1524 const double SigmaMBR::FFA2 = 0.1;
1525 const double SigmaMBR::FFB1 = 4.6;
1526 const double SigmaMBR::FFB2 = 0.6;
1527 
1528 //--------------------------------------------------------------------------
1529 
1530 // Initialize data members.
1531 
1532 void SigmaMBR::init(Info* infoPtrIn) {
1533 
1534  // Use shorthand for settings
1535  Settings& settings = *infoPtrIn->settingsPtr;
1536 
1537 
1538  // Parameters for MBR model.
1539  eps = settings.parm("SigmaDiffractive:MBRepsilon");
1540  alph = settings.parm("SigmaDiffractive:MBRalpha");
1541  beta0gev = settings.parm("SigmaDiffractive:MBRbeta0");
1542  beta0mb = beta0gev * sqrt(HBARCSQ);
1543  sigma0mb = settings.parm("SigmaDiffractive:MBRsigma0");
1544  sigma0gev = sigma0mb/HBARCSQ;
1545  m2min = settings.parm("SigmaDiffractive:MBRm2Min");
1546  dyminSDflux = settings.parm("SigmaDiffractive:MBRdyminSDflux");
1547  dyminDDflux = settings.parm("SigmaDiffractive:MBRdyminDDflux");
1548  dyminCDflux = settings.parm("SigmaDiffractive:MBRdyminCDflux");
1549  dyminSD = settings.parm("SigmaDiffractive:MBRdyminSD");
1550  dyminDD = settings.parm("SigmaDiffractive:MBRdyminDD");
1551  dyminCD = settings.parm("SigmaDiffractive:MBRdyminCD") / 2.;
1552  dyminSigSD = settings.parm("SigmaDiffractive:MBRdyminSigSD");
1553  dyminSigDD = settings.parm("SigmaDiffractive:MBRdyminSigDD");
1554  dyminSigCD = settings.parm("SigmaDiffractive:MBRdyminSigCD") / sqrt(2.);
1555  a1 = FFA1;
1556  a2 = FFA2;
1557  b1 = FFB1;
1558  b2 = FFB2;
1559 
1560  // Initialize parameters for Coulomb corrections to elastic scattering.
1561  initCoulomb( settings, infoPtrIn->particleDataPtr);
1562 
1563  // No rho parameter implemented.
1564  rhoOwn = 0.;
1565 
1566 }
1567 
1568 //--------------------------------------------------------------------------
1569 
1570 // Total and elastic cross section.
1571 
1572 bool SigmaMBR::calcTotEl( int idAin, int idBin, double sIn, double , double) {
1573 
1574  // Save some input.
1575  idA = idAin;
1576  idB = idBin;
1577  s = sIn;
1578  isExpEl = true;
1579 
1580  // Total cross section and elastic/total parametrizations.
1581  double sCDF = pow2(1800.);
1582  double ratio = 0.;
1583  if (s <= sCDF) {
1584  double sign = (idA * idB > 0) ? 1. : -1.;
1585  sigTot = 16.79 * pow(s, 0.104) + 60.81 * pow(s, -0.32)
1586  - sign * 31.68 * pow(s, -0.54);
1587  ratio = 0.100 * pow(s, 0.06) + 0.421 * pow(s, -0.52)
1588  + sign * 0.160 * pow(s, -0.6);
1589  } else {
1590  double sigCDF = 80.03;
1591  double sF = pow2(22.);
1592  sigTot = sigCDF + ( pow2( log(s / sF)) - pow2( log(sCDF / sF)) )
1593  * M_PI / (3.7 / HBARCSQ);
1594  ratio = 0.066 + 0.0119 * log(s);
1595  }
1596  sigEl = sigTot * ratio;
1597  bEl = CONVERTEL * pow2(sigTot) / sigEl;
1598 
1599  // Possibly add Coulomb correction and interference.
1600  addCoulomb();
1601 
1602  // Done.
1603  return true ;
1604 
1605 }
1606 
1607 //--------------------------------------------------------------------------
1608 
1609 // Differential elastic cross section.
1610 
1611 double SigmaMBR::dsigmaEl( double t, bool useCoulomb, bool ) {
1612 
1613  // Hadronic contribution: simple exponential.
1614  double dsig = sigEl * bEl * exp(bEl * t);
1615 
1616  // Possibly add Coulomb contribution and interference.
1617  if (useCoulomb && hasCou) dsig += dsigmaElCoulomb(t);
1618 
1619  // Done.
1620  return dsig;
1621 
1622 }
1623 
1624 //--------------------------------------------------------------------------
1625 
1626 // Total diffractive cross sections, obtained from the ratio of
1627 // two integrals: the Regge cross section and the renormalized flux.
1628 
1629 bool SigmaMBR::calcDiff( int , int , double sIn, double , double ) {
1630 
1631  // Common variables,
1632  s = sIn;
1633  double cflux, csig, c1, step, f;
1634  double dymin0 = 0.;
1635 
1636  // Calculate SD cross section.
1637  double dymaxSD = log(s / m2min);
1638  cflux = pow2(beta0gev) / (16. * M_PI);
1639  csig = cflux * sigma0mb;
1640 
1641  // SD flux.
1642  c1 = cflux;
1643  double fluxsd = 0.;
1644  step = (dymaxSD - dyminSDflux) / NINTEG;
1645  for (int i = 0; i < NINTEG; ++i) {
1646  double dy = dyminSDflux + (i + 0.5) * step;
1647  f = exp(2. * eps * dy) * ( (a1 / (b1 + 2. * alph * dy))
1648  + (a2 / (b2 + 2. * alph * dy)) );
1649  f *= 0.5 * (1. + erf( (dy - dyminSD) / dyminSigSD));
1650  fluxsd = fluxsd + step * c1 * f;
1651  }
1652  if (fluxsd < 1.) fluxsd = 1.;
1653 
1654  // Regge SD cross section.
1655  c1 = csig * pow(s, eps);
1656  sigSD = 0.;
1657  sdpmax = 0.;
1658  step = (dymaxSD - dymin0) / NINTEG;
1659  for (int i = 0; i < NINTEG; ++i) {
1660  double dy = dymin0 + (i + 0.5) * step;
1661  f = exp(eps * dy) * ( (a1 / (b1 + 2. * alph * dy))
1662  + (a2 / (b2 + 2. * alph * dy)) );
1663  f *= 0.5 * (1. + erf( (dy - dyminSD) / dyminSigSD));
1664  if (f > sdpmax) sdpmax = f;
1665  sigSD = sigSD + step * c1 * f;
1666  }
1667  sdpmax *= 1.01;
1668  sigSD /= fluxsd;
1669 
1670  // Calculate DD cross section.
1671  // Note: dymaxDD = ln(s * s0 /mMin^4) with s0 = 1 GeV^2.
1672  double dymaxDD = log(s / pow2(m2min));
1673  cflux = sigma0gev / (16. * M_PI);
1674  csig = cflux * sigma0mb;
1675 
1676  // DD flux.
1677  c1 = cflux / (2. * alph);
1678  double fluxdd = 0.;
1679  step = (dymaxDD - dyminDDflux) / NINTEG;
1680  for (int i = 0; i < NINTEG; ++i) {
1681  double dy = dyminDDflux + (i + 0.5) * step;
1682  f = (dymaxDD - dy) * exp(2. * eps * dy)
1683  * ( exp(-2. * alph * dy * exp(-dy))
1684  - exp(-2. * alph * dy * exp(dy)) ) / dy;
1685  f *= 0.5 * (1. + erf( (dy - dyminDD) / dyminSigDD));
1686  fluxdd = fluxdd + step * c1 * f;
1687  }
1688  if (fluxdd < 1.) fluxdd = 1.;
1689 
1690  // Regge DD cross section.
1691  c1 = csig * pow(s, eps) / (2. * alph);
1692  ddpmax = 0.;
1693  sigDD = 0.;
1694  step = (dymaxDD - dymin0) / NINTEG;
1695  for (int i = 0; i < NINTEG; ++i) {
1696  double dy = dymin0 + (i + 0.5) * step;
1697  f = (dymaxDD - dy) * exp(eps * dy)
1698  * ( exp(-2. * alph * dy * exp(-dy))
1699  - exp(-2. * alph * dy * exp(dy)) ) / dy;
1700  f *= 0.5 * (1. + erf( (dy - dyminDD) / dyminSigDD));
1701  if (f > ddpmax) ddpmax = f;
1702  sigDD = sigDD + step * c1 * f;
1703  }
1704  ddpmax *= 1.01;
1705  sigDD /= fluxdd;
1706 
1707  // Calculate DPE (CD) cross section.
1708  double dymaxCD = log(s / m2min);
1709  cflux = pow4(beta0gev) / pow2(16. * M_PI);
1710  csig = cflux * pow2(sigma0mb / beta0mb);
1711  double dy1, dy2, f1, f2, step2;
1712 
1713  // DPE flux.
1714  c1 = cflux;
1715  double fluxdpe = 0.;
1716  step = (dymaxCD - dyminCDflux) / NINTEG;
1717  for (int i = 0; i < NINTEG; ++i) {
1718  double dy = dyminCDflux + (i + 0.5) * step;
1719  f = 0.;
1720  step2 = (dy - dyminCDflux) / NINTEG2;
1721  for (int j = 0; j < NINTEG2; ++j) {
1722  double yc = -0.5 * (dy - dyminCDflux) + (j + 0.5) * step2;
1723  dy1 = 0.5 * dy - yc;
1724  dy2 = 0.5 * dy + yc;
1725  f1 = exp(2. * eps * dy1) * ( (a1 / (b1 + 2. * alph * dy1))
1726  + (a2 / (b2 + 2. * alph * dy1)) );
1727  f2 = exp(2. * eps * dy2) * ( (a1 / (b1 + 2. * alph * dy2))
1728  + (a2 / (b2 + 2. * alph * dy2)) );
1729  f1 *= 0.5 * (1. + erf( (dy1 - dyminCD) / dyminSigCD) );
1730  f2 *= 0.5 * (1. + erf( (dy2 - dyminCD) / dyminSigCD) );
1731  f += f1 * f2 * step2;
1732  }
1733  fluxdpe += step * c1 * f;
1734  }
1735  if (fluxdpe < 1.) fluxdpe = 1.;
1736 
1737  // Regge DPE (CD) cross section.
1738  c1 = csig * pow(s, eps);
1739  sigCD = 0.;
1740  dpepmax = 0;
1741  step = (dymaxCD - dymin0) / NINTEG;
1742  for (int i = 0; i < NINTEG; ++i) {
1743  double dy = dymin0 + (i + 0.5) * step;
1744  f = 0.;
1745  step2 = (dy - dymin0) / NINTEG2;
1746  for (int j = 0; j < NINTEG2; ++j) {
1747  double yc = -0.5 * (dy - dymin0) + (j + 0.5) * step2;
1748  dy1 = 0.5 * dy - yc;
1749  dy2 = 0.5 * dy + yc;
1750  f1 = exp(eps * dy1) * ( (a1 / (b1 + 2. * alph * dy1))
1751  + (a2 / (b2 + 2. * alph * dy1)) );
1752  f2 = exp(eps * dy2) * ( (a1 / (b1 + 2. * alph * dy2))
1753  + (a2 / (b2 + 2. * alph * dy2)) );
1754  f1 *= 0.5 * (1. + erf( (dy1 - dyminCD) / dyminSigCD) );
1755  f2 *= 0.5 * (1. + erf( (dy2 - dyminCD) / dyminSigCD) );
1756  f += f1 * f2 * step2;
1757  }
1758  sigCD += step * c1 * f;
1759  if ( f > dpepmax) dpepmax = f;
1760  }
1761  dpepmax *= 1.01;
1762  sigCD /= fluxdpe;
1763 
1764  // Output to standard names. Done.
1765  sigXB = sigSD;
1766  sigAX = sigSD;
1767  sigXX = sigDD;
1768  sigAXB = sigCD;
1769  return true;
1770 
1771 }
1772 
1773 //--------------------------------------------------------------------------
1774 
1775 // Differential single diffractive cross sections, separated in xi and t steps.
1776 
1777 double SigmaMBR::dsigmaSD(double xi, double t, bool , int step) {
1778 
1779  // Rapidity gap size.
1780  double dy = -log(xi);
1781 
1782  // Step 1: evaluate cross section in xi, integrated over t.
1783  if (step == 1) {
1784  if (xi * s < m2min) return 0.;
1785  return exp(eps * dy)
1786  * ( (a1 / (b1 + 2. * alph * dy)) + (a2 / (b2 + 2. * alph * dy)) )
1787  * 0.5 * (1. + erf( (dy - dyminSD) / dyminSigSD));
1788 
1789  // Step 2: evaluate cross section in t for fixed xi.
1790  } else if (step == 2) {
1791  return pow2(pFormFac(t)) * exp(2. * alph * dy * t);
1792  }
1793 
1794  // Done.
1795  return 0.;
1796 
1797 }
1798 
1799 //--------------------------------------------------------------------------
1800 
1801 // Differential double diffractive cross sections, separated in xi and t steps.
1802 
1803 double SigmaMBR::dsigmaDD(double xi1, double xi2, double t, int step) {
1804 
1805  // Rapidity gap size (with implicit scale s_0 = 1 GeV).
1806  double dy = - log(xi1 * xi2 * s);
1807 
1808  // Step 1: evaluate cross section in xi1 and xi2, integrated over t.
1809  if (step == 1) {
1810  if (xi1 * s < m2min || xi2 * s < m2min || dy < 0.) return 0.;
1811  return exp(eps * dy) * ( exp(-2. * alph * dy * exp(-dy))
1812  - exp(-2. * alph * dy * exp(dy)) ) / dy
1813  * 0.5 * (1. + erf( (dy - dyminDD) / dyminSigDD));
1814 
1815  // Step 2: evaluate cross section in t for fixed xi1 and xi2.
1816  } else if (step == 2) {
1817  if ( t < -exp(dy) || t > -exp(-dy) ) return 0.;
1818  return exp(2. * alph * dy * t);
1819  }
1820 
1821  // Done.
1822  return 0.;
1823 
1824 }
1825 
1826 //--------------------------------------------------------------------------
1827 
1828 // Differential central diffractive cross section, separated in xi and t steps.
1829 
1830 double SigmaMBR::dsigmaCD(double xi1, double xi2, double t1, double t2,
1831  int step) {
1832 
1833  // Rapidity gap sizes.
1834  double dy1 = -log(xi1);
1835  double dy2 = -log(xi2);
1836 
1837  // Step 1: evaluate cross section in xi1 and xi2, integrated over t1 and t2.
1838  if (step == 1) {
1839  if (xi1 * xi2 * s < m2min) return 0.;
1840  double wt1 = exp(eps * dy1)
1841  * ( (a1 / (b1 + 2. * alph * dy1)) + (a2 / (b2 + 2. * alph * dy1)) )
1842  * 0.5 * (1. + erf( (dy1 - dyminCD) / dyminSigCD));
1843  double wt2 = exp(eps * dy2)
1844  * ( (a1 / (b1 + 2. * alph * dy2)) + (a2 / (b2 + 2. * alph * dy2)) )
1845  * 0.5 * (1. + erf( (dy2 - dyminCD) / dyminSigCD));
1846  return wt1 * wt2;
1847 
1848  // Step 2: evaluate cross section in t1 and t2 for fixed xi1 and xi2.
1849  } else if (step == 2) {
1850  return pow2(pFormFac(t1) * pFormFac(t2))
1851  * exp(2. * alph * (dy1 * t1 + dy2 * t2));
1852  }
1853 
1854  // Done.
1855  return 0.;
1856 
1857 }
1858 
1859 //==========================================================================
1860 
1861 // The SigmaABMST class.
1862 // It parametrizes pp/ppbar total, elastic and diffractive cross sections
1863 // according to Appleby, Barlow, Molson, Serluca and Toader (ABMST).
1864 
1865 //--------------------------------------------------------------------------
1866 
1867 // Definitions of static variables.
1868 
1869 // Parameters of parametrization: total and elastic cross sections.
1870 const double SigmaABMST::EPSI[] = {0.106231, 0.0972043, -0.510662, -0.302082};
1871 const double SigmaABMST::ALPP[] = { 0.0449029, 0.278037, 0.821595, 0.904556};
1872 const double SigmaABMST::NORM[] = { 228.359, 193.811, 518.686, 10.7843};
1873 const double SigmaABMST::SLOPE[] = { 8.38, 3.78, 1.36};
1874 const double SigmaABMST::FRACS[] = { 0.26, 0.56, 0.18};
1875 const double SigmaABMST::TRIG[] = { 0.3, 5.03};
1876 const double SigmaABMST::LAM2P = 0.521223;
1877 const double SigmaABMST::BAPPR[] = { 8.5, 1.086};
1878 const double SigmaABMST::LAM2FF = 0.71;
1879 
1880 // Parameters of parametrization: diffractive cross section.
1881 const double SigmaABMST::MRES[4] = {1.44, 1.52, 1.68, 2.19};
1882 const double SigmaABMST::WRES[4] = {0.325, 0.13, 0.14, 0.45};
1883 const double SigmaABMST::CRES[4] = {3.07, 0.4149, 1.108, 0.9515};
1884 const double SigmaABMST::AFAC[4] = {0.624529, 3.09088, 4.0, 177.217};
1885 const double SigmaABMST::BFAC[4] = {2.5835, 4.51487, 3.03392, 5.86474};
1886 const double SigmaABMST::CFAC[4] = {0., 0.186211, 10.0, 21.0029};
1887 const double SigmaABMST::PPP[4] = {0.4, 0.5, 0.4597, 5.7575};
1888 const double SigmaABMST::EPS[2] = {0.08, -0.4525};
1889 const double SigmaABMST::APR[2] = {0.25, 0.93};
1890 const double SigmaABMST::CPI[6] = {13.63, 0.0808, 31.79, -0.4525, 0.93, 14.4};
1891 const double SigmaABMST::CNST[5] = {1., -0.05, -0.25, -1.15, 13.5};
1892 
1893 // Parameters for integration over t and xi for SD, DD and CD.
1894 const int SigmaABMST::NPOINTSTSD = 200;
1895 const double SigmaABMST::XIDIVSD = 0.1;
1896 const double SigmaABMST::DXIRAWSD = 0.01;
1897 const double SigmaABMST::DLNXIRAWSD = 0.1;
1898 // For DD either Monte Carlo integration or (slower) grid one.
1899 const bool SigmaABMST::MCINTDD = true;
1900 const int SigmaABMST::NPOINTSTDD = 20;
1901 const double SigmaABMST::XIDIVDD = 0.1;
1902 const double SigmaABMST::DXIRAWDD = 0.02;
1903 const double SigmaABMST::DLNXIRAWDD = 0.1;
1904 const double SigmaABMST::BMCINTDD = 2.;
1905 const int SigmaABMST::NPOINTMCDD = 200000;
1906 // For CD only Monte Carlo integration.
1907 const double SigmaABMST::BMCINTCD = 2.;
1908 const int SigmaABMST::NPOINTMCCD = 200000;
1909 
1910 //--------------------------------------------------------------------------
1911 
1912 // Initialize data members.
1913 
1914 void SigmaABMST::init(Info* infoPtrIn) {
1915 
1916  // Use shorthand for settings
1917  Settings& settings = *infoPtrIn->settingsPtr;
1918 
1919  // Save pointer.
1920  rndmPtr = infoPtrIn->rndmPtr;
1921 
1922  // Common setup.
1923  m2minp = pow2(MPROTON + MPION);
1924  m2minm = pow2(MPROTON - MPION);
1925 
1926  // Allow Couplomb corrections for elastic scattering.
1927  tryCoulomb = settings.flag("SigmaElastic:Coulomb");
1928  tAbsMin = settings.parm("SigmaElastic:tAbsMin");
1929 
1930  // Setup for single diffraction.
1931  modeSD = settings.mode("SigmaDiffractive:ABMSTmodeSD");
1932  multSD = settings.parm("SigmaDiffractive:ABMSTmultSD");
1933  powSD = settings.parm("SigmaDiffractive:ABMSTpowSD");
1934  s0 = (modeSD % 2 == 0) ? 4000. : 100.;
1935  c0 = (modeSD % 2 == 0) ? 0.6 : 0.012;
1936 
1937  // Setup for double diffraction.
1938  modeDD = settings.mode("SigmaDiffractive:ABMSTmodeDD");
1939  multDD = settings.parm("SigmaDiffractive:ABMSTmultDD");
1940  powDD = settings.parm("SigmaDiffractive:ABMSTpowDD");
1941 
1942  // Setup for central diffraction.
1943  modeCD = settings.mode("SigmaDiffractive:ABMSTmodeCD");
1944  multCD = settings.parm("SigmaDiffractive:ABMSTmultCD");
1945  powCD = settings.parm("SigmaDiffractive:ABMSTpowCD");
1946  mMinCDnow = settings.parm("SigmaDiffractive:ABMSTmMinCD");
1947 
1948  // Setup to dampen diffractive events with small rapidity gaps.
1949  dampenGap = settings.flag("SigmaDiffractive:ABMSTdampenGap");
1950  ygap = settings.parm("SigmaDiffractive:ABMSTygap");
1951  ypow = settings.parm("SigmaDiffractive:ABMSTypow");
1952  expPygap = exp(ypow * ygap);
1953 
1954  // Setup to force minimal t fall-off like exp(b_min * t).
1955  useBMin = settings.flag("SigmaDiffractive:ABMSTuseBMin");
1956  bMinSD = settings.parm("SigmaDiffractive:ABMSTbMinSD");
1957  bMinDD = settings.parm("SigmaDiffractive:ABMSTbMinDD");
1958  bMinCD = settings.parm("SigmaDiffractive:ABMSTbMinCD");
1959 
1960 }
1961 
1962 //--------------------------------------------------------------------------
1963 
1964 // Calculate total and (integrated) elastic cross sections.
1965 
1966 bool SigmaABMST::calcTotEl( int idAin, int idBin, double sIn, double ,
1967  double ) {
1968 
1969  // Find appropriate combination of incoming beams.
1970  idA = idAin;
1971  idB = idBin;
1972  ispp = (idA * idB > 0);
1973  s = sIn;
1974  facEl = HBARCSQ / (16. * M_PI);
1975  isExpEl = false;
1976 
1977  // Total cross section and the rho parameter using the full expression.
1978  complex amp = amplitude( 0., false, false);
1979  sigTot = HBARCSQ * imag(amp);
1980  rhoOwn = real(amp) / imag(amp);
1981 
1982  // Total elastic cross section, by integration in exp( MINSLOPEEL * t).
1983  sigEl = 0.;
1984  for (int i = 0; i < NPOINTS; ++i) {
1985  double y = (i + 0.5) / NPOINTS;
1986  double t = log(y) / MINSLOPEEL;
1987  sigEl += dsigmaEl( t, false) / y;
1988  }
1989  sigEl /= NPOINTS * MINSLOPEEL;
1990 
1991  // Approximate exponential slope.
1992  bEl = log( dsigmaEl( -TABSREF, false) / dsigmaEl( 0., false) ) / (-TABSREF);
1993 
1994  // Done if no Coulomb corrections.
1995  hasCou = tryCoulomb;
1996  if (abs(idAin) == 2112 || abs(idBin) == 2112) hasCou = false;
1997  sigTotCou = sigTot;
1998  sigElCou = sigEl;
1999  if (!hasCou) return true;
2000 
2001  // Reduce hadronic part of elastic cross section by tMin cut.
2002  sigElCou = sigEl * exp( - bEl * tAbsMin);
2003  if (tAbsMin < 0.9 * TABSMAX) {
2004 
2005  // Loop through t range according to dt/t^2.
2006  double sumCou = 0.;
2007  double xRel, tAbs;
2008  for (int i = 0; i < NPOINTS; ++i) {
2009  xRel = (i + 0.5) / NPOINTS;
2010  tAbs = tAbsMin * TABSMAX / (tAbsMin + xRel * (TABSMAX - tAbsMin));
2011 
2012  // Evaluate cross section difference between with and without Coulomb.
2013  sumCou += pow2(tAbs) * (dsigmaEl( -tAbs, true)
2014  - dsigmaEl( -tAbs, false));
2015  }
2016 
2017  // Include common factors to give new elastic and total cross sections.
2018  sigElCou += sumCou * (TABSMAX - tAbsMin)/ (tAbsMin * TABSMAX * NPOINTS);
2019  }
2020  sigTotCou = sigTot - sigEl + sigElCou;
2021 
2022  // Done.
2023  return true;
2024 
2025 }
2026 
2027 //--------------------------------------------------------------------------
2028 
2029 // The scattering amplitude, from which cross sections are derived.
2030 
2031 complex SigmaABMST::amplitude( double t, bool useCoulomb,
2032  bool onlyPomerons) {
2033 
2034  // Common values.
2035  double snu = s - 2. * SPROTON + 0.5 * t;
2036  double ampt = FRACS[0] * exp(SLOPE[0] * t) + FRACS[1] * exp(SLOPE[1] * t)
2037  + FRACS[2] * exp(SLOPE[2] * t);
2038  complex amp[6], l2p[4], ll2p[4], d2p[4][3];
2039 
2040  // Two Pomeron and even and odd Reggeon exchange.
2041  for (int i = 0; i < 4; ++i)
2042  amp[i] = ((i < 3) ? complex(-NORM[i], 0.) : complex( 0., NORM[i]))
2043  * ampt * sModAlp( ALPP[i] * snu, 1. + EPSI[i] + ALPP[i] * t);
2044 
2045  // Two-pomeron exchange.
2046  amp[4] = complex(0., 0.);
2047  for (int i = 0; i < 4; ++i) {
2048  l2p[i] = ALPP[i] * complex( log(ALPP[i] * snu), -0.5 * M_PI);
2049  ll2p[i] = (1. + EPSI[i]) * l2p[i] / ALPP[i];
2050  for (int k = 0; k < 3; ++k) d2p[i][k] = SLOPE[k] + l2p[i];
2051  }
2052  for (int i = 0; i < 4; ++i)
2053  for (int j = 0; j < 4; ++j)
2054  for (int k = 0; k < 3; ++k)
2055  for (int l = 0; l < 3; ++l) {
2056  complex part = NORM[i] * NORM[j] * exp( ll2p[i] + ll2p[j] )
2057  * exp( t * d2p[i][k] * d2p[j][l] / (d2p[i][k] + d2p[j][l]) )
2058  * FRACS[k] * FRACS[l] / (d2p[i][k] + d2p[j][l]);
2059  if (i == 3) part *= complex( 0., 1.);
2060  if (j == 3) part *= complex( 0., 1.);
2061  amp[4] += part;
2062  }
2063  amp[4] *= LAM2P * complex( 0., 1.) / (16. * M_PI * snu);
2064 
2065  // Triple-gluon exchange.
2066  amp[5] = sqrt(16. * M_PI / HBARCSQ) * TRIG[0] * ((t < -TRIG[1])
2067  ? 1. / pow4(t) : exp(4. + 4. * t / TRIG[1]) / pow4(TRIG[1]));
2068 
2069  // Add up contributions.
2070  complex ampSum = 0.;
2071  if (onlyPomerons) ampSum = (amp[0] + amp[1]) / snu;
2072  else ampSum = (amp[0] + amp[1] + amp[2] + ((ispp) ? -amp[3] : amp[3])
2073  + amp[4]) / snu + ((ispp) ? amp[5] : -amp[5]);
2074 
2075  // Optional Coulomb term. Must not be used for t = 0.
2076  if (useCoulomb && t < 0.) {
2077  double bApp = BAPPR[0] + BAPPR[1] * 0.5 * log(s);
2078  double phase = (GAMMAEUL + log( -0.5 * t * (bApp + 8. / LAM2FF)) +
2079  - 4. * t / LAM2FF * log(- 4. * t / LAM2FF)
2080  - 2. * t / LAM2FF) * (ispp ? 1. : -1.);
2081  complex ampCou = exp( complex( 0., -ALPHAEM * phase) ) * 8. * M_PI
2082  * ALPHAEM * ampt / t;
2083  ampSum += (ispp) ? ampCou : -ampCou;
2084  }
2085 
2086  // Done.
2087  return ampSum;
2088 
2089 }
2090 
2091 //--------------------------------------------------------------------------
2092 
2093 // Diffractive cross sections.
2094 
2095 bool SigmaABMST::calcDiff( int idAin , int idBin, double sIn, double ,
2096  double ) {
2097 
2098  // Find appropriate combination of incoming beams.
2099  idA = idAin;
2100  idB = idBin;
2101  ispp = (idA * idB > 0);
2102  s = sIn;
2103  facEl = HBARCSQ / (16. * M_PI);
2104 
2105  // Total cross section needed for central diffraction.
2106  complex amp = amplitude( 0., false, true);
2107  sigTot = HBARCSQ * imag(amp);
2108 
2109  // Single diffractive cross sections by grid integration.
2110  sigXB = dsigmaSDintXiT( 0., 1., -100., 0.);
2111  sigAX = sigXB;
2112 
2113  // Double diffractive cross section by Monte Carlo or grid integration.
2114  if (MCINTDD) sigXX = dsigmaDDintMC();
2115  else sigXX = dsigmaDDintXi1Xi2T( 0., 1., 0., 1., -100., 0.);
2116 
2117  // Central diffractive cross section by Monte Carlo integration.
2118  sigAXB = dsigmaCDintMC();
2119 
2120  // Done.
2121  return true;
2122 
2123 }
2124 
2125 //--------------------------------------------------------------------------
2126 
2127 // Variations on differential SD cross sections xi * dsigma / dxi dt.
2128 
2129 double SigmaABMST::dsigmaSD(double xi, double t, bool, int) {
2130 
2131  // Calculate core SD cross section.
2132  double dSigSD = dsigmaSDcore( xi, t);
2133 
2134  // Optionally require falloff at least like exp(bMin * t);
2135  if (useBMin && bMinSD > 0.) {
2136  double dSigSDmx = dsigmaSDcore( xi, -SPION) * exp(bMinSD * t);
2137  if (dSigSD > dSigSDmx) dSigSD = dSigSDmx;
2138  }
2139 
2140  // Optionally dampen with 1 / (1 + exp( -p * (y - y_gap))).
2141  if (dampenGap) dSigSD /= 1. + expPygap * pow( xi, ypow);
2142 
2143  // Optionally multiply by s-dependent factor.
2144  if (modeSD > 1) dSigSD *= multSD * pow( s / SPROTON, powSD);
2145 
2146  // Done.
2147  return dSigSD;
2148 
2149 }
2150 
2151 //--------------------------------------------------------------------------
2152 
2153 // Core differential single diffractive cross sections xi * dsigma / dxi dt.
2154 
2155 double SigmaABMST::dsigmaSDcore(double xi, double t) {
2156 
2157  // Calculate mass and check it is above threshold. ABMST valid for |t| < 4.
2158  double m2X = xi * s;
2159  if (m2X < m2minp) return 0.;
2160  double tAbs = abs(t);
2161  if (modeSD % 2 == 0 && tAbs > 4.) return 0.;
2162 
2163  // Some basic parameters.
2164  double tmp = 3. + c0 * pow2( log( s / s0) );
2165  double scaleFac = (s < s0) ? 1. : 3. / tmp;
2166  double mCut = (s < s0) ? 3 : tmp;
2167  if (modeSD % 2 == 0) {
2168  scaleFac = 1.;
2169  mCut = (s < s0) ? 3. : 3. + c0 * log(s/s0);
2170  }
2171  double m2Cut = pow2(mCut);
2172  double xiCut = m2Cut / s;
2173  double xiThr = m2minp / s;
2174  bool isHighM = (m2X > m2Cut);
2175  double xiNow = (isHighM) ? xi : xiCut;
2176  double m2XNow = xiNow * s;
2177 
2178  // Trajectories.
2179  for (int i = 0; i < 2; ++i) {
2180  alp0[i] = 1. + EPS[i];
2181  alpt[i] = alp0[i] + APR[i] * t;
2182  }
2183  alpt[2] = CPI[4] * (t - SPION);
2184 
2185  // Individual amplitudes: PPP remains unmodified.
2186  double ampPPP = pow(xiNow, alp0[0] - 2. * alpt[0]) * pow(s/CNST[0], EPS[0]);
2187  if (t > CNST[2]) ampPPP *= (PPP[0] + PPP[1] * t);
2188  else ampPPP *= (AFAC[0] * exp(BFAC[0] * t) + CFAC[0]) * t / (t + CNST[1]);
2189  if (t < CNST[3]) ampPPP *= (1. + PPP[2] * (tAbs + CNST[3])
2190  + PPP[3] * pow2(tAbs + CNST[3]));
2191  double ampPPR = pow(xiNow, alp0[1] - 2. * alpt[0]) * pow(s/CNST[0], EPS[1]);
2192  double ampRRP = pow(xiNow, alp0[0] - 2. * alpt[1]) * pow(s/CNST[0], EPS[0]);
2193  double ampRRR = pow(xiNow, alp0[1] - 2. * alpt[1]) * pow(s/CNST[0], EPS[1]);
2194 
2195  // ABMST uses exponential slope plus constant term in t.
2196  if (modeSD % 2 == 0) {
2197  ampPPR *= (AFAC[1] * exp(BFAC[1] * t) + CFAC[1]);
2198  ampRRP *= (AFAC[2] * exp(BFAC[2] * t) + CFAC[2]);
2199  ampRRR *= (AFAC[3] * exp(BFAC[3] * t) + CFAC[3]);
2200 
2201  // Modified t form eliminates constant term and has broader exponential.
2202  } else {
2203  double modX[2], modX2[2], expX[2], sumX[2];
2204  double modY[3], modY2[3], expY[3], sumY[3];
2205  double den[3], modB[3], apC[3];
2206  for (int ia = 0; ia < 2; ++ia) {
2207  modX[ia] = -2. * APR[ia] * log(xiNow);
2208  modX2[ia] = pow2(modX[ia]);
2209  expX[ia] = exp(-4. * modX[ia]);
2210  sumX[ia] = 4. * modX[ia] + 1.;
2211  }
2212  for (int ib = 0; ib < 3; ++ib) {
2213  int ix = (ib == 0) ? 0 : 1;
2214  modY[ib] = BFAC[ib+1] + modX[ix];
2215  modY2[ib] = pow2(modY[ib]);
2216  expY[ib] = exp(-4. * modY[ib]);
2217  sumY[ib] = 4. * modY[ib] + 1.;
2218  den[ib] = AFAC[ib+1] * modX2[ix] * (1. - expY[ib] * sumY[ib])
2219  + CFAC[ib+1] * modY2[ib] * (1. - expX[ix] * sumX[ix]);
2220  modB[ib] = (AFAC[ib+1] * modX2[ix] * modY[ib] * (1. - expY[ib])
2221  + CFAC[ib+1] * modY2[ib] * modX[ix] * (1. - expX[ix]))
2222  / den[ib] - modX[ix];
2223  apC[ib] = pow2( AFAC[ib+1] * modX[ix] * (1. - expY[ib])
2224  + CFAC[ib+1] * modY[ib] * (1. - expX[ix]) ) / den[ib];
2225  }
2226  ampPPR *= apC[0] * exp(modB[0] * t);
2227  ampRRP *= apC[1] * exp(modB[1] * t);
2228  ampRRR *= apC[2] * exp(modB[2] * t);
2229  }
2230 
2231  // Form factor and pion amplitude, remains unmodified.
2232  double fFac = pFormFac(t);
2233  double cnstPi = CPI[5]/(4. * M_PI) * tAbs/pow2(t - SPION) * pow2(fFac);
2234  double sigPi = CPI[0] * pow(m2XNow, CPI[1])
2235  + CPI[2] * pow(m2XNow, CPI[3]);
2236  double ampPi = cnstPi * sigPi * pow(xiNow, 1. - 2. * alpt[2]);
2237 
2238  // Total high-mass contribution. Done if at high masses.
2239  double ampHM = scaleFac * (ampPPP + ampPPR + ampRRP + ampRRR + ampPi);
2240  if (isHighM) return xi * ampHM;
2241 
2242  // Begin handling of low-mass region.
2243  double ampBkg = 0.;
2244  double ampRes = 0.;
2245  double ampMatch = 0.;
2246  double ampLM = 0.;
2247 
2248  // Resonance contribution.
2249  double qRef = sqrt( (m2X - m2minp) * (m2X - m2minm) / (4. * m2X) );
2250  for (int i = 0; i < 4; ++i) {
2251  double m2Res = pow2(MRES[i]);
2252  double qRes = sqrt( (m2Res - m2minp) * (m2Res - m2minm) / (4. * m2Res) );
2253  double mGam = MRES[i] * WRES[i] * pow( qRef / qRes, 2. * i + 3.)
2254  * pow( (1. + 5. * qRes) / (1. + 5. * qRef), i + 1.);
2255  ampRes += CRES[i] * mGam / (pow2(m2X - m2Res) + pow2(mGam));
2256  ampMatch += CRES[i] * mGam / (pow2(m2Cut - m2Res) + pow2(mGam));
2257  }
2258  ampRes *= exp( CNST[4] * (t - CNST[1]) ) / xi;
2259  ampMatch *= exp( CNST[4] * (t - CNST[1]) ) / xiNow
2260  * (xi - xiThr) / (xiNow - xiThr);
2261 
2262  // Background contribution.
2263  double dAmpPPP = ampPPP * (alp0[0] - 2. * alpt[0]) / xiNow;
2264  double dAmpPPR = ampPPR * (alp0[1] - 2. * alpt[0]) / xiNow;
2265  double dAmpRRP = ampRRP * (alp0[0] - 2. * alpt[1]) / xiNow;
2266  double dAmpRRR = ampRRR * (alp0[1] - 2. * alpt[1]) / xiNow;
2267  double dSigPi = CPI[0] * CPI[1] * pow(m2XNow, CPI[1] - 1.)
2268  + CPI[2] * CPI[3] * pow(m2XNow, CPI[3] - 1.);
2269  double dAmpPi = cnstPi * (sigPi * (1. - 2. * alpt[2])
2270  * pow(xiNow, -2. * alpt[2])
2271  + dSigPi * pow(xiNow, 1. - 2. * alpt[2]) );
2272  double dAmpHM = scaleFac * (dAmpPPP + dAmpPPR + dAmpRRP + dAmpRRR
2273  + dAmpPi);
2274 
2275  // Original background which vanishes quadratically at threshold.
2276  if (modeSD % 2 == 0) {
2277  double coeff1 = (dAmpHM * (xiCut - xiThr) - ampHM) / pow2(xiCut - xiThr);
2278  double coeff2 = 2. * ampHM / (xiCut - xiThr) - dAmpHM;
2279  ampBkg = coeff1 * pow2(xi - xiThr) + coeff2 * (xi - xiThr);
2280 
2281  // Modified form with combination of linear and quadratic description.
2282  } else {
2283  double xiAtM3 = 9. / s;
2284  double coeff1 = dAmpHM;
2285  double coeff2 = ampHM - coeff1 * (xiCut - xiThr);
2286  double coeff3 = - coeff2 / pow2(xiAtM3 - xiThr);
2287  double coeff4 = (2. * coeff1 * (xiAtM3 - xiThr) + 2. * coeff2)
2288  / (xiAtM3 - xiThr) - coeff1;
2289  ampBkg = (xi < xiAtM3) ? coeff3 * pow2(xi - xiThr)
2290  + coeff4 * (xi - xiThr) : coeff1 * (xi - xiThr) + coeff2;
2291  }
2292 
2293  // Return total low-mass contribution.
2294  ampLM = ampRes - ampMatch + ampBkg;
2295  return xi * ampLM;
2296 
2297 }
2298 
2299 //--------------------------------------------------------------------------
2300 
2301 // Single diffractive cross sections integrated over [t_min, t_max].
2302 
2303 double SigmaABMST::dsigmaSDintT(double xi, double tMinIn, double tMaxIn) {
2304 
2305  // Calculate t range. Check if range closed.
2306  double mu1 = SPROTON / s;
2307  double mu3 = xi;
2308  double rootv = (1. - 4. * mu1) * (pow2(1. - mu1 - mu3) - 4. * mu1 * mu3);
2309  if (rootv <= 0.) return 0.;
2310  double tMin = -0.5 * s * (1. - 3. * mu1 - mu3 + sqrt(rootv));
2311  double tMax = s * s * mu1 * pow2(mu3 - mu1) / tMin;
2312  tMin = max( tMin, tMinIn);
2313  tMax = min( tMax, tMaxIn);
2314  if (tMin >= tMax) return 0.;
2315 
2316  // Prepare integration.
2317  double slope = -0.5 * log(xi);
2318  double etMin = exp(slope * tMin);
2319  double etMax = exp(slope * tMax);
2320 
2321  // Do integration by uniform steps in exp(slope * t).
2322  double dsig = 0.;
2323  double etNow, tNow;
2324  for (int i = 0; i < NPOINTSTSD; ++i) {
2325  etNow = etMin + (i + 0.5) * (etMax - etMin) / NPOINTSTSD;
2326  tNow = log(etNow) / slope;
2327  dsig += dsigmaSD( xi, tNow, true, 0) / etNow;
2328  }
2329 
2330  // Normalize and done.
2331  dsig *= (etMax - etMin) / (NPOINTSTSD * slope);
2332  return dsig;
2333 
2334 }
2335 
2336 //--------------------------------------------------------------------------
2337 
2338 // Single diffractive cross section integrated over
2339 // [xi_min, xi_max] * [t_min, t_max].
2340 
2341 double SigmaABMST::dsigmaSDintXiT( double xiMinIn, double xiMaxIn,
2342  double tMinIn, double tMaxIn) {
2343 
2344  // Restrictions on xi range. Check it is not closed.
2345  double sig = 0.;
2346  double xiMin = max(xiMinIn, m2minp / s);
2347  double xiMax = min(xiMaxIn, 1.);
2348  if (xiMin >= xiMax) return 0.;
2349  double xiNow;
2350 
2351  // Integration in xi: check size of affected range and adjust dxi.
2352  if (xiMax > XIDIVSD) {
2353  double xiMinRng = max( XIDIVSD, xiMin);
2354  int nxi = 2 + (xiMax - xiMinRng) / DXIRAWSD;
2355  double dxi = (xiMax - xiMinRng) / nxi;
2356  for (int ixi = 0; ixi < nxi; ++ixi) {
2357  xiNow = xiMinRng + (ixi + 0.5) * dxi;
2358  sig += dxi * dsigmaSDintT( xiNow, tMinIn, tMaxIn) / xiNow;
2359  }
2360  }
2361 
2362  // Integration in ln(xi): check size of affected range and adjust dlnxi.
2363  if (xiMin < XIDIVSD) {
2364  double xiMaxRng = min( XIDIVSD, xiMax);
2365  int nlnxi = 2 + log( xiMaxRng / xiMin) / DLNXIRAWSD;
2366  double dlnxi = log( xiMaxRng / xiMin) / nlnxi;
2367  for (int ilnxi = 0; ilnxi < nlnxi; ++ilnxi) {
2368  xiNow = xiMin * exp( dlnxi * (ilnxi + 0.5));
2369  sig += dlnxi * dsigmaSDintT( xiNow, tMinIn, tMaxIn);
2370  }
2371  }
2372 
2373  // Done.
2374  return sig;
2375 
2376 }
2377 
2378 //--------------------------------------------------------------------------
2379 
2380 // Differential double diffractive cross section.
2381 
2382 double SigmaABMST::dsigmaDD(double xi1, double xi2, double t, int ) {
2383 
2384  // Calculate mass and check it is above threshold. ABMST valid for |t| < 4.
2385  double m2X1 = xi1 * s;
2386  double m2X2 = xi2 * s;
2387  if (m2X1 < m2minp || m2X2 < m2minp) return 0.;
2388  if (modeSD % 2 == 0 && abs(t) > 4.) return 0.;
2389 
2390  // dSigma_DD(x1, x2, t) = dSigma_SD(x1, t) * dSigma_SD(x2, t) / dSigma_el(t).
2391  // Elastic using only Pomerons.
2392  double dSigDD = dsigmaSDcore( xi1, t) * dsigmaSDcore( xi2, t)
2393  / dsigmaEl( t, false, true);
2394 
2395  // Minimal fall-off relative to t = 0 value.
2396  if (useBMin && bMinDD > 0.) {
2397  double dSigDDmx = dsigmaSDcore( xi1, -SPION) * dsigmaSDcore( xi2, -SPION)
2398  * exp(bMinDD * t) / dsigmaEl( 0., false, true);
2399  if (dSigDD > dSigDDmx) dSigDD = dSigDDmx;
2400  }
2401 
2402  // Optionally dampen with 1 / (1 + exp( -p * (y - y_gap))).
2403  if (dampenGap) dSigDD /= 1. + expPygap * pow( xi1 * xi2 * s / SPROTON, ypow);
2404 
2405  // Optionally multiply by s-dependent factor.
2406  if (modeDD == 1) dSigDD *= multDD * pow( s / SPROTON, powDD);
2407 
2408  // Done.
2409  return dSigDD;
2410 
2411 }
2412 
2413 //--------------------------------------------------------------------------
2414 
2415 // Double diffractive cross section integrated by Monte Carlo.
2416 
2417 double SigmaABMST::dsigmaDDintMC() {
2418 
2419  // Set up parameters of integration.
2420  double sigSum = 0.;
2421  double xiMin = m2minp / s;
2422  double mu1 = SPROTON / s;
2423  double xi1, xi2, t;
2424 
2425  // Integrate flat in dln(xi1) * dln(xi2) * exp(b_min t) dt.
2426  for (int iPoint = 0; iPoint < NPOINTMCDD; ++iPoint) {
2427  xi1 = pow( xiMin, rndmPtr->flat() );
2428  xi2 = pow( xiMin, rndmPtr->flat() );
2429  t = log( rndmPtr->flat() ) / BMCINTDD;
2430 
2431  // Check that point is inside phase space.
2432  if (sqrt(xi1) + sqrt(xi2) > 1.) continue;
2433  if (!tInRange( t/s, 1., mu1, mu1, xi1, xi2)) continue;
2434 
2435  // Calculate and add cross section.
2436  sigSum += dsigmaDD( xi1, xi2, t) * exp(-BMCINTDD * t);
2437  }
2438 
2439  // Normalize and done.
2440  sigSum *= pow2(log(xiMin)) / (BMCINTDD * NPOINTMCDD);
2441  return sigSum;
2442 
2443 }
2444 
2445 //--------------------------------------------------------------------------
2446 
2447 // Double diffractive cross section integrated over [t_min, t_max].
2448 
2449 double SigmaABMST::dsigmaDDintT(double xi1, double xi2, double tMinIn,
2450  double tMaxIn) {
2451 
2452  // Calculate t range. Check if range closed.
2453  double mu1 = SPROTON / s;
2454  pair<double,double> tRng = tRange(1., mu1, mu1, xi1, xi2);
2455  double tMin = max( s * tRng.first, tMinIn);
2456  double tMax = min( s * tRng.second, tMaxIn);
2457  if (tMin >= tMax) return 0.;
2458 
2459  // Prepare integration.
2460  double slope = BMCINTDD;
2461  double etMin = exp(slope * tMin);
2462  double etMax = exp(slope * tMax);
2463 
2464  // Do integration by uniform steps in exp(slope * t).
2465  double dsig = 0.;
2466  double etNow, tNow;
2467  for (int i = 0; i < NPOINTSTDD; ++i) {
2468  etNow = etMin + (i + 0.5) * (etMax - etMin) / NPOINTSTDD;
2469  tNow = log(etNow) / slope;
2470  dsig += dsigmaDD( xi1, xi2, tNow) / etNow;
2471  }
2472 
2473  // Normalize and done.
2474  dsig *= (etMax - etMin) / (NPOINTSTDD * slope);
2475  return dsig;
2476 
2477 }
2478 
2479 //--------------------------------------------------------------------------
2480 
2481 // Double diffractive cross section integrated over
2482 // [xi2_min, xi2_max] * [t_min, t_max].
2483 
2484 double SigmaABMST::dsigmaDDintXi2T( double xi1, double xi2MinIn,
2485  double xi2MaxIn, double tMinIn, double tMaxIn) {
2486 
2487  // Restrictions on xi2 range. Check it is not closed.
2488  double dsig = 0.;
2489  double xi2Min = max( xi2MinIn, m2minp / s);
2490  double xi2Max = min( xi2MaxIn, 1. + xi1 - 2. * sqrt(xi1));
2491  if (xi2Min >= xi2Max) return 0.;
2492  double xi2Now;
2493 
2494  // Integration in xi2: check size of affected range and adjust dxi2.
2495  if (xi2Max > XIDIVDD) {
2496  double xi2MinRng = max( XIDIVDD, xi2Min);
2497  int nxi2 = 2 + (xi2Max - xi2MinRng) / DXIRAWDD;
2498  double dxi2 = (xi2Max - xi2MinRng) / nxi2;
2499  for (int ixi2 = 0; ixi2 < nxi2; ++ixi2) {
2500  xi2Now = xi2MinRng + (ixi2 + 0.5) * dxi2;
2501  dsig += dxi2 * dsigmaDDintT( xi1, xi2Now, tMinIn, tMaxIn)
2502  / xi2Now;
2503  }
2504  }
2505 
2506  // Integration in ln(xi2): check size of affected range and adjust dlnxi2.
2507  if (xi2Min < XIDIVDD) {
2508  double xi2MaxRng = min( XIDIVDD, xi2Max);
2509  int nlnxi2 = 2 + log( xi2MaxRng / xi2Min) / DLNXIRAWDD;
2510  double dlnxi2 = log( xi2MaxRng / xi2Min) / nlnxi2;
2511  for (int ilnxi2 = 0; ilnxi2 < nlnxi2; ++ilnxi2) {
2512  xi2Now = xi2Min * exp( dlnxi2 * (ilnxi2 + 0.5));
2513  dsig += dlnxi2 * dsigmaDDintT( xi1, xi2Now, tMinIn, tMaxIn);
2514  }
2515  }
2516 
2517  // Done.
2518  return dsig;
2519 
2520 }
2521 
2522 //--------------------------------------------------------------------------
2523 
2524 // Double diffractive cross section integrated over
2525 // [xi1_min, xi1_max] * [xi2_min, xi2_max] * [t_min, t_max].
2526 
2527 double SigmaABMST::dsigmaDDintXi1Xi2T( double xi1MinIn, double xi1MaxIn,
2528  double xi2MinIn, double xi2MaxIn, double tMinIn, double tMaxIn) {
2529 
2530  // Restrictions on xi1 range. Check it is not closed.
2531  double dsig = 0.;
2532  double xi1Min = max( xi1MinIn, m2minp / s);
2533  double xi1Max = min( xi1MaxIn, 1.);
2534  if (xi1Min >= xi1Max) return 0.;
2535  double xi1Now;
2536 
2537  // Integration in xi1: check size of affected range and adjust dxi1.
2538  if (xi1Max > XIDIVDD) {
2539  double xi1MinRng = max( XIDIVDD, xi1Min);
2540  int nxi1 = 2 + (xi1Max - xi1MinRng) / DXIRAWDD;
2541  double dxi1 = (xi1Max - xi1MinRng) / nxi1;
2542  for (int ixi1 = 0; ixi1 < nxi1; ++ixi1) {
2543  xi1Now = xi1MinRng + (ixi1 + 0.5) * dxi1;
2544  dsig += dxi1 * dsigmaDDintXi2T( xi1Now, xi2MinIn, xi2MaxIn,
2545  tMinIn, tMaxIn) / xi1Now;
2546  }
2547  }
2548 
2549  // Integration in ln(xi1): check size of affected range and adjust dlnxi1.
2550  if (xi1Min < XIDIVDD) {
2551  double xi1MaxRng = min( XIDIVDD, xi1Max);
2552  int nlnxi1 = 2 + log( xi1MaxRng / xi1Min) / DLNXIRAWDD;
2553  double dlnxi1 = log( xi1MaxRng / xi1Min) / nlnxi1;
2554  for (int ilnxi1 = 0; ilnxi1 < nlnxi1; ++ilnxi1) {
2555  xi1Now = xi1Min * exp( dlnxi1 * (ilnxi1 + 0.5));
2556  dsig += dlnxi1 * dsigmaDDintXi2T( xi1Now, xi2MinIn, xi2MaxIn,
2557  tMinIn, tMaxIn);
2558  }
2559  }
2560 
2561  // Done.
2562  return dsig;
2563 
2564 }
2565 
2566 //--------------------------------------------------------------------------
2567 
2568 // Differential central diffractive cross section.
2569 
2570 double SigmaABMST::dsigmaCD(double xi1, double xi2, double t1, double t2,
2571  int ) {
2572 
2573  // ABMST valid for |t| < 4.
2574  if (modeSD % 2 == 0 && max( abs(t1), abs(t2)) > 4.) return 0.;
2575 
2576  // dSigma_CD(x1, x2, t1, t2)
2577  // = dSigma_SD(x1, t1) * dSigma_SD(x2, t2) / sigma_tot.
2578  double dSigCD = dsigmaSDcore( xi1, t1) * dsigmaSDcore( xi2, t2) / sigTot;
2579 
2580  // Minimal fall-off relative to t = 0 value.
2581  if (useBMin && bMinCD > 0.) {
2582  double dSigCDmx = dsigmaSDcore( xi1, -SPION) * dsigmaSDcore( xi2, -SPION)
2583  * exp(bMinCD * (t1 + t2)) / sigTot;
2584  if (dSigCD > dSigCDmx) dSigCD = dSigCDmx;
2585  }
2586 
2587  // Optionally dampen with 1 / (1 + exp( -p * (y - y_gap))) for both gaps.
2588  if (dampenGap) dSigCD /= (1. + expPygap * pow( xi1, ypow))
2589  * (1. + expPygap * pow( xi2, ypow));
2590 
2591  // Optionally multiply by s-dependent factor.
2592  if (modeCD == 1) dSigCD *= multCD * pow( s / SPROTON, powCD);
2593 
2594  // Done.
2595  return dSigCD;
2596 
2597 }
2598 
2599 //--------------------------------------------------------------------------
2600 
2601 // Central diffractive cross section integrated by Monte Carlo.
2602 
2603 double SigmaABMST::dsigmaCDintMC() {
2604 
2605  // Set up parameters of integration.
2606  double sigSum = 0.;
2607  double xiMin = m2minp / s;
2608  double xi1, xi2, t1, t2;
2609 
2610  // Integrate flat in dln(xi1) * exp(b_min t1) dt1 * (same with xi2, t2).
2611  for (int iPoint = 0; iPoint < NPOINTMCCD; ++iPoint) {
2612  xi1 = pow( xiMin, rndmPtr->flat() );
2613  xi2 = pow( xiMin, rndmPtr->flat() );
2614  t1 = log( rndmPtr->flat() ) / BMCINTCD;
2615  t2 = log( rndmPtr->flat() ) / BMCINTCD;
2616 
2617  // Check that point is inside phase space.
2618  if (xi1 * xi2 < xiMin) continue;
2619  if (xi1 * xi2 + 2. * xiMin > 1.) continue;
2620  if (!tInRange( t1, s, SPROTON, SPROTON, SPROTON, SPROTON + xi1 * s))
2621  continue;
2622  if (!tInRange( t1, s, SPROTON, SPROTON, SPROTON, SPROTON + xi2 * s))
2623  continue;
2624 
2625  // Calculate and add cross section.
2626  sigSum += dsigmaCD( xi1, xi2, t1, t2) * exp(-BMCINTCD * (t1 + t2));
2627  }
2628 
2629  // Normalize and done.
2630  sigSum *= pow2(log(xiMin) / BMCINTCD) / NPOINTMCCD;
2631  return sigSum;
2632 
2633 }
2634 
2635 //==========================================================================
2636 
2637 // The SigmaRPP class.
2638 // It parametrizes pp/ppbar total and elastic cross sections according to
2639 // the fit in Review of Particle Physics 2016.
2640 
2641 //--------------------------------------------------------------------------
2642 
2643 // Definitions of static variables.
2644 
2645 // Parameters of parametrization.
2646 const double SigmaRPP::EPS1[] = { 1., 0.614, 0.444, 1., 1., 1.};
2647 const double SigmaRPP::ALPP[] = { 0.151, 0.8, 0.8, 0.947};
2648 const double SigmaRPP::NORM[] = { 0.2478, 0.0078, 11.22, -0.150, 148.4, -26.6,
2649  -1.5, -0.0441, 0., 0.686, -3.82, -8.60, 64.1, 99.1, -58.0, 9.5};
2650 const double SigmaRPP::BRPP[] = { 3.592, 0.622, 5.44, 0.205, 5.643, 1.92,
2651  0.41, 0., 0., 3.013, 2.572, 12.25, 2.611, 11.28, 1.27};
2652 const double SigmaRPP::KRPP[] = { 0.3076, 0.0998, 1.678, 0.190, -26.1};
2653 const double SigmaRPP::LAM2FF = 0.71;
2654 
2655 //--------------------------------------------------------------------------
2656 
2657 // Calculate total and (integrated) elastic cross sections.
2658 
2659 bool SigmaRPP::calcTotEl( int idAin, int idBin, double sIn, double ,
2660  double ) {
2661 
2662  // Find appropriate combination of incoming beams.
2663  idA = idAin;
2664  idB = idBin;
2665  ispp = (idA * idB > 0);
2666  s = sIn;
2667  facEl = CONVERTEL / (s * (s - 4. * SPROTON));
2668  isExpEl = false;
2669 
2670  // Total cross section and the rho parameter.
2671  complex amp = amplitude( 0., false);
2672  sigTot = imag(amp) / sqrt(s * ( s - 4. * SPROTON));
2673  rhoOwn = real(amp) / imag(amp);
2674 
2675  // Total elastic cross section, by integration in exp( MINSLOPEEL * t).
2676  sigEl = 0.;
2677  for (int i = 0; i < NPOINTS; ++i) {
2678  double y = (i + 0.5) / NPOINTS;
2679  double t = log(y) / MINSLOPEEL;
2680  sigEl += dsigmaEl( t, false) / y;
2681  }
2682  sigEl /= NPOINTS * MINSLOPEEL;
2683 
2684  // Approximate exponential slope.
2685  bEl = log( dsigmaEl( -TABSREF, false) / dsigmaEl( 0., false) ) / (-TABSREF);
2686 
2687  // Done if no Coulomb corrections.
2688  hasCou = tryCoulomb;
2689  if (abs(idAin) == 2112 || abs(idBin) == 2112) hasCou = false;
2690  sigTotCou = sigTot;
2691  sigElCou = sigEl;
2692  if (!hasCou) return true;
2693 
2694  // Reduce hadronic part of elastic cross section by tMin cut.
2695  sigElCou = sigEl * exp( - bEl * tAbsMin);
2696  if (tAbsMin < 0.9 * TABSMAX) {
2697 
2698  // Loop through t range according to dt/t^2.
2699  double sumCou = 0.;
2700  double xRel, tAbs;
2701  for (int i = 0; i < NPOINTS; ++i) {
2702  xRel = (i + 0.5) / NPOINTS;
2703  tAbs = tAbsMin * TABSMAX / (tAbsMin + xRel * (TABSMAX - tAbsMin));
2704 
2705  // Evaluate cross section difference between with and without Coulomb.
2706  sumCou += pow2(tAbs) * (dsigmaEl( -tAbs, true)
2707  - dsigmaEl( -tAbs, false));
2708  }
2709 
2710  // Include common factors to give new elastic and total cross sections.
2711  sigElCou += sumCou * (TABSMAX - tAbsMin)/ (tAbsMin * TABSMAX * NPOINTS);
2712  }
2713  sigTotCou = sigTot - sigEl + sigElCou;
2714 
2715  // Done.
2716  return true;
2717 
2718 }
2719 
2720 //--------------------------------------------------------------------------
2721 
2722 // Amplitude.
2723 
2724 complex SigmaRPP::amplitude( double t, bool useCoulomb) {
2725 
2726  // Modified s-related values.
2727  double shat = s - 2. * SPROTON + 0.5 * t;
2728  complex stlog = complex( log(shat), -0.5 * M_PI);
2729  complex taut = sqrt(abs(t)) * stlog;
2730 
2731  // Trajectories.
2732  double aP = EPS1[0] + ALPP[0] * t;
2733  double aRpos = EPS1[1] + ALPP[1] * t;
2734  double aRneg = EPS1[2] + ALPP[2] * t;
2735  double aO = EPS1[3] + ALPP[3] * t;
2736  double aOP = EPS1[4] + ALPP[0] * ALPP[3] * t / (ALPP[0] + ALPP[3]);
2737  double aPP = EPS1[5] + 0.5 * ALPP[0] * t;
2738  double aRPpos = EPS1[1] + ALPP[0] * ALPP[1] * t / (ALPP[0] + ALPP[1]);
2739  double aRPneg = EPS1[2] + ALPP[0] * ALPP[2] * t / (ALPP[0] + ALPP[2]);
2740 
2741  // Even terms.
2742  complex besArg = KRPP[0] * taut;
2743  complex besJ0n = besJ0(besArg);
2744  complex besJ1n = besJ1(besArg);
2745  complex besRat = (abs(besArg) < 0.01) ? 1. : 2. * besJ1n / besArg;
2746  complex fPosH = complex( 0., shat) * (NORM[0] * besRat
2747  * exp(BRPP[0] * t) * stlog * stlog
2748  + NORM[1] * besJ0n * exp(BRPP[1] * t) * stlog
2749  + NORM[2] * (besJ0n - besArg * besJ1n) * exp(BRPP[2] * t));
2750  complex fPosP = -NORM[3] * exp(BRPP[3] * t) * sModAlp( shat, aP);
2751  complex fPosPP = (-NORM[4] / stlog) * exp(BRPP[4] * t) * sModAlp( shat, aPP);
2752  complex fPosR = -NORM[5] * exp(BRPP[5] * t) * sModAlp( shat, aRpos);
2753  complex fPosRP = t * (NORM[6] / stlog) * exp(BRPP[6] * t)
2754  * sModAlp( shat, aRPpos);
2755  complex nPos = complex( 0., -shat) * NORM[7] * stlog * t
2756  * pow( 1. - t / KRPP[2], -5.);
2757  complex fPos = fPosH + fPosP + fPosPP + fPosR + fPosRP + nPos;
2758 
2759  // Odd terms.
2760  complex fNegMO = shat * (NORM[9] * cos(KRPP[1] * taut) * exp(BRPP[9] * t)
2761  * stlog + NORM[10] * exp(BRPP[10] * t));
2762  complex fNegO = complex( 0., NORM[11]) * exp(BRPP[11] * t)
2763  * sModAlp( shat, aO) * (1. + KRPP[4] * t);
2764  complex fNegOP = (complex( 0., NORM[12]) / stlog) * exp(BRPP[12] * t)
2765  * sModAlp( shat, aOP);
2766  complex fNegR = complex( 0., -NORM[13]) * exp(BRPP[13] * t)
2767  * sModAlp( shat, aRneg);
2768  complex fNegRP = t * (complex( 0., -NORM[14]) / stlog) * exp(BRPP[14] * t)
2769  * sModAlp( shat, aRPneg);
2770  complex nNeg = -shat * NORM[15] * stlog * t * pow( 1. - t / KRPP[3], -5.);
2771  complex fNeg = fNegMO + fNegO + fNegOP + fNegR + fNegRP + nNeg;
2772 
2773  // Combine nuclear part.
2774  complex ampSum = ispp ? fPos + fNeg : fPos - fNeg;
2775 
2776  // Optional Coulomb term. Must not be used for t = 0.
2777  complex ampCou = 0.;
2778  if (useCoulomb && t < 0.) {
2779  double bAppr = imag(ampSum) / ( sqrt(s * ( s - 4. * SPROTON))
2780  * 4. * M_PI * HBARCSQ );
2781  double phase = (log( -0.5 * t * (bAppr + 8. / LAM2FF)) + GAMMAEUL
2782  - 4. * t / LAM2FF * log(- 4. * t / LAM2FF)
2783  - 2. * t / LAM2FF) * (ispp ? -1. : 1.);
2784  ampCou = exp( complex( 0., ALPHAEM * phase) ) * 8. * M_PI * HBARCSQ
2785  * ALPHAEM * s / t * pow(1 - t / LAM2FF, -4.);
2786  }
2787 
2788  // Combine and return.
2789  return ispp ? ampSum + ampCou : ampSum - ampCou;
2790 
2791 }
2792 
2793 //--------------------------------------------------------------------------
2794 
2795 // Complex Bessel functions J0 and J1.
2796 
2797 complex SigmaRPP::besJ0( complex x) {
2798  int mMax = 5. + 5. * abs(x);
2799  complex z = 0.25 * x * x;
2800  complex term = 1.;
2801  complex sum = term;
2802  for (int m = 1; m < mMax; ++m) {
2803  term *= - z / double(m * m);
2804  sum += term;
2805  }
2806  return sum;
2807 }
2808 
2809 complex SigmaRPP::besJ1( complex x) {
2810  int mMax = 5. + 5. * abs(x);
2811  complex z = 0.25 * x * x;
2812  complex term = 0.5 * x;
2813  complex sum = term;
2814  for (int m = 1; m < mMax; ++m) {
2815  term *= - z / double(m * (m+1));
2816  sum += term;
2817  }
2818  return sum;
2819 }
2820 
2821 //==========================================================================
2822 
2823 } // end namespace Pythia8