StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
MultipartonInteractions.cc
1 // MultipartonInteractions.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
7 // SigmaMultiparton and MultipartonInteractions classes.
8 
9 #include "Pythia8/MultipartonInteractions.h"
10 
11 // Internal headers for special processes.
12 #include "Pythia8/SigmaQCD.h"
13 #include "Pythia8/SigmaEW.h"
14 #include "Pythia8/SigmaOnia.h"
15 
16 namespace Pythia8 {
17 
18 //==========================================================================
19 
20 // The SigmaMultiparton class.
21 
22 //--------------------------------------------------------------------------
23 
24 // Constants: could be changed here if desired, but normally should not.
25 // These are of technical nature, as described for each.
26 
27 // The sum of outgoing masses must not be too close to the cm energy.
28 const double SigmaMultiparton::MASSMARGIN = 0.1;
29 
30 // Fraction of time not the dominant "gluon t-channel" process is picked.
31 const double SigmaMultiparton::OTHERFRAC = 0.2;
32 
33 //--------------------------------------------------------------------------
34 
35 // Initialize the generation process for given beams.
36 
37 bool SigmaMultiparton::init(int inState, int processLevel, Info* infoPtr,
38  BeamParticle* beamAPtr, BeamParticle* beamBPtr) {
39 
40  // Store input pointer for future use.
41  particleDataPtr = infoPtr->particleDataPtr;
42  rndmPtr = infoPtr->rndmPtr;
43  Settings* settingsPtr = infoPtr->settingsPtr;
44 
45  // Reset vector sizes (necessary in case of re-initialization).
46  if (sigmaT.size() > 0) {
47  for (int i = 0; i < int(sigmaT.size()); ++i) delete sigmaT[i];
48  sigmaT.resize(0);
49  }
50  if (sigmaU.size() > 0) {
51  for (int i = 0; i < int(sigmaU.size()); ++i) delete sigmaU[i];
52  sigmaU.resize(0);
53  }
54 
55  // Always store mimimal set of processes:QCD 2 -> 2 t-channel.
56 
57  // Gluon-gluon instate.
58  if (inState == 0) {
59  sigmaT.push_back( new Sigma2gg2gg() );
60  sigmaU.push_back( new Sigma2gg2gg() );
61 
62  // Quark-gluon instate.
63  } else if (inState == 1) {
64  sigmaT.push_back( new Sigma2qg2qg() );
65  sigmaU.push_back( new Sigma2qg2qg() );
66 
67  // Quark-(anti)quark instate.
68  } else {
69  sigmaT.push_back( new Sigma2qq2qq() );
70  sigmaU.push_back( new Sigma2qq2qq() );
71  }
72 
73  // Normally store QCD processes to new flavour.
74  if (processLevel > 0) {
75  if (inState == 0) {
76  sigmaT.push_back( new Sigma2gg2qqbar() );
77  sigmaU.push_back( new Sigma2gg2qqbar() );
78  sigmaT.push_back( new Sigma2gg2QQbar(4, 121) );
79  sigmaU.push_back( new Sigma2gg2QQbar(4, 121) );
80  sigmaT.push_back( new Sigma2gg2QQbar(5, 123) );
81  sigmaU.push_back( new Sigma2gg2QQbar(5, 123) );
82  } else if (inState == 2) {
83  sigmaT.push_back( new Sigma2qqbar2gg() );
84  sigmaU.push_back( new Sigma2qqbar2gg() );
85  sigmaT.push_back( new Sigma2qqbar2qqbarNew() );
86  sigmaU.push_back( new Sigma2qqbar2qqbarNew() );
87  sigmaT.push_back( new Sigma2qqbar2QQbar(4, 122) );
88  sigmaU.push_back( new Sigma2qqbar2QQbar(4, 122) );
89  sigmaT.push_back( new Sigma2qqbar2QQbar(5, 124) );
90  sigmaU.push_back( new Sigma2qqbar2QQbar(5, 124) );
91  }
92  }
93 
94  // Optionally store electroweak processes, mainly photon production.
95  if (processLevel > 1) {
96  if (inState == 0) {
97  sigmaT.push_back( new Sigma2gg2ggamma() );
98  sigmaU.push_back( new Sigma2gg2ggamma() );
99  sigmaT.push_back( new Sigma2gg2gammagamma() );
100  sigmaU.push_back( new Sigma2gg2gammagamma() );
101  } else if (inState == 1) {
102  sigmaT.push_back( new Sigma2qg2qgamma() );
103  sigmaU.push_back( new Sigma2qg2qgamma() );
104  } else if (inState == 2) {
105  sigmaT.push_back( new Sigma2qqbar2ggamma() );
106  sigmaU.push_back( new Sigma2qqbar2ggamma() );
107  sigmaT.push_back( new Sigma2ffbar2gammagamma() );
108  sigmaU.push_back( new Sigma2ffbar2gammagamma() );
109  sigmaT.push_back( new Sigma2ffbar2ffbarsgm() );
110  sigmaU.push_back( new Sigma2ffbar2ffbarsgm() );
111  }
112  if (inState >= 2) {
113  sigmaT.push_back( new Sigma2ff2fftgmZ() );
114  sigmaU.push_back( new Sigma2ff2fftgmZ() );
115  sigmaT.push_back( new Sigma2ff2fftW() );
116  sigmaU.push_back( new Sigma2ff2fftW() );
117  }
118  }
119 
120  // Optionally store charmonium and bottomonium production.
121  if (processLevel > 2) {
122  SigmaOniaSetup charmonium(infoPtr, 4);
123  SigmaOniaSetup bottomonium(infoPtr, 5);
124  if (inState == 0) {
125  charmonium.setupSigma2gg(sigmaT, true);
126  charmonium.setupSigma2gg(sigmaU, true);
127  bottomonium.setupSigma2gg(sigmaT, true);
128  bottomonium.setupSigma2gg(sigmaU, true);
129  } else if (inState == 1) {
130  charmonium.setupSigma2qg(sigmaT, true);
131  charmonium.setupSigma2qg(sigmaU, true);
132  bottomonium.setupSigma2qg(sigmaT, true);
133  bottomonium.setupSigma2qg(sigmaU, true);
134  } else if (inState == 2) {
135  charmonium.setupSigma2qq(sigmaT, true);
136  charmonium.setupSigma2qq(sigmaU, true);
137  bottomonium.setupSigma2qq(sigmaT, true);
138  bottomonium.setupSigma2qq(sigmaU, true);
139  }
140  }
141 
142  // Resize arrays to match sizes above.
143  nChan = sigmaT.size();
144  needMasses.resize(nChan);
145  m3Fix.resize(nChan);
146  m4Fix.resize(nChan);
147  sHatMin.resize(nChan);
148  useNarrowBW3.resize(nChan);
149  useNarrowBW4.resize(nChan);
150  sigmaTval.resize(nChan);
151  sigmaUval.resize(nChan);
152  bool useBreitWigners = settingsPtr->flag("PhaseSpace:useBreitWigners");
153  double minWidthNarrowBW = settingsPtr->parm("PhaseSpace:minWidthNarrowBW");
154 
155  // Initialize the processes.
156  for (int i = 0; i < nChan; ++i) {
157  sigmaT[i]->initInfoPtr(*infoPtr);
158  sigmaT[i]->init(beamAPtr, beamBPtr);
159  sigmaT[i]->initProc();
160  sigmaU[i]->initInfoPtr(*infoPtr);
161  sigmaU[i]->init(beamAPtr, beamBPtr);
162  sigmaU[i]->initProc();
163 
164  // Prepare for massive kinematics where required.
165  int id3Mass = sigmaT[i]->id3Mass();
166  int id4Mass = sigmaT[i]->id4Mass();
167  needMasses[i] = (id3Mass > 0 || id4Mass > 0);
168  m3Fix[i] = (id3Mass > 0) ? particleDataPtr->m0(id3Mass) : 0.;
169  m4Fix[i] = (id4Mass > 0) ? particleDataPtr->m0(id4Mass) : 0.;
170  sHatMin[i] = pow2( m3Fix[i] + m4Fix[i] + MASSMARGIN);
171 
172  // Prepare for (narrow) Breit-Wigner mass distribution.
173  useNarrowBW3[i] = (useBreitWigners && id3Mass > 0
174  && particleDataPtr->mWidth(id3Mass) > minWidthNarrowBW);
175  useNarrowBW4[i] = (useBreitWigners && id4Mass > 0
176  && particleDataPtr->mWidth(id4Mass) > minWidthNarrowBW);
177  }
178 
179  // Done.
180  return true;
181 
182 }
183 
184 //--------------------------------------------------------------------------
185 
186 // Calculate cross section summed over possibilities.
187 
188 double SigmaMultiparton::sigma( int id1, int id2, double x1, double x2,
189  double sHat, double tHat, double uHat, double alpS, double alpEM,
190  bool restore, bool pickOtherIn) {
191 
192  // Choose either the dominant process (in slot 0) or the rest of them.
193  if (restore) pickOther = pickOtherIn;
194  else pickOther = (rndmPtr->flat() < OTHERFRAC);
195 
196  // Iterate over all subprocesses.
197  sigmaTsum = 0.;
198  sigmaUsum = 0.;
199  for (int i = 0; i < nChan; ++i) {
200  sigmaTval[i] = 0.;
201  sigmaUval[i] = 0.;
202 
203  // Skip the not chosen processes.
204  if (i == 0 && pickOther) continue;
205  if (i > 0 && !pickOther) continue;
206 
207  // Check if variable mass is needed (and then ...Fix becomes misleading).
208  if (useNarrowBW3[i])
209  m3Fix[i] = particleDataPtr->mSel(sigmaT[i]->id3Mass());
210  if (useNarrowBW4[i])
211  m4Fix[i] = particleDataPtr->mSel(sigmaT[i]->id4Mass());
212  if ((useNarrowBW3[i] || useNarrowBW4[i])
213  && pow2( m3Fix[i] + m4Fix[i] + MASSMARGIN) > sHat) return 0.;
214 
215  // t-channel-sampling contribution.
216  if (sHat > sHatMin[i]) {
217  sigmaT[i]->set2KinMPI( x1, x2, sHat, tHat, uHat,
218  alpS, alpEM, needMasses[i], m3Fix[i], m4Fix[i]);
219  sigmaTval[i] = sigmaT[i]->sigmaHatWrap(id1, id2);
220  sigmaT[i]->pickInState(id1, id2);
221  // Correction factor for tHat rescaling in massive kinematics.
222  if (needMasses[i]) sigmaTval[i] *= sigmaT[i]->sHBetaMPI() / sHat;
223  sigmaTsum += sigmaTval[i];
224  }
225 
226  // u-channel-sampling contribution.
227  if (sHat > sHatMin[i]) {
228  sigmaU[i]->set2KinMPI( x1, x2, sHat, uHat, tHat,
229  alpS, alpEM, needMasses[i], m3Fix[i], m4Fix[i]);
230  sigmaUval[i] = sigmaU[i]->sigmaHatWrap( id1, id2);
231  sigmaU[i]->pickInState(id1, id2);
232  // Correction factor for tHat rescaling in massive kinematics.
233  if (needMasses[i]) sigmaUval[i] *= sigmaU[i]->sHBetaMPI() / sHat;
234  sigmaUsum += sigmaUval[i];
235  }
236 
237  // Average of t- and u-channel sampling; corrected for not selected channels.
238  }
239  double sigmaAvg = 0.5 * (sigmaTsum + sigmaUsum);
240  if (pickOther) sigmaAvg /= OTHERFRAC;
241  if (!pickOther) sigmaAvg /= (1. - OTHERFRAC);
242  return sigmaAvg;
243 
244 }
245 
246 //--------------------------------------------------------------------------
247 
248 // Return one subprocess, picked according to relative cross sections.
249 
250 SigmaProcess* SigmaMultiparton::sigmaSel() {
251 
252  // Decide between t- and u-channel-sampled kinematics.
253  pickedU = (rndmPtr->flat() * (sigmaTsum + sigmaUsum) < sigmaUsum);
254 
255  // Pick one of t-channel-sampled processes.
256  if (!pickedU) {
257  double sigmaRndm = sigmaTsum * rndmPtr->flat();
258  int iPick = -1;
259  do sigmaRndm -= sigmaTval[++iPick];
260  while (sigmaRndm > 0.);
261  return sigmaT[iPick];
262 
263  // Pick one of u-channel-sampled processes.
264  } else {
265  double sigmaRndm = sigmaUsum * rndmPtr->flat();
266  int iPick = -1;
267  do sigmaRndm -= sigmaUval[++iPick];
268  while (sigmaRndm > 0.);
269  return sigmaU[iPick];
270  }
271 
272 }
273 
274 //==========================================================================
275 
276 // The MultipartonInteractions class.
277 
278 //--------------------------------------------------------------------------
279 
280 // Constants: could be changed here if desired, but normally should not.
281 // These are of technical nature, as described for each.
282 
283 // Factorization scale pT2 by default, but could be shifted to pT2 + pT02.
284 // (A priori possible, but problems for flavour threshold interpretation.)
285 const bool MultipartonInteractions::SHIFTFACSCALE = false;
286 
287 // Pick one parton to represent rescattering cross section to speed up.
288 const bool MultipartonInteractions::PREPICKRESCATTER = true;
289 
290 // Naive upper estimate of cross section too pessimistic, so reduce by this.
291 const double MultipartonInteractions::SIGMAFUDGE = 0.8;
292 
293 // The r value above, picked to allow a flatter correct/trial cross section.
294 const double MultipartonInteractions::RPT20 = 0.25;
295 
296 // Reduce pT0 by factor pT0STEP if sigmaInt < SIGMASTEP * sigmaND.
297 const double MultipartonInteractions::PT0STEP = 0.9;
298 const double MultipartonInteractions::SIGMASTEP = 1.1;
299 
300 // Stop if pT0 or pTmin fall below this, or alpha_s blows up.
301 const double MultipartonInteractions::PT0MIN = 0.2;
302 
303 // Refuse too low expPow in impact parameter profile.
304 const double MultipartonInteractions::EXPPOWMIN = 0.4;
305 
306 // Define low-b region by interaction rate above given number.
307 const double MultipartonInteractions::PROBATLOWB = 0.6;
308 
309 // Basic step size for b integration; sometimes modified.
310 const double MultipartonInteractions::BSTEP = 0.01;
311 
312 // Stop b integration when integrand dropped enough.
313 const double MultipartonInteractions::BMAX = 1e-8;
314 
315 // Do not allow too large argument to exp function.
316 const double MultipartonInteractions::EXPMAX = 50.;
317 
318 // Convergence criterion for k iteration.
319 const double MultipartonInteractions::KCONVERGE = 1e-7;
320 
321 // Conversion of GeV^{-2} to mb for cross section.
322 const double MultipartonInteractions::CONVERT2MB = 0.389380;
323 
324 // Stay away from division by zero in Jacobian for tHat -> pT2.
325 const double MultipartonInteractions::ROOTMIN = 0.01;
326 
327 // No need to reinitialize parameters if energy close to previous.
328 const double MultipartonInteractions::ECMDEV = 0.01;
329 
330 // Settings for x-dependent matter profile:
331 // Number of bins in b (with these settings, no bStep increase and
332 // reintegration needed with a1 ~ 0.20 up to ECM ~ 40TeV).
333 const int MultipartonInteractions::XDEP_BBIN = 500;
334 // Initial value of a0.
335 const double MultipartonInteractions::XDEP_A0 = 1.0;
336 // Width of form ( XDEP_A1 + a1 * log(1 / x) ).
337 const double MultipartonInteractions::XDEP_A1 = 1.0;
338 // Initial step size in b and increment.
339 const double MultipartonInteractions::XDEP_BSTEP = 0.02;
340 const double MultipartonInteractions::XDEP_BSTEPINC = 0.01;
341 // Overlap-weighted cross section in last bin of b must be beneath
342 // XDEP_CUTOFF * sigmaInt.
343 const double MultipartonInteractions::XDEP_CUTOFF = 1e-4;
344 // a0 is calculated in units of sqrt(mb), so convert to fermi.
345 const double MultipartonInteractions::XDEP_SMB2FM = sqrt(0.1);
346 
347 // Only write warning when weight clearly above unity.
348 const double MultipartonInteractions::WTACCWARN = 1.1;
349 
350 // Limit below which scientific notation is used for printing.
351 const double MultipartonInteractions::SIGMAMBLIMIT = 1.;
352 
353 //--------------------------------------------------------------------------
354 
355 // Initialize the generation process for given beams.
356 
357 bool MultipartonInteractions::init( bool doMPIinit, int iDiffSysIn,
358  BeamParticle* beamAPtrIn, BeamParticle* beamBPtrIn,
359  PartonVertexPtr partonVertexPtrIn, bool hasGammaIn) {
360 
361  // Store input pointers for future use. Done if no initialization.
362  beamAPtr = beamAPtrIn;
363  beamBPtr = beamBPtrIn;
364  iDiffSys = iDiffSysIn;
365  partonVertexPtr = partonVertexPtrIn;
366  hasGamma = hasGammaIn;
367  if (!doMPIinit) return false;
368 
369  // If both beams are baryons then softer PDF's than for mesons/Pomerons.
370  hasBaryonBeams = ( beamAPtr->isBaryon() && beamBPtr->isBaryon() );
371  hasPomeronBeams = ( beamAPtr->id() == 990 || beamBPtr->id() == 990 );
372 
373  // Matching in pT of hard interaction to further interactions.
374  pTmaxMatch = mode("MultipartonInteractions:pTmaxMatch");
375 
376  // Parameters of alphaStrong generation.
377  alphaSvalue = parm("MultipartonInteractions:alphaSvalue");
378  alphaSorder = mode("MultipartonInteractions:alphaSorder");
379  alphaSnfmax = mode("StandardModel:alphaSnfmax");
380 
381  // Parameters of alphaEM generation.
382  alphaEMorder = mode("MultipartonInteractions:alphaEMorder");
383 
384  // Parameters of cross section generation.
385  Kfactor = parm("MultipartonInteractions:Kfactor");
386 
387  // Check if photon-photon or photon-hadron collision.
388  isGammaGamma = beamAPtr->isGamma() && beamBPtr->isGamma();
389  isGammaHadron = beamAPtr->isGamma() && beamBPtr->isHadron();
390  isHadronGamma = beamAPtr->isHadron() && beamBPtr->isGamma();
391 
392  // Regularization of QCD evolution for pT -> 0.
393  // Separate default parameters for photon-photon collisions.
394  if (isGammaGamma) {
395  pT0paramMode = mode("PhotonPhoton:pT0parametrization");
396  pT0Ref = parm("PhotonPhoton:pT0Ref");
397  ecmRef = parm("PhotonPhoton:ecmRef");
398  ecmPow = parm("PhotonPhoton:ecmPow");
399  pTmin = parm("PhotonPhoton:pTmin");
400  } else {
401  pT0paramMode = mode("MultipartonInteractions:pT0parametrization");
402  pT0Ref = parm("MultipartonInteractions:pT0Ref");
403  ecmRef = parm("MultipartonInteractions:ecmRef");
404  ecmPow = parm("MultipartonInteractions:ecmPow");
405  pTmin = parm("MultipartonInteractions:pTmin");
406  }
407 
408  // Impact parameter profile: nondiffractive topologies.
409  if (iDiffSys == 0) {
410  bProfile = mode("MultipartonInteractions:bProfile");
411  coreRadius = parm("MultipartonInteractions:coreRadius");
412  coreFraction = parm("MultipartonInteractions:coreFraction");
413  expPow = parm("MultipartonInteractions:expPow");
414  expPow = max(EXPPOWMIN, expPow);
415  // x-dependent impact parameter profile.
416  a1 = parm("MultipartonInteractions:a1");
417 
418  // Impact parameter profile: diffractive topologies.
419  } else {
420  bProfile = mode("Diffraction:bProfile");
421  coreRadius = parm("Diffraction:coreRadius");
422  coreFraction = parm("Diffraction:coreFraction");
423  expPow = parm("Diffraction:expPow");
424  expPow = max(EXPPOWMIN, expPow);
425  }
426 
427  // No x-dependent impact-parameter profile for diffraction.
428  if ((iDiffSys > 0 || flag("Diffraction:doHard")) && bProfile == 4) {
429  infoPtr->errorMsg("Error in MultipartonInteractions::init:"
430  " chosen b profile not allowed for diffraction");
431  return false;
432  }
433 
434  // Common choice of "pT" scale for determining impact parameter.
435  bSelScale = mode("MultipartonInteractions:bSelScale");
436 
437  // Process sets to include in machinery.
438  processLevel = mode("MultipartonInteractions:processLevel");
439 
440  // Parameters of rescattering description.
441  allowRescatter = flag("MultipartonInteractions:allowRescatter");
442  allowDoubleRes = flag("MultipartonInteractions:allowDoubleRescatter");
443  rescatterMode = mode("MultipartonInteractions:rescatterMode");
444  ySepResc = parm("MultipartonInteractions:ySepRescatter");
445  deltaYResc = parm("MultipartonInteractions:deltaYRescatter");
446 
447  // Rescattering not yet implemented for x-dependent impact profile.
448  if (bProfile == 4) allowRescatter = false;
449 
450  // A global recoil FSR stategy restricts rescattering.
451  globalRecoilFSR = flag("TimeShower:globalRecoil");
452  nMaxGlobalRecoilFSR = mode("TimeShower:nMaxGlobalRecoil");
453 
454  // Various other parameters.
455  nQuarkIn = mode("MultipartonInteractions:nQuarkIn");
456  nSample = mode("MultipartonInteractions:nSample");
457 
458  // Optional dampening at small pT's when large multiplicities.
459  enhanceScreening = mode("MultipartonInteractions:enhanceScreening");
460 
461  // Parameters for diffractive systems.
462  sigmaPomP = parm("Diffraction:sigmaRefPomP");
463  mPomP = parm("Diffraction:mRefPomP");
464  pPomP = parm("Diffraction:mPowPomP");
465  mMinPertDiff = parm("Diffraction:mMinPert");
466  bSelHard = mode("Diffraction:bSelHard");
467 
468  // Beam particles might not be found from the usual positions.
469  beamOffset = 0;
470 
471  // Possibility to allow user veto of MPI.
472  canVetoMPI = (userHooksPtr != 0) ? userHooksPtr->canVetoMPIEmission()
473  : false;
474 
475  // Possibility to set parton vertex information.
476  doPartonVertex = flag("PartonVertex:setVertex") && (partonVertexPtr != 0);
477 
478  // Some common combinations for double Gaussian, as shorthand.
479  if (bProfile == 2) {
480  fracA = pow2(1. - coreFraction);
481  fracB = 2. * coreFraction * (1. - coreFraction);
482  fracC = pow2(coreFraction);
483  radius2B = 0.5 * (1. + pow2(coreRadius));
484  radius2C = pow2(coreRadius);
485 
486  // Some common combinations for exp(b^pow), as shorthand.
487  } else if (bProfile == 3) {
488  hasLowPow = (expPow < 2.);
489  expRev = 2. / expPow - 1.;
490  }
491  enhanceBavg = 1.;
492 
493  // Initialize alpha_strong generation.
494  alphaS.init( alphaSvalue, alphaSorder, alphaSnfmax, false);
495  double Lambda3 = alphaS.Lambda3();
496 
497  // Initialize alphaEM generation.
498  alphaEM.init( alphaEMorder, settingsPtr);
499 
500  // Attach matrix-element calculation objects.
501  sigma2gg.init( 0, processLevel, infoPtr, beamAPtr, beamBPtr);
502  sigma2qg.init( 1, processLevel, infoPtr, beamAPtr, beamBPtr);
503  sigma2qqbarSame.init( 2, processLevel, infoPtr, beamAPtr, beamBPtr);
504  sigma2qq.init( 3, processLevel, infoPtr, beamAPtr, beamBPtr);
505 
506  // Calculate invariant mass of system.
507  eCM = infoPtr->eCM();
508  sCM = eCM * eCM;
509  mMaxPertDiff = eCM;
510  eCMsave = eCM;
511 
512  // Allow for variable collision energies.
513  doVarEcm = flag("Beams:allowVariableEnergy");
514  if (iDiffSys > 0 || hasGamma) doVarEcm = false;
515 
516  // Limits on invariant mass of gm+gm system.
517  mGmGmMin = parm("Photon:Wmin");
518  mGmGmMax = parm("Photon:Wmax");
519  if ( mGmGmMax < mGmGmMin ) mGmGmMax = eCM;
520 
521  // Get the total inelastic and nondiffractive cross section.
522  // Ensure correct cross sections for VMD photons.
523  if (infoPtr->isVMDstateA() || infoPtr->isVMDstateB()) {
524  int idVMDA = infoPtr->isVMDstateA() ? 22 : infoPtr->idA();
525  int idVMDB = infoPtr->isVMDstateB() ? 22 : infoPtr->idB();
526  sigmaTotPtr->calc(idVMDA, idVMDB, infoPtr->eCM());
527  }
528  // Ensure correct cross sections also for non-VMD photon beams.
529  else if ( (isGammaGamma || isGammaHadron || isHadronGamma) && !hasGamma)
530  sigmaTotPtr->calc(infoPtr->idA(), infoPtr->idB(), infoPtr->eCM());
531  if (!sigmaTotPtr->hasSigmaTot()) return false;
532  bool isNonDiff = (iDiffSys == 0);
533  sigmaND = sigmaTotPtr->sigmaND();
534  double sigmaMaxViol = 0.;
535 
536  // Output initialization info - first part.
537  bool showMPI = flag("Init:showMultipartonInteractions");
538  if (showMPI) {
539  cout << "\n *------- PYTHIA Multiparton Interactions Initialization "
540  << "---------* \n"
541  << " | "
542  << " | \n";
543  if (!doVarEcm && isNonDiff && !hasGamma)
544  cout << " | sigmaNonDiffractive = " << setprecision(2)
545  << ((sigmaND > 1.) ? fixed : scientific) << setw(8) << sigmaND
546  << " mb | \n";
547  else if (doVarEcm)
548  cout << " | non-diffractive "
549  << " | \n";
550  else if (iDiffSys == 1)
551  cout << " | diffraction XB "
552  << " | \n";
553  else if (iDiffSys == 2)
554  cout << " | diffraction AX "
555  << " | \n";
556  else if (iDiffSys == 3)
557  cout << " | diffraction AXB "
558  << " | \n";
559  else if ( hasGamma && isGammaGamma )
560  cout << " | A+B -> gamma+gamma -> X "
561  << " | \n";
562  else if ( hasGamma && isGammaHadron )
563  cout << " | A+B -> gamma+B -> X "
564  << " | \n";
565  else if ( hasGamma && isHadronGamma )
566  cout << " | A+B -> A+gamma -> X "
567  << " | \n";
568  cout << " | "
569  << " | \n";
570  }
571 
572  // Normally fixed collision cm energy.
573  nStep = 1;
574  eStepMin = 1.;
575  eStepMax = 1.;
576  eStepSize = 1.;
577  // For variable-energy beams cover range of cm energies.
578  if (doVarEcm || iDiffSys > 0 || hasGamma) {
579  if (doVarEcm) {
580  eStepMin = parm("Beams:eMinPert");
581  eStepMax = eCM;
582  // For diffraction cover range of diffractive masses.
583  } else if (iDiffSys > 0) {
584  eStepMin = mMinPertDiff;
585  eStepMax = mMaxPertDiff;
586  // For photons from lepton cover range of gm+gm invariant masses.
587  } else {
588  eStepMin = mGmGmMin;
589  eStepMax = mGmGmMax;
590  }
591  nStep = min( 20, int( 2. + 2. * log( eStepMax / eStepMin)) );
592  eStepSize = log( eStepMax / eStepMin) / (nStep - 1.);
593  }
594 
595  // Loop over masses for which to initialize generation.
596  for (int iStep = 0; iStep < nStep; ++iStep) {
597  if (nStep > 1) {
598  eCM = eStepMin * pow( eStepMax / eStepMin, iStep / (nStep - 1.) );
599  sCM = eCM * eCM;
600 
601  // Nondiffractive cross section at current mass.
602  if (doVarEcm) {
603  sigmaTotPtr->calc( beamAPtr->id(), beamBPtr->id(), eCM );
604  sigmaND = sigmaTotPtr->sigmaND();
605  if (showMPI) cout << " | collision energy = " << scientific
606  << setprecision(2) << setw(8) << eCM << " GeV and sigmaNorm = "
607  << ((sigmaND > SIGMAMBLIMIT) ? fixed : scientific)
608  << setw(8) << sigmaND << " mb | \n";
609 
610  // MPI for diffractive events. Rescale Pom/p flux to use for Pom/gamma.
611  } else if (hasPomeronBeams) {
612  double gamPomRatio = 1.;
613  if (hasGamma) {
614  sigmaTotPtr->calc(22, 2212, eCM);
615  double sigGamP = sigmaTotPtr->sigmaTot();
616  sigmaTotPtr->calc(2212, 2212, eCM);
617  double sigPP = sigmaTotPtr->sigmaTot();
618  gamPomRatio = sigGamP / sigPP;
619  }
620  sigmaND = gamPomRatio * sigmaPomP * pow( eCM / mPomP, pPomP);
621  if (showMPI) cout << " | diffractive mass = " << scientific
622  << setprecision(2) << setw(8) << eCM << " GeV and sigmaNorm = "
623  << ((sigmaND > SIGMAMBLIMIT) ? fixed : scientific)
624  << setw(8) << sigmaND << " mb | \n";
625 
626  // Keep track of pomeron momentum fraction.
627  if ( beamAPtr->id() == 990 && beamBPtr->id() == 990 ) {
628  beamAPtr->xPom(eCM/eCMsave);
629  beamBPtr->xPom(eCM/eCMsave);
630  }
631  else if ( beamAPtr->id() == 990 )
632  beamAPtr->xPom(pow2(eCM/eCMsave));
633  else if ( beamBPtr->id() == 990 )
634  beamBPtr->xPom(pow2(eCM/eCMsave));
635 
636  // MPI with photons from leptons.
637  } else {
638 
639  // Hadron-photon case.
640  if ( isHadronGamma ) {
641  sigmaTotPtr->calc( beamAPtr->id(), 22, eCM );
642  sigmaND = sigmaTotPtr->sigmaND();
643  if (showMPI) cout << " | hadron+gamma eCM = " << scientific
644  << setprecision(2) << setw(8) << eCM << " GeV and sigmaNorm = "
645  << ((sigmaND > SIGMAMBLIMIT) ? fixed : scientific)
646  << setw(8) << sigmaND << " mb | \n";
647 
648  // Photon-hadron case.
649  } else if ( isGammaHadron ) {
650  sigmaTotPtr->calc( 22, beamBPtr->id(), eCM );
651  sigmaND = sigmaTotPtr->sigmaND();
652  if (showMPI) cout << " | gamma+hadron eCM = " << scientific
653  << setprecision(2) << setw(8) << eCM << " GeV and sigmaNorm = "
654  << ((sigmaND > SIGMAMBLIMIT) ? fixed : scientific)
655  << setw(8) << sigmaND << " mb | \n";
656 
657  // Photon-photon case.
658  } else {
659  sigmaTotPtr->calc( 22, 22, eCM );
660  sigmaND = sigmaTotPtr->sigmaND();
661  if (showMPI) cout << " | gamma+gamma eCM = " << scientific
662  << setprecision(2) << setw(8) << eCM << " GeV and sigmaNorm = "
663  << ((sigmaND > SIGMAMBLIMIT) ? fixed : scientific)
664  << setw(8) << sigmaND << " mb | \n";
665  }
666  }
667 
668  }
669 
670  // Set current pT0 scale according to chosed parametrization.
671  if (pT0paramMode == 0) pT0 = pT0Ref * pow(eCM / ecmRef, ecmPow);
672  else pT0 = pT0Ref + ecmPow * log (eCM / ecmRef);
673 
674  // The pT0 value may need to be decreased, if sigmaInt < sigmaND.
675  double pT4dSigmaMaxBeg = 0.;
676  for ( ; ; ) {
677 
678  // Derived pT kinematics combinations.
679  pT20 = pT0*pT0;
680  pT2min = pTmin*pTmin;
681  pTmax = 0.5*eCM;
682  pT2max = pTmax*pTmax;
683  pT20R = RPT20 * pT20;
684  pT20minR = pT2min + pT20R;
685  pT20maxR = pT2max + pT20R;
686  pT20min0maxR = pT20minR * pT20maxR;
687  pT2maxmin = pT2max - pT2min;
688 
689  // Provide upper estimate of interaction rate d(Prob)/d(pT2).
690  upperEnvelope();
691 
692  // Setup binning in b for x-dependent matter profile.
693  if (bProfile == 4) {
694  sigmaIntWgt.resize(XDEP_BBIN);
695  sigmaSumWgt.resize(XDEP_BBIN);
696  bstepNow = XDEP_BSTEP;
697  }
698 
699  // Integrate the parton-parton interaction cross section.
700  pT4dSigmaMaxBeg = pT4dSigmaMax;
701  jetCrossSection();
702 
703  // If the overlap-weighted cross section has not fallen below
704  // cutoff, then increase bin size in b and reintegrate.
705  while (bProfile == 4
706  && sigmaIntWgt[XDEP_BBIN - 1] > XDEP_CUTOFF * sigmaInt) {
707  bstepNow += XDEP_BSTEPINC;
708  jetCrossSection();
709  }
710 
711  // Sufficiently big SigmaInt or reduce pT0; maybe also pTmin.
712  if (sigmaInt > SIGMASTEP * sigmaND) break;
713  if (showMPI) cout << fixed << setprecision(2) << " | pT0 = "
714  << setw(5) << pT0 << " gives sigmaInteraction = " << setw(8)
715  << ((sigmaInt > SIGMAMBLIMIT) ? fixed : scientific) << sigmaInt
716  << " mb: rejected | \n";
717  if (pTmin > pT0) pTmin *= PT0STEP;
718  pT0 *= PT0STEP;
719 
720  // Give up if pT0 and pTmin fall too low.
721  if ( max(pT0, pTmin) < max(PT0MIN, Lambda3) ) {
722  infoPtr->errorMsg("Error in MultipartonInteractions::init:"
723  " failed to find acceptable pT0 and pTmin");
724  infoPtr->setTooLowPTmin(true);
725  return false;
726  }
727  }
728 
729  // Output for accepted pT0.
730  if (showMPI) cout << fixed << setprecision(2) << " | pT0 = "
731  << setw(5) << pT0 << " gives sigmaInteraction = "<< setw(8)
732  << ((sigmaInt > SIGMAMBLIMIT) ? fixed : scientific) << sigmaInt
733  << " mb: accepted | \n";
734 
735  // Calculate factor relating matter overlap and interaction rate.
736  overlapInit();
737 
738  // Maximum violation relative to first estimate.
739  sigmaMaxViol = max( sigmaMaxViol, pT4dSigmaMax / pT4dSigmaMaxBeg);
740 
741  // Save values calculated.
742  if (nStep > 1) {
743  pT0Save[iStep] = pT0;
744  pT4dSigmaMaxSave[iStep] = pT4dSigmaMax;
745  pT4dProbMaxSave[iStep] = pT4dProbMax;
746  sigmaIntSave[iStep] = sigmaInt;
747  for (int j = 0; j <= 100; ++j) sudExpPTSave[iStep][j] = sudExpPT[j];
748  zeroIntCorrSave[iStep] = zeroIntCorr;
749  normOverlapSave[iStep] = normOverlap;
750  kNowSave[iStep] = kNow;
751  bAvgSave[iStep] = bAvg;
752  bDivSave[iStep] = bDiv;
753  probLowBSave[iStep] = probLowB;
754  fracAhighSave[iStep] = fracAhigh;
755  fracBhighSave[iStep] = fracBhigh;
756  fracChighSave[iStep] = fracBhigh;
757  fracABChighSave[iStep] = fracABChigh;
758  cDivSave[iStep] = cDiv;
759  cMaxSave[iStep] = cMax;
760  }
761 
762  // End of loop over energies or diffractive/invariant gamma+gamma masses.
763  }
764 
765  // Reset pomeron momentum fraction.
766  beamAPtr->xPom();
767  beamBPtr->xPom();
768 
769  // Output details for x-dependent matter profile.
770  if (bProfile == 4 && showMPI)
771  cout << " | "
772  << " | \n"
773  << fixed << setprecision(2)
774  << " | x-dependent matter profile: a1 = " << a1 << ", "
775  << "a0 = " << a0now * XDEP_SMB2FM << ", bStep = "
776  << bstepNow << " | \n";
777 
778  // End initialization printout.
779  if (showMPI) cout << " | "
780  << " | \n"
781  << " *------- End PYTHIA Multiparton Interactions Initialization"
782  << " -----* " << endl;
783 
784  // Amount of violation from upperEnvelope to jetCrossSection.
785  if (sigmaMaxViol > 1.) {
786  ostringstream osWarn;
787  osWarn << "by factor " << fixed << setprecision(3) << sigmaMaxViol;
788  infoPtr->errorMsg("Warning in MultipartonInteractions::init:"
789  " maximum increased", osWarn.str());
790  }
791 
792  // Reset statistics.
793  SigmaMultiparton* dSigma;
794  for (int i = 0; i < 4; ++i) {
795  if (i == 0) dSigma = &sigma2gg;
796  else if (i == 1) dSigma = &sigma2qg;
797  else if (i == 2) dSigma = &sigma2qqbarSame;
798  else dSigma = &sigma2qq;
799  int nProc = dSigma->nProc();
800  for (int iProc = 0; iProc < nProc; ++iProc)
801  nGen[ dSigma->codeProc(iProc) ] = 0;
802  }
803 
804  // Additional setup for x-dependent matter profile.
805  if (bProfile == 4) {
806  sigmaIntWgt.clear();
807  sigmaSumWgt.clear();
808  }
809  // No preselection of sea/valence content and initialise a0.
810  vsc1 = 0;
811  vsc2 = 0;
812 
813  // Done.
814  return true;
815 }
816 
817 //--------------------------------------------------------------------------
818 
819 // Reset impact parameter choice and update the CM energy.
820 // Sometimes also interpolate parameters to current CM energy.
821 
822 void MultipartonInteractions::reset( ) {
823 
824  // Reset impact parameter choice.
825  bIsSet = false;
826  bSetInFirst = false;
827 
828  // Update CM energy. Done if not diffraction and not new energy.
829  eCM = infoPtr->eCM();
830  sCM = eCM * eCM;
831  if (nStep == 1 || abs( eCM / eCMsave - 1.) < ECMDEV) return;
832 
833  // For variable-energy collisions, including photons from leptons,
834  // calculate sigmaND at updated collision CM energy.
835  if (doVarEcm || hasGamma) {
836  sigmaTotPtr->calc( beamAPtr->id(), beamBPtr->id(), eCM );
837  sigmaND = sigmaTotPtr->sigmaND();
838  // Set fictitious Pomeron-proton cross section for diffractive system.
839  } else sigmaND = sigmaPomP * pow( eCM / mPomP, pPomP);
840 
841  // Current interpolation point.
842  eCMsave = eCM;
843  eStepSave = log(eCM / eStepMin) / eStepSize;
844  iStepFrom = max( 0, min( nStep - 2, int( eStepSave) ) );
845  iStepTo = iStepFrom + 1;
846  eStepTo = max( 0., min( 1., eStepSave - iStepFrom) );
847  eStepFrom = 1. - eStepTo;
848 
849  // Update pT0 and combinations derived from it.
850  pT0 = eStepFrom * pT0Save[iStepFrom]
851  + eStepTo * pT0Save[iStepTo];
852  pT20 = pT0*pT0;
853  pT2min = pTmin*pTmin;
854  pTmax = 0.5*eCM;
855  pT2max = pTmax*pTmax;
856  pT20R = RPT20 * pT20;
857  pT20minR = pT2min + pT20R;
858  pT20maxR = pT2max + pT20R;
859  pT20min0maxR = pT20minR * pT20maxR;
860  pT2maxmin = pT2max - pT2min;
861 
862  // Update other parameters used in pT choice.
863  pT4dSigmaMax = eStepFrom * pT4dSigmaMaxSave[iStepFrom]
864  + eStepTo * pT4dSigmaMaxSave[iStepTo];
865  pT4dProbMax = eStepFrom * pT4dProbMaxSave[iStepFrom]
866  + eStepTo * pT4dProbMaxSave[iStepTo];
867  sigmaInt = eStepFrom * sigmaIntSave[iStepFrom]
868  + eStepTo * sigmaIntSave[iStepTo];
869  for (int j = 0; j <= 100; ++j)
870  sudExpPT[j] = eStepFrom * sudExpPTSave[iStepFrom][j]
871  + eStepTo * sudExpPTSave[iStepTo][j];
872 
873  // Update parameters related to the impact-parameter picture.
874  zeroIntCorr = eStepFrom * zeroIntCorrSave[iStepFrom]
875  + eStepTo * zeroIntCorrSave[iStepTo];
876  normOverlap = eStepFrom * normOverlapSave[iStepFrom]
877  + eStepTo * normOverlapSave[iStepTo];
878  kNow = eStepFrom * kNowSave[iStepFrom]
879  + eStepTo * kNowSave[iStepTo];
880  bAvg = eStepFrom * bAvgSave[iStepFrom]
881  + eStepTo * bAvgSave[iStepTo];
882  bDiv = eStepFrom * bDivSave[iStepFrom]
883  + eStepTo * bDivSave[iStepTo];
884  probLowB = eStepFrom * probLowBSave[iStepFrom]
885  + eStepTo * probLowBSave[iStepTo];
886  fracAhigh = eStepFrom * fracAhighSave[iStepFrom]
887  + eStepTo * fracAhighSave[iStepTo];
888  fracBhigh = eStepFrom * fracBhighSave[iStepFrom]
889  + eStepTo * fracBhighSave[iStepTo];
890  fracChigh = eStepFrom * fracChighSave[iStepFrom]
891  + eStepTo * fracChighSave[iStepTo];
892  fracABChigh = eStepFrom * fracABChighSave[iStepFrom]
893  + eStepTo * fracABChighSave[iStepTo];
894  cDiv = eStepFrom * cDivSave[iStepFrom]
895  + eStepTo * cDivSave[iStepTo];
896  cMax = eStepFrom * cMaxSave[iStepFrom]
897  + eStepTo * cMaxSave[iStepTo];
898 
899 }
900 
901 //--------------------------------------------------------------------------
902 
903 // Select first = hardest pT in nondiffractive process.
904 // Requires separate treatment at low and high b values.
905 
906 void MultipartonInteractions::pTfirst() {
907 
908  // Pick impact parameter and thereby interaction rate enhancement.
909  // This is not used for the x-dependent matter profile, which
910  // instead uses trial interactions.
911  if (bProfile == 4) isAtLowB = false;
912  else overlapFirst();
913  bSetInFirst = true;
914  double WTacc;
915 
916  // At low b values evolve downwards with Sudakov.
917  if (isAtLowB) {
918  pT2 = pT2max;
919  do {
920 
921  // Pick a pT using a quick-and-dirty cross section estimate.
922  pT2 = fastPT2(pT2);
923 
924  // If fallen below lower cutoff then need to restart at top.
925  if (pT2 < pT2min) {
926  pT2 = pT2max;
927  WTacc = 0.;
928 
929  // Else pick complete kinematics and evaluate cross-section correction.
930  } else {
931  WTacc = sigmaPT2scatter(true) / dSigmaApprox;
932  if (WTacc > WTACCWARN) infoPtr->errorMsg("Warning in "
933  "MultipartonInteractions::pTfirst: weight above unity");
934  }
935 
936  // Loop until acceptable pT and acceptable kinematics.
937  } while (WTacc < rndmPtr->flat() || !dSigmaDtSel->final2KinMPI());
938 
939  // At high b values make preliminary pT choice without Sudakov factor.
940  } else {
941 
942  while (true) {
943  do {
944  pT2 = pT20min0maxR / (pT20minR + rndmPtr->flat() * pT2maxmin) - pT20R;
945 
946  // Evaluate upper estimate of cross section for this pT2 choice.
947  dSigmaApprox = pT4dSigmaMax / pow2(pT2 + pT20R);
948 
949  // Pick complete kinematics and evaluate cross-section correction.
950  WTacc = sigmaPT2scatter(true) / dSigmaApprox;
951 
952  // Evaluate and include Sudakov factor.
953  if (bProfile != 4) WTacc *= sudakov( pT2, enhanceB);
954 
955  // Warn for weight above unity
956  if (WTacc > WTACCWARN) infoPtr->errorMsg("Warning in "
957  "MultipartonInteractions::pTfirst: weight above unity");
958 
959  // Loop until acceptable pT and acceptable kinematics.
960  } while (WTacc < rndmPtr->flat() || !dSigmaDtSel->final2KinMPI());
961 
962  // For x-dependent matter profile, use trial interactions to
963  // generate Sudakov, otherwise done.
964  if (bProfile != 4) break;
965  else {
966  // Save details of the original hard interaction.
967  pT2Save = pT2;
968  id1Save = id1;
969  id2Save = id2;
970  x1Save = x1;
971  x2Save = x2;
972  sHatSave = sHat;
973  tHatSave = tHat;
974  uHatSave = uHat;
975  alpSsave = alpS;
976  alpEMsave = alpEM;
977  pT2FacSave = pT2Fac;
978  pT2RenSave = pT2Ren;
979  xPDF1nowSave = xPDF1now;
980  xPDF2nowSave = xPDF2now;
981  // Save accepted kinematics and pointer to SigmaProcess.
982  dSigmaDtSel->saveKin();
983  dSigmaDtSelSave = dSigmaDtSel;
984 
985  // Put x1, x2 information into beam pointers to get correct
986  // PDF rescaling in trial interaction (for hard process, can
987  // be sea or valence, not companion).
988  beamAPtr->append( 0, id1, x1);
989  beamAPtr->xfISR( 0, id1, x1, pT2Fac * pT2Fac);
990  vsc1 = beamAPtr->pickValSeaComp();
991  beamBPtr->append( 0, id2, x2);
992  beamBPtr->xfISR( 0, id2, x2, pT2Fac * pT2Fac);
993  vsc2 = beamBPtr->pickValSeaComp();
994 
995  // Pick b according to O(b, x1, x2).
996  double w1 = XDEP_A1 + a1 * log(1. / x1);
997  double w2 = XDEP_A1 + a1 * log(1. / x2);
998  double fac = a02now * (w1 * w1 + w2 * w2);
999  double expb2 = 1.;
1000  if ( userHooksPtr && userHooksPtr->canSetImpactParameter() ) {
1001  bNow = userHooksPtr->doSetImpactParameter() * bAvg;
1002  b2now = pow2(bNow);
1003  expb2 = exp(-b2now / fac);
1004  } else {
1005  expb2 = rndmPtr->flat();
1006  b2now = - fac * log(expb2);
1007  bNow = sqrt(b2now);
1008  }
1009 
1010  // Enhancement factor for the hard process and overestimate
1011  // for fastPT2. Note that existing framework has a (1. / sigmaND)
1012  // present.
1013  enhanceB = sigmaND / M_PI / fac * expb2;
1014  enhanceBmax = sigmaND / 2. / M_PI / a02now *
1015  exp( -b2now / 2. / a2max );
1016 
1017  // Trial interaction with dummy event.
1018  Event evDummy;
1019  double pTtrial = pTnext(pTmax, pTmin, evDummy);
1020 
1021  // Restore beams.
1022  beamAPtr->clear();
1023  beamBPtr->clear();
1024 
1025  // Accept if fallen beneath factorisation scale.
1026  if (pTtrial < sqrt(pT2FacSave)) {
1027  // Restore previous values and original sigma.
1028  swap(pT2, pT2Save);
1029  swap(pT2Fac, pT2FacSave);
1030  swap(pT2Ren, pT2RenSave);
1031  swap(id1, id1Save);
1032  swap(id2, id2Save);
1033  swap(x1, x1Save);
1034  swap(x2, x2Save);
1035  swap(sHat, sHatSave);
1036  swap(tHat, tHatSave);
1037  swap(uHat, uHatSave);
1038  swap(alpS, alpSsave);
1039  swap(alpEM, alpEMsave);
1040  swap(xPDF1now, xPDF1nowSave);
1041  swap(xPDF2now, xPDF2nowSave);
1042  if (dSigmaDtSel == dSigmaDtSelSave) dSigmaDtSel->swapKin();
1043  else swap(dSigmaDtSel, dSigmaDtSelSave);
1044 
1045  // Accept.
1046  bNow /= bAvg;
1047  bIsSet = true;
1048  break;
1049  }
1050  } // if (bProfile == 4)
1051  } // while (true)
1052 
1053  // End handling for high b.
1054  }
1055 
1056 }
1057 
1058 //--------------------------------------------------------------------------
1059 
1060 // Set up kinematics for first = hardest pT in nondiffractive process.
1061 
1062 void MultipartonInteractions::setupFirstSys( Event& process) {
1063 
1064  // Last beam-status particles. Offset relative to normal beam locations.
1065  int sizeProc = process.size();
1066  int nBeams = 3;
1067  for (int i = 3; i < sizeProc; ++i)
1068  if (process[i].statusAbs() < 20) nBeams = i + 1;
1069  int nOffset = nBeams - 3;
1070 
1071  // Remove any partons of previous failed interactions.
1072  if (sizeProc > nBeams) {
1073  process.popBack( sizeProc - nBeams);
1074  process.initColTag();
1075  }
1076 
1077  // Entries 3 and 4, now to be added, come from 1 and 2.
1078  process[1 + nOffset].daughter1(3 + nOffset);
1079  process[2 + nOffset].daughter1(4 + nOffset);
1080 
1081  // Negate beam status, if not already done. (Case with offset beams.)
1082  process[1 + nOffset].statusNeg();
1083  process[2 + nOffset].statusNeg();
1084 
1085  // Loop over four partons and offset info relative to subprocess itself.
1086  int colOffset = process.lastColTag();
1087  for (int i = 1; i <= 4; ++i) {
1088  Particle parton = dSigmaDtSel->getParton(i);
1089  if (i <= 2) parton.status(-21);
1090  else parton.status(23);
1091  if (i <= 2) parton.mothers( i + nOffset, 0);
1092  else parton.mothers( 3 + nOffset, 4 + nOffset);
1093  if (i <= 2) parton.daughters( 5 + nOffset, 6 + nOffset);
1094  else parton.daughters( 0, 0);
1095  int col = parton.col();
1096  if (col > 0) parton.col( col + colOffset);
1097  int acol = parton.acol();
1098  if (acol > 0) parton.acol( acol + colOffset);
1099 
1100  // Put the partons into the event record.
1101  process.append(parton);
1102  }
1103  if (doPartonVertex)
1104  partonVertexPtr->vertexMPI( sizeProc, 4, bNow, process);
1105 
1106  // Set scale from which to begin evolution.
1107  process.scale( sqrt(pT2Fac) );
1108 
1109  // Info on subprocess - specific to mimimum-bias events.
1110  string nameSub = dSigmaDtSel->name();
1111  int codeSub = dSigmaDtSel->code();
1112  int nFinalSub = dSigmaDtSel->nFinal();
1113  double pTMPI = dSigmaDtSel->pTMPIFin();
1114  infoPtr->setSubType( iDiffSys, nameSub, codeSub, nFinalSub);
1115  if (iDiffSys == 0) infoPtr->setTypeMPI( codeSub, pTMPI, 0, 0,
1116  enhanceB / zeroIntCorr);
1117 
1118  // Further standard info on process.
1119  infoPtr->setPDFalpha( iDiffSys, id1, id2, x1, x2,
1120  (id1 == 21 ? 4./9. : 1.) * xPDF1now, (id2 == 21 ? 4./9. : 1.) * xPDF2now,
1121  pT2Fac, alpEM, alpS, pT2Ren, 0.);
1122  double m3 = dSigmaDtSel->m(3);
1123  double m4 = dSigmaDtSel->m(4);
1124  double theta = dSigmaDtSel->thetaMPI();
1125  double phi = dSigmaDtSel->phiMPI();
1126  infoPtr->setKin( iDiffSys, id1, id2, x1, x2, sHat, tHat, uHat, sqrt(pT2),
1127  m3, m4, theta, phi);
1128 
1129 }
1130 
1131 //--------------------------------------------------------------------------
1132 
1133 // Find whether to limit maximum scale of emissions.
1134 
1135 bool MultipartonInteractions::limitPTmax( Event& event) {
1136 
1137  // User-set cases.
1138  if (pTmaxMatch == 1) return true;
1139  if (pTmaxMatch == 2) return false;
1140 
1141  // Always restrict SoftQCD processes.
1142  if (infoPtr->isNonDiffractive() || infoPtr->isDiffractiveA()
1143  || infoPtr->isDiffractiveB() || infoPtr->isDiffractiveC() )
1144  return true;
1145 
1146  // Look if only quarks (u, d, s, c, b), gluons and photons in final state.
1147  bool onlyQGP1 = true;
1148  bool onlyQGP2 = true;
1149  double scaleLimit1 = 0.;
1150  double scaleLimit2 = 0.;
1151  int n21 = 0;
1152  int iBegin = 5 + beamOffset;
1153  for (int i = iBegin; i < event.size(); ++i) {
1154  if (event[i].status() == -21) ++n21;
1155  else if (n21 == 0) {
1156  scaleLimit1 += 0.5 * event[i].pT();
1157  int idAbs = event[i].idAbs();
1158  if (idAbs > 5 && idAbs != 21 && idAbs != 22) onlyQGP1 = false;
1159  } else if (n21 == 2) {
1160  scaleLimit2 += 0.5 * event[i].pT();
1161  int idAbs = event[i].idAbs();
1162  if (idAbs > 5 && idAbs != 21 && idAbs != 22) onlyQGP2 = false;
1163  }
1164  }
1165 
1166  // If two hard interactions then limit if one only contains q/g/gamma.
1167  scaleLimitPTsave = (n21 == 2) ? min( scaleLimit1, scaleLimit2) : scaleLimit1;
1168  bool onlyQGP = (n21 == 2) ? (onlyQGP1 || onlyQGP2) : onlyQGP1;
1169  return (onlyQGP);
1170 
1171 }
1172 
1173 //--------------------------------------------------------------------------
1174 
1175 // Select next pT in downwards evolution.
1176 
1177 double MultipartonInteractions::pTnext( double pTbegAll, double pTendAll,
1178  Event& event) {
1179 
1180  // Initial values.
1181  bool pickRescatter, acceptKin;
1182  double dSigmaScatter, dSigmaRescatter, WTacc;
1183  double pT2end = pow2( max(pTmin, pTendAll) );
1184 
1185  // With the x-dependent matter profile, and minimum bias or diffraction,
1186  // it is possible to reuse values that have been stored during the trial
1187  // interactions for a slight speedup.
1188  // bIsSet is false during trial interactions, counter 21 in case partonLevel
1189  // is retried and counter 22 for the first pass through partonLevel.
1190  if (bProfile == 4 && bIsSet && bSetInFirst && infoPtr->getCounter(21) == 1
1191  && infoPtr->getCounter(22) == 1) {
1192  if (pT2Save < pT2end) return 0.;
1193  pT2 = pT2Save;
1194  pT2Fac = pT2FacSave;
1195  pT2Ren = pT2RenSave;
1196  id1 = id1Save;
1197  id2 = id2Save;
1198  x1 = x1Save;
1199  x2 = x2Save;
1200  sHat = sHatSave;
1201  tHat = tHatSave;
1202  uHat = uHatSave;
1203  alpS = alpSsave;
1204  alpEM = alpEMsave;
1205  xPDF1now = xPDF1nowSave;
1206  xPDF2now = xPDF2nowSave;
1207  if (dSigmaDtSel == dSigmaDtSelSave) dSigmaDtSel->swapKin();
1208  else dSigmaDtSel = dSigmaDtSelSave;
1209  return sqrt(pT2);
1210  }
1211 
1212  // Do not allow rescattering while still FSR with global recoil.
1213  bool allowRescatterNow = allowRescatter;
1214  if (globalRecoilFSR && partonSystemsPtr->sizeOut(0) <= nMaxGlobalRecoilFSR)
1215  allowRescatterNow = false;
1216 
1217  // Initial pT2 value.
1218  pT2 = pow2(pTbegAll);
1219 
1220  // Find the set of already scattered partons on the two sides.
1221  if (allowRescatterNow) findScatteredPartons( event);
1222 
1223  // Pick a pT2 using a quick-and-dirty cross section estimate.
1224  do {
1225  do {
1226  pT2 = fastPT2(pT2);
1227  if (pT2 < pT2end) return 0.;
1228 
1229  // Initial values: no rescattering.
1230  i1Sel = 0;
1231  i2Sel = 0;
1232  dSigmaSum = 0.;
1233  pickRescatter = false;
1234 
1235  // Pick complete kinematics and evaluate interaction cross-section.
1236  dSigmaScatter = sigmaPT2scatter(false);
1237 
1238  // Also cross section from rescattering if allowed.
1239  dSigmaRescatter = (allowRescatterNow) ? sigmaPT2rescatter( event) : 0.;
1240 
1241  // Normalize to dSigmaApprox, which was set in fastPT2 above.
1242  WTacc = (dSigmaScatter + dSigmaRescatter) / dSigmaApprox;
1243  if (WTacc > WTACCWARN) infoPtr->errorMsg("Warning in "
1244  "MultipartonInteractions::pTnext: weight above unity");
1245 
1246  // Idea suggested by Gosta Gustafson: increased screening in events
1247  // with large activity can be simulated by pT0_eff = sqrt(n) * pT0.
1248  if (enhanceScreening > 0) {
1249  int nSysNow = infoPtr->nMPI() + 1;
1250  if (enhanceScreening == 2) nSysNow += infoPtr->nISR();
1251  double WTscreen = pow2( (pT2 + pT20) / (pT2 + nSysNow * pT20) );
1252  WTacc *= WTscreen;
1253  }
1254 
1255  // x-dependent matter profile overlap weighting.
1256  if (bProfile == 4) {
1257  double w1 = XDEP_A1 + a1 * log(1. / x1);
1258  double w2 = XDEP_A1 + a1 * log(1. / x2);
1259  double fac = a02now * (w1 * w1 + w2 * w2);
1260  // Correct enhancement factor and weight
1261  enhanceBnow = sigmaND / M_PI / fac * exp( - b2now / fac);
1262  double oWgt = enhanceBnow / enhanceBmax;
1263  if (oWgt > 1.0000000001) infoPtr->errorMsg("Warning in Multiparton"
1264  "Interactions::pTnext: overlap weight above unity");
1265  WTacc *= oWgt;
1266  }
1267 
1268  // Decide whether to keep the event based on weight.
1269  } while (WTacc < rndmPtr->flat());
1270 
1271  // When rescattering possible: new interaction or rescattering?
1272  if (allowRescatterNow) {
1273  pickRescatter = (i1Sel > 0 || i2Sel > 0);
1274 
1275  // Restore kinematics for selected scattering/rescattering.
1276  id1 = id1Sel;
1277  id2 = id2Sel;
1278  x1 = x1Sel;
1279  x2 = x2Sel;
1280  sHat = sHatSel;
1281  tHat = tHatSel;
1282  uHat = uHatSel;
1283  sigma2Sel->sigma( id1, id2, x1, x2, sHat, tHat, uHat, alpS, alpEM,
1284  true, pickOtherSel);
1285  }
1286 
1287  // Pick one of the possible channels summed above.
1288  dSigmaDtSel = sigma2Sel->sigmaSel();
1289  if (sigma2Sel->swapTU()) swap( tHat, uHat);
1290 
1291  // Decide to keep event based on kinematics (normally always OK).
1292  // Rescattering: need to provide incoming four-vectors and masses.
1293  if (pickRescatter) {
1294  Vec4 p1Res = (i1Sel == 0) ? 0.5 * eCM * x1Sel * Vec4( 0., 0., 1., 1.)
1295  : event[i1Sel].p();
1296  Vec4 p2Res = (i2Sel == 0) ? 0.5 * eCM * x2Sel * Vec4( 0., 0., -1., 1.)
1297  : event[i2Sel].p();
1298  double m1Res = (i1Sel == 0) ? 0. : event[i1Sel].m();
1299  double m2Res = (i2Sel == 0) ? 0. : event[i2Sel].m();
1300  acceptKin = dSigmaDtSel->final2KinMPI( i1Sel, i2Sel, p1Res, p2Res,
1301  m1Res, m2Res);
1302  // New interaction: already stored values enough.
1303  } else acceptKin = dSigmaDtSel->final2KinMPI();
1304  } while (!acceptKin);
1305 
1306  // Done.
1307  return sqrt(pT2);
1308 
1309 }
1310 
1311 //--------------------------------------------------------------------------
1312 
1313 // Set up the kinematics of the 2 -> 2 scattering process,
1314 // and store the scattering in the event record.
1315 
1316 bool MultipartonInteractions::scatter( Event& event) {
1317 
1318  // Last beam-status particles. Offset relative to normal beam locations.
1319  int sizeProc = event.size();
1320  int nBeams = 3;
1321  for (int i = 3; i < sizeProc; ++i)
1322  if (event[i].statusAbs() < 20) nBeams = i + 1;
1323  int nOffset = nBeams - 3;
1324 
1325  // Loop over four partons and offset info relative to subprocess itself.
1326  int motherOffset = event.size();
1327  int colOffset = event.lastColTag();
1328  for (int i = 1; i <= 4; ++i) {
1329  Particle parton = dSigmaDtSel->getParton(i);
1330  if (i <= 2 ) parton.mothers( i + nOffset, 0);
1331  else parton.mothers( motherOffset, motherOffset + 1);
1332  if (i <= 2 ) parton.daughters( motherOffset + 2, motherOffset + 3);
1333  else parton.daughters( 0, 0);
1334  int col = parton.col();
1335  if (col > 0) parton.col( col + colOffset);
1336  int acol = parton.acol();
1337  if (acol > 0) parton.acol( acol + colOffset);
1338 
1339  // Put the partons into the event record.
1340  event.append(parton);
1341  }
1342 
1343  // Allow setting of new parton production vertices.
1344  if (doPartonVertex)
1345  partonVertexPtr->vertexMPI( sizeProc, 4, bNow, event);
1346 
1347  // Allow veto of MPI. If so restore event record to before scatter.
1348  if (canVetoMPI && userHooksPtr->doVetoMPIEmission(sizeProc, event)) {
1349  event.popBack(event.size() - sizeProc);
1350  return false;
1351  }
1352 
1353  // Store participating partons as a new set in list of all systems.
1354  int iSys = partonSystemsPtr->addSys();
1355  partonSystemsPtr->setInA(iSys, motherOffset);
1356  partonSystemsPtr->setInB(iSys, motherOffset + 1);
1357  partonSystemsPtr->addOut(iSys, motherOffset + 2);
1358  partonSystemsPtr->addOut(iSys, motherOffset + 3);
1359  partonSystemsPtr->setSHat(iSys, sHat);
1360 
1361  // Tag double rescattering graphs that annihilate one initial colour.
1362  bool annihil1 = false;
1363  bool annihil2 = false;
1364  if (i1Sel > 0 && i2Sel > 0) {
1365  if (event[motherOffset].col() == event[motherOffset + 1].acol()
1366  && event[motherOffset].col() > 0) annihil1 = true;
1367  if (event[motherOffset].acol() == event[motherOffset + 1].col()
1368  && event[motherOffset].acol() > 0) annihil2 = true;
1369  }
1370 
1371  // Beam remnant A: add scattered partons to list.
1372  BeamParticle& beamA = *beamAPtr;
1373  int iA = beamA.append( motherOffset, id1, x1);
1374 
1375  // Find whether incoming partons are valence or sea, so prepared for ISR.
1376  if (i1Sel == 0) {
1377  beamA.xfISR( iA, id1, x1, pT2);
1378  beamA.pickValSeaComp();
1379 
1380  // Remove rescattered parton from final state and change history.
1381  // Propagate existing colour labels throught graph.
1382  } else {
1383  beamA[iA].companion(-10);
1384  event[i1Sel].statusNeg();
1385  event[i1Sel].daughters( motherOffset, motherOffset);
1386  event[motherOffset].mothers( i1Sel, i1Sel);
1387  int colOld = event[i1Sel].col();
1388  if (colOld > 0) {
1389  int colNew = event[motherOffset].col();
1390  for (int i = motherOffset; i < motherOffset + 4; ++i) {
1391  if (event[i].col() == colNew) event[i].col( colOld);
1392  if (event[i].acol() == colNew) event[i].acol( colOld);
1393  }
1394  }
1395  int acolOld = event[i1Sel].acol();
1396  if (acolOld > 0) {
1397  int acolNew = event[motherOffset].acol();
1398  for (int i = motherOffset; i < motherOffset + 4; ++i) {
1399  if (event[i].col() == acolNew) event[i].col( acolOld);
1400  if (event[i].acol() == acolNew) event[i].acol( acolOld);
1401  }
1402  }
1403  }
1404 
1405  // Beam remnant B: add scattered partons to list.
1406  BeamParticle& beamB = *beamBPtr;
1407  int iB = beamB.append( motherOffset + 1, id2, x2);
1408 
1409  // Find whether incoming partons are valence or sea, so prepared for ISR.
1410  if (i2Sel == 0) {
1411  beamB.xfISR( iB, id2, x2, pT2);
1412  beamB.pickValSeaComp();
1413 
1414  // Remove rescattered parton from final state and change history.
1415  // Propagate existing colour labels throught graph.
1416  } else {
1417  beamB[iB].companion(-10);
1418  event[i2Sel].statusNeg();
1419  event[i2Sel].daughters( motherOffset + 1, motherOffset + 1);
1420  event[motherOffset + 1].mothers( i2Sel, i2Sel);
1421  int colOld = event[i2Sel].col();
1422  if (colOld > 0) {
1423  int colNew = event[motherOffset + 1].col();
1424  for (int i = motherOffset; i < motherOffset + 4; ++i) {
1425  if (event[i].col() == colNew) event[i].col( colOld);
1426  if (event[i].acol() == colNew) event[i].acol( colOld);
1427  }
1428  }
1429  int acolOld = event[i2Sel].acol();
1430  if (acolOld > 0) {
1431  int acolNew = event[motherOffset + 1].acol();
1432  for (int i = motherOffset; i < motherOffset + 4; ++i) {
1433  if (event[i].col() == acolNew) event[i].col( acolOld);
1434  if (event[i].acol() == acolNew) event[i].acol( acolOld);
1435  }
1436  }
1437  }
1438 
1439  // Annihilating colour in double rescattering requires relabelling
1440  // of one colour into the other in the whole preceding event.
1441  if (annihil1 || annihil2) {
1442  int colLeft = (annihil1) ? event[motherOffset].col()
1443  : event[motherOffset].acol();
1444  int mother1 = event[motherOffset].mother1();
1445  int mother2 = event[motherOffset + 1].mother1();
1446  int colLost = (annihil1)
1447  ? event[mother1].col() + event[mother2].acol() - colLeft
1448  : event[mother1].acol() + event[mother2].col() - colLeft;
1449  for (int i = 0; i < motherOffset; ++i) {
1450  if (event[i].col() == colLost) event[i].col( colLeft );
1451  if (event[i].acol() == colLost) event[i].acol( colLeft );
1452  }
1453  }
1454 
1455  // With gamma+gamma check that room for beam remnants for current scattering.
1456  // Otherwise take the partons out from event record.
1457  // roomForRemnants treats both beam equally so need to do only once.
1458  if ( beamAPtr->isGamma() || beamBPtr->isGamma() ) {
1459  if ( !beamAPtr->roomForRemnants(*beamBPtr) ) {
1460  // Remove the partons associated to the latest scattering from the
1461  // event record.
1462  event.popBack(4);
1463  beamAPtr->popBack();
1464  beamBPtr->popBack();
1465  partonSystemsPtr->popBack();
1466 
1467  infoPtr->errorMsg("Warning in MultipartonInteractions::scatter:"
1468  " No room for remnants for given scattering");
1469  return false;
1470  }
1471  }
1472 
1473  // Store the pT value for valence decision of resolved photons.
1474  beamA.pTMPI(sqrtpos(pT2));
1475  beamB.pTMPI(sqrtpos(pT2));
1476 
1477  // Store info on subprocess code and rescattered partons.
1478  int codeMPI = dSigmaDtSel->code();
1479  double pTMPI = dSigmaDtSel->pTMPIFin();
1480  if (iDiffSys == 0) infoPtr->setTypeMPI( codeMPI, pTMPI, i1Sel, i2Sel,
1481  enhanceBnow / zeroIntCorr);
1482  partonSystemsPtr->setPTHat(iSys, pTMPI);
1483 
1484  // Done.
1485  return true;
1486 }
1487 
1488 //--------------------------------------------------------------------------
1489 
1490 // Determine constant in d(Prob)/d(pT2) < const / (pT2 + r * pT20)^2.
1491 
1492 void MultipartonInteractions::upperEnvelope() {
1493 
1494  // Initially determine constant in jet cross section upper estimate
1495  // d(sigma_approx)/d(pT2) < const / (pT2 + r * pT20)^2.
1496  pT4dSigmaMax = 0.;
1497 
1498  // Loop thorough allowed pT range logarithmically evenly.
1499  for (int iPT = 0; iPT < 100; ++iPT) {
1500  double pT = pTmin * pow( pTmax/pTmin, 0.01 * (iPT + 0.5) );
1501  pT2 = pT*pT;
1502  pT2shift = pT2 + pT20;
1503  pT2Ren = pT2shift;
1504  pT2Fac = (SHIFTFACSCALE) ? pT2shift : pT2;
1505  xT = 2. * pT / eCM;
1506 
1507  // Evaluate parton density sums at x1 = x2 = xT.
1508  double xPDF1sumMax = (9./4.) * beamAPtr->xf(21, xT, pT2Fac);
1509  for (int id = 1; id <= nQuarkIn; ++id)
1510  xPDF1sumMax += beamAPtr->xf( id, xT, pT2Fac)
1511  + beamAPtr->xf(-id, xT, pT2Fac);
1512  double xPDF2sumMax = (9./4.) * beamBPtr->xf(21, xT, pT2Fac);
1513  for (int id = 1; id <= nQuarkIn; ++id)
1514  xPDF2sumMax += beamBPtr->xf( id, xT, pT2Fac)
1515  + beamBPtr->xf(-id, xT, pT2Fac);
1516 
1517  // Evaluate alpha_strong and _EM, matrix element and phase space volume.
1518  alpS = alphaS.alphaS(pT2Ren);
1519  alpEM = alphaEM.alphaEM(pT2Ren);
1520  double dSigmaPartonApprox = CONVERT2MB * Kfactor * 0.5 * M_PI
1521  * pow2(alpS / pT2shift);
1522  double yMax = log(1./xT + sqrt(1./(xT*xT) - 1.));
1523  double volumePhSp = pow2(2. * yMax);
1524 
1525  // Final comparison to determine upper estimate.
1526  double dSigmaApproxNow = SIGMAFUDGE * xPDF1sumMax * xPDF2sumMax
1527  * dSigmaPartonApprox * volumePhSp;
1528  double pT4dSigmaNow = pow2(pT2 + pT20R) * dSigmaApproxNow;
1529  if ( pT4dSigmaNow > pT4dSigmaMax) pT4dSigmaMax = pT4dSigmaNow;
1530  }
1531 
1532  // Get wanted constant by dividing by the nondiffractive cross section.
1533  pT4dProbMax = pT4dSigmaMax / sigmaND;
1534 
1535 }
1536 
1537 //--------------------------------------------------------------------------
1538 
1539 // Integrate the parton-parton interaction cross section,
1540 // using stratified Monte Carlo sampling.
1541 // Store result in pT bins for use as Sudakov form factors.
1542 
1543 void MultipartonInteractions::jetCrossSection() {
1544 
1545  // Common factor from bin size in dpT2 / (pT2 + r * pT20)^2 and statistics.
1546  double sigmaFactor = (1. / pT20minR - 1. / pT20maxR) / (100. * nSample);
1547 
1548  // Reset overlap-weighted cross section for x-dependent matter profile.
1549  if (bProfile == 4) for (int bBin = 0; bBin < XDEP_BBIN; bBin++)
1550  sigmaIntWgt[bBin] = 0.;
1551 
1552  // Loop through allowed pT range evenly in dpT2 / (pT2 + r * pT20)^2.
1553  sigmaInt = 0.;
1554  double dSigmaMax = 0.;
1555  sudExpPT[100] = 0.;
1556 
1557  for (int iPT = 99; iPT >= 0; --iPT) {
1558  double sigmaSum = 0.;
1559 
1560  // Reset pT-binned overlap-weigted integration.
1561  if (bProfile == 4) for (int bBin = 0; bBin < XDEP_BBIN; bBin++)
1562  sigmaSumWgt[bBin] = 0.;
1563 
1564  // In each pT bin sample a number of random pT values.
1565  for (int iSample = 0; iSample < nSample; ++iSample) {
1566  double mappedPT2 = 1. - 0.01 * (iPT + rndmPtr->flat());
1567  pT2 = pT20min0maxR / (pT20minR + mappedPT2 * pT2maxmin) - pT20R;
1568 
1569  // Evaluate cross section dSigma/dpT2 in phase space point.
1570  double dSigma = sigmaPT2scatter(true);
1571 
1572  // Multiply by (pT2 + r * pT20)^2 to compensate for pT sampling. Sum.
1573  dSigma *= pow2(pT2 + pT20R);
1574  sigmaSum += dSigma;
1575  if (dSigma > dSigmaMax) dSigmaMax = dSigma;
1576 
1577  // Overlap-weighted cross section for x-dependent matter profile.
1578  // Note that dSigma can be 0. when points are rejected.
1579  if (bProfile == 4 && dSigma > 0.) {
1580  double w1 = XDEP_A1 + a1 * log(1. / x1);
1581  double w2 = XDEP_A1 + a1 * log(1. / x2);
1582  double fac = XDEP_A0 * XDEP_A0 * (w1 * w1 + w2 * w2);
1583  double b = 0.5 * bstepNow;
1584  for (int bBin = 0; bBin < XDEP_BBIN; bBin++) {
1585  double wgt = exp( - b * b / fac ) / fac / M_PI;
1586  sigmaSumWgt[bBin] += dSigma * wgt;
1587  b += bstepNow;
1588  }
1589  }
1590  }
1591 
1592  // Store total cross section and exponent of Sudakov.
1593  sigmaSum *= sigmaFactor;
1594  sigmaInt += sigmaSum;
1595  sudExpPT[iPT] = sudExpPT[iPT + 1] + sigmaSum / sigmaND;
1596 
1597  // Sum overlap-weighted cross section
1598  if (bProfile == 4) for (int bBin = 0; bBin < XDEP_BBIN; bBin++) {
1599  sigmaSumWgt[bBin] *= sigmaFactor;
1600  sigmaIntWgt[bBin] += sigmaSumWgt[bBin];
1601  }
1602 
1603  // End of loop over pT values.
1604  }
1605 
1606  // Update upper estimate of differential cross section. Done.
1607  if (dSigmaMax > pT4dSigmaMax) {
1608  pT4dSigmaMax = dSigmaMax;
1609  pT4dProbMax = dSigmaMax / sigmaND;
1610  }
1611 
1612 }
1613 
1614 //--------------------------------------------------------------------------
1615 
1616 // Evaluate "Sudakov form factor" for not having a harder interaction
1617 // at the selected b value, given the pT scale of the event.
1618 
1619 double MultipartonInteractions::sudakov(double pT2sud, double enhance) {
1620 
1621  // Find bin the pT2 scale falls in.
1622  double xBin = (pT2sud - pT2min) * pT20maxR
1623  / (pT2maxmin * (pT2sud + pT20R));
1624  xBin = max(1e-6, min(100. - 1e-6, 100. * xBin) );
1625  int iBin = int(xBin);
1626 
1627  // Interpolate inside bin. Optionally include enhancement factor.
1628  double sudExp = sudExpPT[iBin] + (xBin - iBin)
1629  * (sudExpPT[iBin + 1] - sudExpPT[iBin]);
1630  return exp( -enhance * sudExp);
1631 
1632 }
1633 
1634 //--------------------------------------------------------------------------
1635 
1636 // Pick a trial next pT, based on a simple upper estimate of the
1637 // d(sigma)/d(pT2) spectrum.
1638 
1639 double MultipartonInteractions::fastPT2( double pT2beg) {
1640 
1641  // Use d(Prob)/d(pT2) < pT4dProbMax / (pT2 + r * pT20)^2.
1642  double pT20begR = pT2beg + pT20R;
1643  double pT4dProbMaxNow = pT4dProbMax * enhanceBmax;
1644  double pT2try = pT4dProbMaxNow * pT20begR
1645  / (pT4dProbMaxNow - pT20begR * log(rndmPtr->flat())) - pT20R;
1646 
1647  if ( pT2try + pT20R <= 0.0 ) return 0.0;
1648 
1649  // Save cross section associated with ansatz above. Done.
1650  dSigmaApprox = pT4dSigmaMax / pow2(pT2try + pT20R);
1651  return pT2try;
1652 
1653 }
1654 
1655 //--------------------------------------------------------------------------
1656 
1657 // Calculate the actual cross section to decide whether fast choice is OK.
1658 // Select flavours and kinematics for interaction at given pT.
1659 // Slightly different treatment for first interaction and subsequent ones.
1660 
1661 double MultipartonInteractions::sigmaPT2scatter(bool isFirst) {
1662 
1663  // Derive recormalization and factorization scales, amd alpha_strong/em.
1664  pT2shift = pT2 + pT20;
1665  pT2Ren = pT2shift;
1666  pT2Fac = (SHIFTFACSCALE) ? pT2shift : pT2;
1667  alpS = alphaS.alphaS(pT2Ren);
1668  alpEM = alphaEM.alphaEM(pT2Ren);
1669 
1670  // Derive rapidity limits from chosen pT2.
1671  xT = 2. * sqrt(pT2) / eCM;
1672  if (xT >= 1.) return 0.;
1673  xT2 = xT*xT;
1674  double yMax = log(1./xT + sqrt(1./xT2 - 1.));
1675 
1676  // Select rapidities y3 and y4 of the two produced partons.
1677  double y3 = yMax * (2. * rndmPtr->flat() - 1.);
1678  double y4 = yMax * (2. * rndmPtr->flat() - 1.);
1679  y = 0.5 * (y3 + y4);
1680 
1681  // Failure if x1 or x2 exceed what is left in respective beam.
1682  x1 = 0.5 * xT * (exp(y3) + exp(y4));
1683  x2 = 0.5 * xT * (exp(-y3) + exp(-y4));
1684  if (isFirst && iDiffSys == 0) {
1685  if (x1 > 1. || x2 > 1.) return 0.;
1686  } else {
1687  if (x1 > beamAPtr->xMax() || x2 > beamBPtr->xMax()) return 0.;
1688  }
1689  tau = x1 * x2;
1690 
1691  // Begin evaluate parton densities at actual x1 and x2.
1692  double xPDF1[21];
1693  double xPDF1sum = 0.;
1694  double xPDF2[21];
1695  double xPDF2sum = 0.;
1696 
1697  // For first interaction use normal densities.
1698  if (isFirst) {
1699  for (int id = -nQuarkIn; id <= nQuarkIn; ++id) {
1700  if (id == 0) {
1701  xPDF1[10] = (9./4.) * beamAPtr->xf(21, x1, pT2Fac);
1702  xPDF2[10] = (9./4.) * beamBPtr->xf(21, x2, pT2Fac);
1703  } else {
1704  xPDF1[id+10] = beamAPtr->xf(id, x1, pT2Fac);
1705  xPDF2[id+10] = beamBPtr->xf(id, x2, pT2Fac);
1706  }
1707  xPDF1sum += xPDF1[id+10];
1708  xPDF2sum += xPDF2[id+10];
1709  }
1710 
1711  // For subsequent interactions use rescaled densities.
1712  } else {
1713  xfModPrepData xfDataA = beamAPtr->xfModPrep(-1, pT2Fac);
1714  xfModPrepData xfDataB = beamBPtr->xfModPrep(-1, pT2Fac);
1715  for (int id = -nQuarkIn; id <= nQuarkIn; ++id) {
1716  if (id == 0) continue;
1717  xPDF1[id+10] = beamAPtr->xfMPI(id, x1, pT2Fac, xfDataA);
1718  xPDF2[id+10] = beamBPtr->xfMPI(id, x2, pT2Fac, xfDataB);
1719  xPDF1sum += xPDF1[id+10];
1720  xPDF2sum += xPDF2[id+10];
1721  }
1722  xPDF1[10] = (9./4.) * beamAPtr->xfMPI(21, x1, pT2Fac, xfDataA);
1723  xPDF2[10] = (9./4.) * beamBPtr->xfMPI(21, x2, pT2Fac, xfDataB);
1724  xPDF1sum += xPDF1[10];
1725  xPDF2sum += xPDF2[10];
1726  }
1727 
1728  // Select incoming flavours according to actual PDF's.
1729  id1 = -nQuarkIn - 1;
1730  double temp = xPDF1sum * rndmPtr->flat();
1731  do { xPDF1now = xPDF1[(++id1) + 10]; temp -= xPDF1now; }
1732  while (temp > 0. && id1 < nQuarkIn);
1733  if (id1 == 0) id1 = 21;
1734  id2 = -nQuarkIn-1;
1735  temp = xPDF2sum * rndmPtr->flat();
1736  do { xPDF2now = xPDF2[(++id2) + 10]; temp -= xPDF2now;}
1737  while (temp > 0. && id2 < nQuarkIn);
1738  if (id2 == 0) id2 = 21;
1739 
1740  // Check whether room for remnants left after scattering with photon beams.
1741  if ( isFirst && ( beamAPtr->isGamma() || beamBPtr->isGamma() ) ) {
1742  double mTRem = eCM * sqrt( (1 - x1) * (1 - x2) );
1743  double m1 = beamAPtr->remnantMass(id1);
1744  double m2 = beamBPtr->remnantMass(id2);
1745  if (mTRem < m1 + m2) return 0.;
1746  }
1747 
1748  // Assign pointers to processes relevant for incoming flavour choice:
1749  // g + g, q + g, q + qbar (same flavour), q + q(bar) (the rest).
1750  // Factor 4./9. per incoming gluon to compensate for preweighting.
1751  SigmaMultiparton* sigma2Tmp;
1752  double gluFac = 1.;
1753  if (id1 == 21 && id2 == 21) {
1754  sigma2Tmp = &sigma2gg;
1755  gluFac = 16. / 81.;
1756  } else if (id1 == 21 || id2 == 21) {
1757  sigma2Tmp = &sigma2qg;
1758  gluFac = 4. / 9.;
1759  } else if (id1 == -id2) sigma2Tmp = &sigma2qqbarSame;
1760  else sigma2Tmp = &sigma2qq;
1761 
1762  // Prepare to generate differential cross sections.
1763  sHat = tau * sCM;
1764  double root = sqrtpos(1. - xT2 / tau);
1765  tHat = -0.5 * sHat * (1. - root);
1766  uHat = -0.5 * sHat * (1. + root);
1767 
1768  // Evaluate cross sections, include possibility of K factor.
1769  // Use kinematics for two symmetrical configurations (tHat <-> uHat).
1770  // (Not necessary, but makes for better MC efficiency.)
1771  double dSigmaPartonCorr = Kfactor * gluFac
1772  * sigma2Tmp->sigma( id1, id2, x1, x2, sHat, tHat, uHat, alpS, alpEM);
1773 
1774  // Combine cross section, pdf's and phase space integral.
1775  double volumePhSp = pow2(2. * yMax);
1776  double dSigmaScat = dSigmaPartonCorr * xPDF1sum * xPDF2sum * volumePhSp;
1777 
1778  // Dampen cross section at small pT values; part of formalism.
1779  // Use pT2 corrected for massive kinematics at this step.??
1780  // double pT2massive = dSigmaDtSel->pT2MPI();
1781  double pT2massive = pT2;
1782  dSigmaScat *= pow2( pT2massive / (pT2massive + pT20) );
1783 
1784  // Sum up total contribution for all scatterings and rescatterings.
1785  dSigmaSum += dSigmaScat;
1786 
1787  // Save values for comparison with rescattering processes.
1788  i1Sel = 0;
1789  i2Sel = 0;
1790  id1Sel = id1;
1791  id2Sel = id2;
1792  x1Sel = x1;
1793  x2Sel = x2;
1794  sHatSel = sHat;
1795  tHatSel = tHat;
1796  uHatSel = uHat;
1797  sigma2Sel = sigma2Tmp;
1798  pickOtherSel = sigma2Tmp->pickedOther();
1799 
1800  // For first interaction: pick one of the possible channels summed above.
1801  if (isFirst) {
1802  dSigmaDtSel = sigma2Tmp->sigmaSel();
1803  if (sigma2Tmp->swapTU()) swap( tHat, uHat);
1804  }
1805 
1806  // Done.
1807  return dSigmaScat;
1808 }
1809 
1810 //--------------------------------------------------------------------------
1811 
1812 // Find the partons that are allowed to rescatter.
1813 
1814 void MultipartonInteractions::findScatteredPartons( Event& event) {
1815 
1816  // Reset arrays.
1817  scatteredA.resize(0);
1818  scatteredB.resize(0);
1819  double yTmp, probA, probB;
1820 
1821  // Loop though the event record and catch "final" partons.
1822  for (int i = 0; i < event.size(); ++i)
1823  if (event[i].isFinal() && (event[i].idAbs() <= nQuarkIn
1824  || event[i].id() == 21)) {
1825  yTmp = event[i].y();
1826 
1827  // Different strategies to determine which partons may rescatter.
1828  switch(rescatterMode) {
1829 
1830  // Case 0: step function at origin
1831  case 0:
1832  if ( yTmp > 0.) scatteredA.push_back( i);
1833  if (-yTmp > 0.) scatteredB.push_back( i);
1834  break;
1835 
1836  // Case 1: step function as ySepResc.
1837  case 1:
1838  if ( yTmp > ySepResc) scatteredA.push_back( i);
1839  if (-yTmp > ySepResc) scatteredB.push_back( i);
1840  break;
1841 
1842  // Case 2: linear rise from ySep - deltaY to ySep + deltaY.
1843  case 2:
1844  probA = 0.5 * (1. + ( yTmp - ySepResc) / deltaYResc);
1845  if (probA > rndmPtr->flat()) scatteredA.push_back( i);
1846  probB = 0.5 * (1. + (-yTmp - ySepResc) / deltaYResc);
1847  if (probB > rndmPtr->flat()) scatteredB.push_back( i);
1848  break;
1849 
1850  // Case 3: rise like (1/2) * ( 1 + tanh((y - ySep) / deltaY) ).
1851  // Use that (1/2) (1 + tanh(x)) = 1 / (1 + exp(-2x)).
1852  case 3:
1853  probA = 1. / (1. + exp(-2. * ( yTmp - ySepResc) / deltaYResc));
1854  if (probA > rndmPtr->flat()) scatteredA.push_back( i);
1855  probB = 1. / (1. + exp(-2. * (-yTmp - ySepResc) / deltaYResc));
1856  if (probB > rndmPtr->flat()) scatteredB.push_back( i);
1857  break;
1858 
1859  // Case 4 and undefined values: all partons can rescatter.
1860  default:
1861  scatteredA.push_back( i);
1862  scatteredB.push_back( i);
1863  break;
1864 
1865  // End of loop over partons. Done.
1866  }
1867  }
1868 
1869 }
1870 
1871 //--------------------------------------------------------------------------
1872 
1873 // Rescattering contribution summed over all already scattered partons.
1874 // Calculate the actual cross section to decide whether fast choice is OK.
1875 // Select flavours and kinematics for interaction at given pT.
1876 
1877 double MultipartonInteractions::sigmaPT2rescatter( Event& event) {
1878 
1879  // Derive xT scale from chosen pT2.
1880  xT = 2. * sqrt(pT2) / eCM;
1881  if (xT >= 1.) return 0.;
1882  xT2 = xT*xT;
1883 
1884  // Pointer to cross section and total rescatter contribution.
1885  SigmaMultiparton* sigma2Tmp;
1886  double dSigmaResc = 0.;
1887 
1888  // Normally save time by picking one random scattered parton from side A.
1889  int nScatA = scatteredA.size();
1890  int iScatA = -1;
1891  if (PREPICKRESCATTER && nScatA > 0) iScatA = min( nScatA - 1,
1892  int( rndmPtr->flat() * double(nScatA) ) );
1893 
1894  // Loop over all already scattered partons from side A.
1895  xfModPrepData xfDataB = beamBPtr->xfModPrep(-1, pT2Fac);
1896  for (int iScat = 0; iScat < nScatA; ++iScat) {
1897  if (PREPICKRESCATTER && iScat != iScatA) continue;
1898  int iA = scatteredA[iScat];
1899  int id1Tmp = event[iA].id();
1900 
1901  // Calculate maximum possible sHat and check whether big enough.
1902  double x1Tmp = event[iA].pPos() / eCM;
1903  double sHatMax = x1Tmp * beamBPtr->xMax() * sCM;
1904  if (sHatMax < 4. * pT2) continue;
1905 
1906  // Select rapidity separation between two produced partons.
1907  double dyMax = log( sqrt(0.25 * sHatMax / pT2)
1908  * (1. + sqrtpos(1. - 4. * pT2 / sHatMax)) );
1909  double dy = dyMax * (2. * rndmPtr->flat() - 1.);
1910 
1911  // Reconstruct kinematical variables, especially x2.
1912  // Incoming c/b masses handled better if tau != x1 * x2.
1913  double m2Tmp = event[iA].m2();
1914  double sHatTmp = m2Tmp + 4. * pT2 * pow2(cosh(dy));
1915  double x2Tmp = (sHatTmp - m2Tmp) /(x1Tmp * sCM);
1916  double tauTmp = sHatTmp / sCM;
1917  double root = sqrtpos(1. - xT2 / tauTmp);
1918  double tHatTmp = -0.5 * sHatTmp * (1. - root);
1919  double uHatTmp = -0.5 * sHatTmp * (1. + root);
1920 
1921  // Begin evaluate parton densities at actual x2.
1922  double xPDF2[21];
1923  double xPDF2sum = 0.;
1924 
1925  // Use rescaled densities, with preweighting 9/4 for gluons.
1926  for (int id = -nQuarkIn; id <= nQuarkIn; ++id) {
1927  if (id == 0) continue;
1928  xPDF2[id+10] = beamBPtr->xfMPI(id, x2Tmp, pT2Fac, xfDataB);
1929  xPDF2sum += xPDF2[id+10];
1930  }
1931  xPDF2[10] = (9./4.) * beamBPtr->xfMPI(21, x2Tmp, pT2Fac, xfDataB);
1932  xPDF2sum += xPDF2[10];
1933 
1934  // Select incoming flavour according to actual PDF's.
1935  int id2Tmp = -nQuarkIn - 1;
1936  double temp = xPDF2sum * rndmPtr->flat();
1937  do { xPDF2now = xPDF2[(++id2Tmp) + 10]; temp -= xPDF2now;}
1938  while (temp > 0. && id2Tmp < nQuarkIn);
1939  if (id2Tmp == 0) id2Tmp = 21;
1940 
1941  // Assign pointers to processes relevant for incoming flavour choice:
1942  // g + g, q + g, q + qbar (same flavour), q + q(bar) (the rest).
1943  // Factor 4./9. for incoming gluon 2 to compensate for preweighting.
1944  if (id1Tmp == 21 && id2Tmp == 21) sigma2Tmp = &sigma2gg;
1945  else if (id1Tmp == 21 || id2Tmp == 21) sigma2Tmp = &sigma2qg;
1946  else if (id1Tmp == -id2Tmp) sigma2Tmp = &sigma2qqbarSame;
1947  else sigma2Tmp = &sigma2qq;
1948  double gluFac = (id2Tmp == 21) ? 4. / 9. : 1.;
1949 
1950  // Evaluate cross sections, include possibility of K factor.
1951  // Use kinematics for two symmetrical configurations (tHat <-> uHat).
1952  // (Not necessary, but makes for better MC efficiency.)
1953  double dSigmaPartonCorr = Kfactor * gluFac
1954  * sigma2Tmp->sigma( id1Tmp, id2Tmp, x1Tmp, x2Tmp, sHatTmp, tHatTmp,
1955  uHatTmp, alpS, alpEM);
1956 
1957  // Combine cross section, pdf's and phase space integral.
1958  double volumePhSp = 4. *dyMax;
1959  double dSigmaCorr = dSigmaPartonCorr * xPDF2sum * volumePhSp;
1960 
1961  // Dampen cross section at small pT values; part of formalism.
1962  // Use pT2 corrected for massive kinematics at this step.
1963  //?? double pT2massive = dSigmaDtSel->pT2MPI();
1964  double pT2massive = pT2;
1965  dSigmaCorr *= pow2( pT2massive / (pT2massive + pT20) );
1966 
1967  // Compensate for prepicked rescattering if appropriate.
1968  if (PREPICKRESCATTER) dSigmaCorr *= nScatA;
1969 
1970  // Sum up total contribution for all scatterings or rescattering only.
1971  dSigmaSum += dSigmaCorr;
1972  dSigmaResc += dSigmaCorr;
1973 
1974  // Determine whether current rescattering should be selected.
1975  if (dSigmaCorr > rndmPtr->flat() * dSigmaSum) {
1976  i1Sel = iA;
1977  i2Sel = 0;
1978  id1Sel = id1Tmp;
1979  id2Sel = id2Tmp;
1980  x1Sel = x1Tmp;
1981  x2Sel = x2Tmp;
1982  sHatSel = sHatTmp;
1983  tHatSel = tHatTmp;
1984  uHatSel = uHatTmp;
1985  sigma2Sel = sigma2Tmp;
1986  pickOtherSel = sigma2Tmp->pickedOther();
1987  }
1988  }
1989 
1990  // Normally save time by picking one random scattered parton from side B.
1991  int nScatB = scatteredB.size();
1992  int iScatB = -1;
1993  if (PREPICKRESCATTER && nScatB > 0) iScatB = min( nScatB - 1,
1994  int( rndmPtr->flat() * double(nScatB) ) );
1995 
1996  // Loop over all already scattered partons from side B.
1997  xfModPrepData xfDataA = beamAPtr->xfModPrep(-1, pT2Fac);
1998  for (int iScat = 0; iScat < nScatB; ++iScat) {
1999  if (PREPICKRESCATTER && iScat != iScatB) continue;
2000  int iB = scatteredB[iScat];
2001  int id2Tmp = event[iB].id();
2002 
2003  // Calculate maximum possible sHat and check whether big enough.
2004  double x2Tmp = event[iB].pNeg() / eCM;
2005  double sHatMax = beamAPtr->xMax() * x2Tmp * sCM;
2006  if (sHatMax < 4. * pT2) continue;
2007 
2008  // Select rapidity separation between two produced partons.
2009  double dyMax = log( sqrt(0.25 * sHatMax / pT2)
2010  * (1. + sqrtpos(1. - 4. * pT2 / sHatMax)) );
2011  double dy = dyMax * (2. * rndmPtr->flat() - 1.);
2012 
2013  // Reconstruct kinematical variables, especially x1.
2014  // Incoming c/b masses handled better if tau != x1 * x2.
2015  double m2Tmp = event[iB].m2();
2016  double sHatTmp = m2Tmp + 4. * pT2 * pow2(cosh(dy));
2017  double x1Tmp = (sHatTmp - m2Tmp) /(x2Tmp * sCM);
2018  double tauTmp = sHatTmp / sCM;
2019  double root = sqrtpos(1. - xT2 / tauTmp);
2020  double tHatTmp = -0.5 * sHatTmp * (1. - root);
2021  double uHatTmp = -0.5 * sHatTmp * (1. + root);
2022 
2023  // Begin evaluate parton densities at actual x1.
2024  double xPDF1[21];
2025  double xPDF1sum = 0.;
2026 
2027  // Use rescaled densities, with preweighting 9/4 for gluons.
2028  for (int id = -nQuarkIn; id <= nQuarkIn; ++id) {
2029  if (id == 0) continue;
2030  xPDF1[id+10] = beamAPtr->xfMPI(id, x1Tmp, pT2Fac, xfDataA);
2031  xPDF1sum += xPDF1[id+10];
2032  }
2033  xPDF1[10] = (9./4.) * beamAPtr->xfMPI(21, x1Tmp, pT2Fac, xfDataA);
2034  xPDF1sum += xPDF1[10];
2035 
2036  // Select incoming flavour according to actual PDF's.
2037  int id1Tmp = -nQuarkIn - 1;
2038  double temp = xPDF1sum * rndmPtr->flat();
2039  do { xPDF1now = xPDF1[(++id1Tmp) + 10]; temp -= xPDF1now;}
2040  while (temp > 0. && id1Tmp < nQuarkIn);
2041  if (id1Tmp == 0) id1Tmp = 21;
2042 
2043  // Assign pointers to processes relevant for incoming flavour choice:
2044  // g + g, q + g, q + qbar (same flavour), q + q(bar) (the rest).
2045  // Factor 4./9. for incoming gluon 2 to compensate for preweighting.
2046  if (id1Tmp == 21 && id2Tmp == 21) sigma2Tmp = &sigma2gg;
2047  else if (id1Tmp == 21 || id2Tmp == 21) sigma2Tmp = &sigma2qg;
2048  else if (id1Tmp == -id2Tmp) sigma2Tmp = &sigma2qqbarSame;
2049  else sigma2Tmp = &sigma2qq;
2050  double gluFac = (id1Tmp == 21) ? 4. / 9. : 1.;
2051 
2052  // Evaluate cross sections, include possibility of K factor.
2053  // Use kinematics for two symmetrical configurations (tHat <-> uHat).
2054  // (Not necessary, but makes for better MC efficiency.)
2055  double dSigmaPartonCorr = Kfactor * gluFac
2056  * sigma2Tmp->sigma( id1Tmp, id2Tmp, x1Tmp, x2Tmp, sHatTmp, tHatTmp,
2057  uHatTmp, alpS, alpEM);
2058 
2059  // Combine cross section, pdf's and phase space integral.
2060  double volumePhSp = 4. *dyMax;
2061  double dSigmaCorr = dSigmaPartonCorr * xPDF1sum * volumePhSp;
2062 
2063  // Dampen cross section at small pT values; part of formalism.
2064  // Use pT2 corrected for massive kinematics at this step.
2065  //?? double pT2massive = dSigmaDtSel->pT2MPI();
2066  double pT2massive = pT2;
2067  dSigmaCorr *= pow2( pT2massive / (pT2massive + pT20) );
2068 
2069  // Compensate for prepicked rescattering if appropriate.
2070  if (PREPICKRESCATTER) dSigmaCorr *= nScatB;
2071 
2072  // Sum up total contribution for all scatterings or rescattering only.
2073  dSigmaSum += dSigmaCorr;
2074  dSigmaResc += dSigmaCorr;
2075 
2076  // Determine whether current rescattering should be selected.
2077  if (dSigmaCorr > rndmPtr->flat() * dSigmaSum) {
2078  i1Sel = 0;
2079  i2Sel = iB;
2080  id1Sel = id1Tmp;
2081  id2Sel = id2Tmp;
2082  x1Sel = x1Tmp;
2083  x2Sel = x2Tmp;
2084  sHatSel = sHatTmp;
2085  tHatSel = tHatTmp;
2086  uHatSel = uHatTmp;
2087  sigma2Sel = sigma2Tmp;
2088  pickOtherSel = sigma2Tmp->pickedOther();
2089  }
2090  }
2091 
2092  // Double rescatter: loop over already scattered partons from both sides.
2093  // As before, allow to use only one parton per side to speed up.
2094  if (allowDoubleRes) {
2095  for (int iScat1 = 0; iScat1 < nScatA; ++iScat1) {
2096  if (PREPICKRESCATTER && iScat1 != iScatA) continue;
2097  int iA = scatteredA[iScat1];
2098  int id1Tmp = event[iA].id();
2099  for (int iScat2 = 0; iScat2 < nScatB; ++iScat2) {
2100  if (PREPICKRESCATTER && iScat2 != iScatB) continue;
2101  int iB = scatteredB[iScat2];
2102  int id2Tmp = event[iB].id();
2103 
2104  // Calculate current sHat and check whether big enough.
2105  double sHatTmp = (event[iA].p() + event[iB].p()).m2Calc();
2106  if (sHatTmp < 4. * pT2) continue;
2107 
2108  // Reconstruct other kinematical variables. (x values not needed.)
2109  double x1Tmp = event[iA].pPos() / eCM;
2110  double x2Tmp = event[iB].pNeg() / eCM;
2111  double tauTmp = sHatTmp / sCM;
2112  double root = sqrtpos(1. - xT2 / tauTmp);
2113  double tHatTmp = -0.5 * sHatTmp * (1. - root);
2114  double uHatTmp = -0.5 * sHatTmp * (1. + root);
2115 
2116  // Assign pointers to processes relevant for incoming flavour choice:
2117  // g + g, q + g, q + qbar (same flavour), q + q(bar) (the rest).
2118  if (id1Tmp == 21 && id2Tmp == 21) sigma2Tmp = &sigma2gg;
2119  else if (id1Tmp == 21 || id2Tmp == 21) sigma2Tmp = &sigma2qg;
2120  else if (id1Tmp == -id2Tmp) sigma2Tmp = &sigma2qqbarSame;
2121  else sigma2Tmp = &sigma2qq;
2122 
2123  // Evaluate cross sections, include possibility of K factor.
2124  // Use kinematics for two symmetrical configurations (tHat <-> uHat).
2125  // (Not necessary, but makes for better MC efficiency.)
2126  double dSigmaPartonCorr = Kfactor
2127  * sigma2Tmp->sigma( id1Tmp, id2Tmp, x1Tmp, x2Tmp, sHatTmp, tHatTmp,
2128  uHatTmp, alpS, alpEM);
2129 
2130  // Combine cross section and Jacobian tHat -> pT2
2131  // (with safety minvalue).
2132  double dSigmaCorr = dSigmaPartonCorr / max(ROOTMIN, root);
2133 
2134  // Dampen cross section at small pT values; part of formalism.
2135  // Use pT2 corrected for massive kinematics at this step.
2136  //?? double pT2massive = dSigmaDtSel->pT2MPI();
2137  double pT2massive = pT2;
2138  dSigmaCorr *= pow2( pT2massive / (pT2massive + pT20) );
2139 
2140  // Compensate for prepicked rescattering if appropriate.
2141  if (PREPICKRESCATTER) dSigmaCorr *= nScatA * nScatB;
2142 
2143  // Sum up total contribution for all scatterings or rescattering only.
2144  dSigmaSum += dSigmaCorr;
2145  dSigmaResc += dSigmaCorr;
2146 
2147  // Determine whether current rescattering should be selected.
2148  if (dSigmaCorr > rndmPtr->flat() * dSigmaSum) {
2149  i1Sel = iA;
2150  i2Sel = iB;
2151  id1Sel = id1Tmp;
2152  id2Sel = id2Tmp;
2153  x1Sel = x1Tmp;
2154  x2Sel = x2Tmp;
2155  sHatSel = sHatTmp;
2156  tHatSel = tHatTmp;
2157  uHatSel = uHatTmp;
2158  sigma2Sel = sigma2Tmp;
2159  pickOtherSel = sigma2Tmp->pickedOther();
2160  }
2161  }
2162  }
2163  }
2164 
2165  // Done.
2166  return dSigmaResc;
2167 }
2168 
2169 
2170 //--------------------------------------------------------------------------
2171 
2172 // Calculate factor relating matter overlap and interaction rate,
2173 // i.e. k in <n_interaction(b)> = k * overlap(b) (neglecting
2174 // n_int = 0 corrections and energy-momentum conservation effects).
2175 
2176 void MultipartonInteractions::overlapInit() {
2177 
2178  // Initial values for iteration. Step size of b integration.
2179  nAvg = sigmaInt / sigmaND;
2180  kNow = 0.5;
2181  int stepDir = 1;
2182  double deltaB = BSTEP;
2183  if (bProfile == 2) deltaB *= min( 0.5, 2.5 * coreRadius);
2184  if (bProfile == 3) deltaB *= max(1., pow(2. / expPow, 1. / expPow));
2185 
2186  // Further variables, with dummy initial values.
2187  double nNow = 0.;
2188  double kLow = 0.;
2189  double nLow = 0.;
2190  double kHigh = 0.;
2191  double nHigh = 0.;
2192  double overlapNow = 0.;
2193  double probNow = 0.;
2194  double overlapInt = 0.5;
2195  double overlap2Int = 0.;
2196  double probInt = 0.;
2197  double probOverlapInt = 0.;
2198  double bProbInt = 0.;
2199  normPi = 1. / (2. * M_PI);
2200 
2201  // Subdivision into low-b and high-b region by interaction rate.
2202  bool pastBDiv = false;
2203  double overlapHighB = 0.;
2204 
2205  // For x-dependent matter profile, try to find a0 rather than k.
2206  // Existing framework is used, but with substitutions:
2207  // a0 tuned according to Int( Pint(b), d^2b ) = sigmaND,
2208  // nAvg = sigmaND, kNow = a0now, kLow = a0low, kHigh = a0high,
2209  // nNow = probInt, nLow = probIntLow, nHigh = probIntHigh.
2210  double rescale2 = 1.;
2211  if (bProfile == 4) {
2212  nAvg = sigmaND;
2213  kNow = XDEP_A0 / 2.0;
2214  }
2215 
2216  // First close k into an interval by binary steps,
2217  // then find k by successive interpolation.
2218  do {
2219  if (stepDir == 1) kNow *= 2.;
2220  else if (stepDir == -1) kNow *= 0.5;
2221  else kNow = kLow + (nAvg - nLow) * (kHigh - kLow) / (nHigh - nLow);
2222 
2223  // Overlap trivial if no impact parameter dependence.
2224  if (bProfile <= 0 || bProfile > 4) {
2225  probInt = 0.5 * M_PI * (1. - exp(-kNow));
2226  probOverlapInt = probInt / M_PI;
2227  bProbInt = probInt;
2228 
2229  // Ratio of b-integrated k * overlap / (1 - exp( - k * overlap)).
2230  nNow = M_PI * kNow * overlapInt / probInt;
2231 
2232  // Else integrate overlap over impact parameter.
2233  } else if (bProfile < 4) {
2234 
2235  // Reset integrals.
2236  overlapInt = (bProfile == 3) ? 0. : 0.5;
2237  overlap2Int = 0.;
2238  probInt = 0.;
2239  probOverlapInt = 0.;
2240  bProbInt = 0.;
2241  pastBDiv = false;
2242  overlapHighB = 0.;
2243 
2244  // Step in b space.
2245  double b = -0.5 * deltaB;
2246  double bArea = 0.;
2247  do {
2248  b += deltaB;
2249  bArea = 2. * M_PI * b * deltaB;
2250 
2251  // Evaluate overlap at current b value.
2252  if (bProfile == 1) {
2253  overlapNow = normPi * exp( -b*b);
2254  } else if (bProfile == 2) {
2255  overlapNow = normPi * ( fracA * exp( -min(EXPMAX, b*b))
2256  + fracB * exp( -min(EXPMAX, b*b / radius2B)) / radius2B
2257  + fracC * exp( -min(EXPMAX, b*b / radius2C)) / radius2C );
2258  } else {
2259  overlapNow = normPi * exp( -pow( b, expPow));
2260  overlapInt += bArea * overlapNow;
2261  }
2262  if (pastBDiv) overlapHighB += bArea * overlapNow;
2263 
2264  // Calculate interaction probability and integrate.
2265  probNow = 1. - exp( -min(EXPMAX, M_PI * kNow * overlapNow));
2266  overlap2Int += bArea * pow2(overlapNow);
2267  probInt += bArea * probNow;
2268  probOverlapInt += bArea * overlapNow * probNow;
2269  bProbInt += b * bArea * probNow;
2270 
2271  // Check when interaction probability has dropped sufficiently.
2272  if (!pastBDiv && probNow < PROBATLOWB) {
2273  bDiv = b + 0.5 * deltaB;
2274  pastBDiv = true;
2275  }
2276 
2277  // Continue out in b until overlap too small.
2278  } while (b < 1. || b * probNow > BMAX);
2279 
2280  // Ratio of b-integrated k * overlap / (1 - exp( - k * overlap)).
2281  nNow = M_PI * kNow * overlapInt / probInt;
2282 
2283  // x-dependent matter profile.
2284  } else if (bProfile == 4) {
2285  rescale2 = pow2(kNow / XDEP_A0);
2286  probInt = 0.;
2287  double b = 0.5 * bstepNow;
2288  for (int bBin = 0; bBin < XDEP_BBIN; bBin++) {
2289  double bArea = 2. * M_PI * b * bstepNow;
2290  double pIntNow = 1 - exp( -min(EXPMAX, sigmaIntWgt[bBin] / rescale2) );
2291  probInt += bArea * rescale2 * pIntNow;
2292  b += bstepNow;
2293  }
2294  nNow = probInt;
2295  }
2296 
2297  // Replace lower or upper limit of k.
2298  if (nNow < nAvg) {
2299  kLow = kNow;
2300  nLow = nNow;
2301  if (stepDir == -1) stepDir = 0;
2302  } else {
2303  kHigh = kNow;
2304  nHigh = nNow;
2305  if (stepDir == 1) stepDir = -1;
2306  }
2307 
2308  // Continue iteration until convergence.
2309  } while (abs(nNow - nAvg) > KCONVERGE * nAvg);
2310 
2311  // Save relevant final numbers for overlap values.
2312  if (bProfile >= 0 && bProfile < 4) {
2313  double avgOverlap = probOverlapInt / probInt;
2314  zeroIntCorr = probOverlapInt / overlapInt;
2315  normOverlap = normPi * zeroIntCorr / avgOverlap;
2316  bAvg = bProbInt / probInt;
2317  enhanceBavg = (overlap2Int * probInt) / pow2(overlapInt);
2318 
2319  // Values for x-dependent matter profile.
2320  } else if (bProfile == 4) {
2321  // bAvg = Int(b * Pint(b), d2b) / sigmaND.
2322  // zeroIntCorr = Int(<n(b)> * Pint(b), d2b) / sigmaInt.
2323  bAvg = 0.;
2324  zeroIntCorr = 0.;
2325  double b = 0.5 * bstepNow;
2326  for (int bBin = 0; bBin < XDEP_BBIN; bBin++) {
2327  double bArea = 2. * M_PI * b * bstepNow;
2328  double pIntNow = 1. - exp( -min(EXPMAX, sigmaIntWgt[bBin] / rescale2) );
2329  bAvg += sqrt(rescale2) * b * bArea * rescale2 * pIntNow;
2330  zeroIntCorr += bArea * sigmaIntWgt[bBin] * pIntNow;
2331  b += bstepNow;
2332  }
2333  bAvg /= nNow;
2334  zeroIntCorr /= sigmaInt;
2335 
2336  // Other required values.
2337  a0now = kNow;
2338  infoPtr->seta0MPI(a0now * XDEP_SMB2FM);
2339  a02now = a0now * a0now;
2340  double xMin = 2. * pTmin / infoPtr->eCM();
2341  a2max = a0now * (XDEP_A1 + a1 * log(1. / xMin));
2342  a2max *= a2max;
2343  }
2344 
2345  // Relative rates for preselection of low-b and high-b region.
2346  // Other useful combinations for subsequent selection.
2347  if (bProfile > 0 && bProfile <= 3) {
2348  probLowB = M_PI * bDiv*bDiv;
2349  double probHighB = M_PI * kNow * overlapHighB;
2350  if (bProfile == 1) probHighB = M_PI * kNow * 0.5 * exp( -bDiv*bDiv);
2351  else if (bProfile == 2) {
2352  fracAhigh = fracA * exp( -bDiv*bDiv);
2353  fracBhigh = fracB * exp( -bDiv*bDiv / radius2B);
2354  fracChigh = fracC * exp( -bDiv*bDiv / radius2C);
2355  fracABChigh = fracAhigh + fracBhigh + fracChigh;
2356  probHighB = M_PI * kNow * 0.5 * fracABChigh;
2357  } else {
2358  cDiv = pow( bDiv, expPow);
2359  cMax = max(2. * expRev, cDiv);
2360  }
2361  probLowB /= (probLowB + probHighB);
2362  }
2363 
2364 }
2365 
2366 //--------------------------------------------------------------------------
2367 
2368 // Pick impact parameter and interaction rate enhancement beforehand,
2369 // i.e. before even the hardest interaction for minimum-bias events.
2370 
2371 void MultipartonInteractions::overlapFirst() {
2372 
2373  // Trivial values if no impact parameter dependence.
2374  if (bProfile <= 0 || bProfile > 4) {
2375  bNow = 1.;
2376  enhanceB = enhanceBmax = enhanceBnow = zeroIntCorr;
2377  bIsSet = true;
2378  isAtLowB = true;
2379  return;
2380  }
2381 
2382  // Possibility for user to set impact parameter. Evaluate overlap.
2383  double overlapNow = 0.;
2384  if ( userHooksPtr && userHooksPtr->canSetImpactParameter() ) {
2385  bNow = userHooksPtr->doSetImpactParameter() * bAvg;
2386  isAtLowB = ( bNow < bDiv );
2387 
2388  if (bProfile == 1) overlapNow = normPi * exp( -min(EXPMAX, bNow*bNow));
2389  else if (bProfile == 2) overlapNow = normPi *
2390  ( fracA * exp( -min(EXPMAX, bNow*bNow))
2391  + fracB * exp( -min(EXPMAX, bNow*bNow / radius2B)) / radius2B
2392  + fracC * exp( -min(EXPMAX, bNow*bNow / radius2C)) / radius2C );
2393  else overlapNow = normPi * exp( -pow( bNow, expPow));
2394  // Same enhancement for hardest process and all subsequent MPI.
2395  enhanceB = enhanceBmax = enhanceBnow = (normOverlap / normPi) * overlapNow;
2396 
2397  // Done.
2398  bNow /= bAvg;
2399  bIsSet = true;
2400  return;
2401  }
2402 
2403  // Preliminary choice between and inside low-b and high-b regions.
2404  double probAccept = 0.;
2405  do {
2406 
2407  // Treatment in low-b region: pick b flat in area.
2408  if (rndmPtr->flat() < probLowB) {
2409  isAtLowB = true;
2410  bNow = bDiv * sqrt(rndmPtr->flat());
2411 
2412  // Evaluate overlap and from that acceptance probability.
2413  if (bProfile == 1) overlapNow = normPi * exp( -bNow*bNow);
2414  else if (bProfile == 2) overlapNow = normPi *
2415  ( fracA * exp( -bNow*bNow)
2416  + fracB * exp( -bNow*bNow / radius2B) / radius2B
2417  + fracC * exp( -bNow*bNow / radius2C) / radius2C );
2418  else overlapNow = normPi * exp( -pow( bNow, expPow));
2419  probAccept = 1. - exp( -min(EXPMAX, M_PI * kNow * overlapNow));
2420 
2421  // Treatment in high-b region: pick b according to overlap.
2422  } else {
2423  isAtLowB = false;
2424 
2425  // For simple and double Gaussian pick b according to exp(-b^2 / r^2).
2426  if (bProfile == 1) {
2427  bNow = sqrt(bDiv*bDiv - log(rndmPtr->flat()));
2428  overlapNow = normPi * exp( -min(EXPMAX, bNow*bNow));
2429  } else if (bProfile == 2) {
2430  double pickFrac = rndmPtr->flat() * fracABChigh;
2431  if (pickFrac < fracAhigh)
2432  bNow = sqrt(bDiv*bDiv - log(rndmPtr->flat()));
2433  else if (pickFrac < fracAhigh + fracBhigh)
2434  bNow = sqrt(bDiv*bDiv - radius2B * log(rndmPtr->flat()));
2435  else bNow = sqrt(bDiv*bDiv - radius2C * log(rndmPtr->flat()));
2436  overlapNow = normPi * ( fracA * exp( -min(EXPMAX, bNow*bNow))
2437  + fracB * exp( -min(EXPMAX, bNow*bNow / radius2B)) / radius2B
2438  + fracC * exp( -min(EXPMAX, bNow*bNow / radius2C)) / radius2C );
2439 
2440  // For exp( - b^expPow) transform to variable c = b^expPow so that
2441  // f(b) = b * exp( - b^expPow) -> f(c) = c^r * exp(-c) with r = expRev.
2442  // case hasLowPow: expPow < 2 <=> r > 0: preselect according to
2443  // f(c) < N exp(-c/2) and then accept with N' * c^r * exp(-c/2).
2444  } else if (hasLowPow) {
2445  double cNow, acceptC;
2446  do {
2447  cNow = cDiv - 2. * log(rndmPtr->flat());
2448  acceptC = pow(cNow / cMax, expRev) * exp( -0.5 * (cNow - cMax));
2449  } while (acceptC < rndmPtr->flat());
2450  bNow = pow( cNow, 1. / expPow);
2451  overlapNow = normPi * exp( -cNow);
2452 
2453  // case !hasLowPow: expPow >= 2 <=> - 1 < r < 0: preselect according to
2454  // f(c) < N exp(-c) and then accept with N' * c^r.
2455  } else {
2456  double cNow, acceptC;
2457  do {
2458  cNow = cDiv - log(rndmPtr->flat());
2459  acceptC = pow(cNow / cDiv, expRev);
2460  } while (acceptC < rndmPtr->flat());
2461  bNow = pow( cNow, 1. / expPow);
2462  overlapNow = normPi * exp( -cNow);
2463  }
2464  double temp = M_PI * kNow *overlapNow;
2465  probAccept = (1. - exp( -min(EXPMAX, temp))) / temp;
2466  }
2467 
2468  // Confirm choice of b value. Derive enhancement factor.
2469  } while (probAccept < rndmPtr->flat());
2470 
2471  // Same enhancement for hardest process and all subsequent MPI
2472  enhanceB = enhanceBmax = enhanceBnow = (normOverlap / normPi) * overlapNow;
2473 
2474  // Done.
2475  bNow /= bAvg;
2476  bIsSet = true;
2477 
2478 }
2479 
2480 //--------------------------------------------------------------------------
2481 
2482 // Pick impact parameter and interaction rate enhancement afterwards,
2483 // i.e. after a hard interaction is known but before rest of MPI treatment.
2484 
2485 void MultipartonInteractions::overlapNext(Event& event, double pTscale,
2486  bool rehashB) {
2487 
2488  // Special case for hard diffraction if unchanged/related b.
2489  if (rehashB && bSelHard < 3) {
2490 
2491  // One option: bring b closer to its average value.
2492  bNow = infoPtr->bMPI();
2493  if (bSelHard == 2) bNow = sqrt(bNow);
2494  bNow *= bAvg;
2495  double b2 = bNow * bNow;
2496 
2497  // Caclulate new overlap enhancement factor.
2498  if (bProfile == 1) {
2499  double expb2 = exp( -min(EXPMAX, b2));
2500  enhanceB = enhanceBmax = enhanceBnow = normOverlap * expb2;
2501  } else if (bProfile == 2) {
2502  enhanceB = enhanceBmax = enhanceBnow = normOverlap *
2503  ( fracA * exp( -min(EXPMAX, b2))
2504  + fracB * exp( -min(EXPMAX, b2 / radius2B)) / radius2B
2505  + fracC * exp( -min(EXPMAX, b2 / radius2C)) / radius2C );
2506  } else {
2507  double cNow = pow( bNow, expPow);
2508  enhanceB = enhanceBmax = enhanceBnow = normOverlap * exp(-cNow);
2509  }
2510 
2511  // Done for simple cases.
2512  bNow /= bAvg;
2513  bIsSet = true;
2514  return;
2515  }
2516 
2517  // Default, valid for bProfile = 0. Also initial Sudakov.
2518  enhanceB = enhanceBmax = enhanceBnow = zeroIntCorr;
2519  if (bProfile <= 0 || bProfile > 4) return;
2520 
2521  // Alternative choices of event scale for Sudakov in (pT, b) space.
2522  if (bSelScale == 1) {
2523  vector<double> mmT;
2524  for (int i = 5; i < event.size(); ++i) if (event[i].isFinal()) {
2525  mmT.push_back( event[i].m() + event[i].mT() );
2526  for (int j = int(mmT.size()) - 1; j > 0; --j)
2527  if (mmT[j] > mmT[j - 1]) swap( mmT[j], mmT[j - 1] );
2528  }
2529  pTscale = 0.5 * mmT[0];
2530  for (int j = 1; j < int(mmT.size()); ++j) pTscale += mmT[j] / (j + 1.);
2531  } else if (bSelScale == 2) pTscale = event.scale();
2532  double pT2scale = pTscale*pTscale;
2533 
2534  // Use trial interaction for x-dependent matter profile.
2535  if (bProfile == 4) {
2536  double pTtrial = 0.;
2537  do {
2538  // Pick b according to wanted O(b, x1, x2).
2539  double expb2 = rndmPtr->flat();
2540  double w1 = XDEP_A1 + a1 * log(1. / infoPtr->x1());
2541  double w2 = XDEP_A1 + a1 * log(1. / infoPtr->x2());
2542  double fac = a02now * (w1 * w1 + w2 * w2);
2543  b2now = - fac * log(expb2);
2544  bNow = sqrt(b2now);
2545 
2546  // Enhancement factor for the hard process and overestimate
2547  // for fastPT2. Note that existing framework has a (1. / sigmaND)
2548  // present.
2549  enhanceB = sigmaND / M_PI / fac * expb2;
2550  enhanceBmax = sigmaND / 2. / M_PI / a02now
2551  * exp( -b2now / 2. / a2max );
2552 
2553  // Trial interaction. Keep going until pTtrial < pTscale.
2554  pTtrial = pTnext(pTmax, pTmin, event);
2555  } while (pTtrial > pTscale);
2556  bNow /= bAvg;
2557  bIsSet = true;
2558  return;
2559  }
2560 
2561  // Begin loop over pT-dependent rejection of b value.
2562  do {
2563 
2564  // Flat enhancement distribution for simple Gaussian.
2565  if (bProfile == 1) {
2566  double expb2 = rndmPtr->flat();
2567  // Same enhancement for hardest process and all subsequent MPI.
2568  enhanceB = enhanceBmax = enhanceBnow = normOverlap * expb2;
2569  bNow = sqrt( -log(expb2));
2570 
2571  // For double Gaussian go the way via b, according to each Gaussian.
2572  } else if (bProfile == 2) {
2573  double bType = rndmPtr->flat();
2574  double b2 = -log( rndmPtr->flat() );
2575  if (bType < fracA) ;
2576  else if (bType < fracA + fracB) b2 *= radius2B;
2577  else b2 *= radius2C;
2578  // Same enhancement for hardest process and all subsequent MPI.
2579  enhanceB = enhanceBmax = enhanceBnow = normOverlap *
2580  ( fracA * exp( -min(EXPMAX, b2))
2581  + fracB * exp( -min(EXPMAX, b2 / radius2B)) / radius2B
2582  + fracC * exp( -min(EXPMAX, b2 / radius2C)) / radius2C );
2583  bNow = sqrt(b2);
2584 
2585  // For exp( - b^expPow) transform to variable c = b^expPow so that
2586  // f(b) = b * exp( - b^expPow) -> f(c) = c^r * exp(-c) with r = expRev.
2587  // case hasLowPow: expPow < 2 <=> r > 0:
2588  // f(c) < r^r exp(-r) for c < 2r, < (2r)^r exp(-r-c/2) for c > 2r.
2589  } else if (bProfile == 3 && hasLowPow) {
2590  double cNow, acceptC;
2591  double probLowC = expRev / (expRev + pow(2., expRev) * exp( - expRev));
2592  do {
2593  if (rndmPtr->flat() < probLowC) {
2594  cNow = 2. * expRev * rndmPtr->flat();
2595  acceptC = pow( cNow / expRev, expRev) * exp(expRev - cNow);
2596  } else {
2597  cNow = 2. * (expRev - log( rndmPtr->flat() ));
2598  acceptC = pow(0.5 * cNow / expRev, expRev)
2599  * exp(expRev - 0.5 * cNow);
2600  }
2601  } while (acceptC < rndmPtr->flat());
2602  // Same enhancement for hardest process and all subsequent MPI.
2603  enhanceB = enhanceBmax = enhanceBnow = normOverlap *exp(-cNow);
2604  bNow = pow( cNow, 1. / expPow);
2605 
2606  // case !hasLowPow: expPow >= 2 <=> - 1 < r < 0:
2607  // f(c) < c^r for c < 1, f(c) < exp(-c) for c > 1.
2608  } else if (bProfile == 3 && !hasLowPow) {
2609  double cNow, acceptC;
2610  double probLowC = expPow / (2. * exp(-1.) + expPow);
2611  do {
2612  if (rndmPtr->flat() < probLowC) {
2613  cNow = pow( rndmPtr->flat(), 0.5 * expPow);
2614  acceptC = exp(-cNow);
2615  } else {
2616  cNow = 1. - log( rndmPtr->flat() );
2617  acceptC = pow( cNow, expRev);
2618  }
2619  } while (acceptC < rndmPtr->flat());
2620  // Same enhancement for hardest process and all subsequent MPI.
2621  enhanceB = enhanceBmax = enhanceBnow = normOverlap * exp(-cNow);
2622  bNow = pow( cNow, 1. / expPow);
2623  }
2624 
2625  // Evaluate "Sudakov form factor" for not having a harder interaction.
2626  } while (sudakov(pT2scale, enhanceB) < rndmPtr->flat());
2627 
2628  // Done.
2629  bNow /= bAvg;
2630  bIsSet = true;
2631 }
2632 
2633 //--------------------------------------------------------------------------
2634 
2635 // Print statistics on number of multiparton-interactions processes.
2636 
2637 void MultipartonInteractions::statistics(bool resetStat) {
2638 
2639  // Header.
2640  cout << "\n *------- PYTHIA Multiparton Interactions Statistics -----"
2641  << "---*\n"
2642  << " | "
2643  << " |\n"
2644  << " | Note: excludes hardest subprocess if already listed above "
2645  << " |\n"
2646  << " | "
2647  << " |\n"
2648  << " | Subprocess Code | Times"
2649  << " |\n"
2650  << " | | "
2651  << " |\n"
2652  << " |------------------------------------------------------------"
2653  << "-|\n"
2654  << " | | "
2655  << " |\n";
2656 
2657  // Loop over existing processes. Sum of all subprocesses.
2658  int numberSum = 0;
2659  for ( map<int, int>::iterator iter = nGen.begin(); iter != nGen.end();
2660  ++iter) {
2661  int code = iter -> first;
2662  int number = iter->second;
2663  numberSum += number;
2664 
2665  // Find process name that matches code.
2666  string name = " ";
2667  bool foundName = false;
2668  SigmaMultiparton* dSigma;
2669  for (int i = 0; i < 4; ++i) {
2670  if (i == 0) dSigma = &sigma2gg;
2671  else if (i == 1) dSigma = &sigma2qg;
2672  else if (i == 2) dSigma = &sigma2qqbarSame;
2673  else dSigma = &sigma2qq;
2674  int nProc = dSigma->nProc();
2675  for (int iProc = 0; iProc < nProc; ++iProc)
2676  if (dSigma->codeProc(iProc) == code) {
2677  name = dSigma->nameProc(iProc);
2678  foundName = true;
2679  }
2680  if (foundName) break;
2681  }
2682 
2683  // Print individual process info.
2684  cout << " | " << left << setw(40) << name << right << setw(5) << code
2685  << " | " << setw(11) << number << " |\n";
2686  }
2687 
2688  // Print summed process info.
2689  cout << " | "
2690  << " |\n"
2691  << " | " << left << setw(45) << "sum" << right << " | " << setw(11)
2692  << numberSum << " |\n";
2693 
2694  // Listing finished.
2695  cout << " | | "
2696  << " |\n"
2697  << " *------- End PYTHIA Multiparton Interactions Statistics ----"
2698  << "-*" << endl;
2699 
2700  // Optionally reset statistics contents.
2701  if (resetStat) resetStatistics();
2702 
2703 }
2704 
2705 //==========================================================================
2706 
2707 } // end namespace Pythia8
Definition: AgUStep.h:26