LCOV - code coverage report
Current view: top level - PYTHIA8/pythia8210dev/src - MultipartonInteractions.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 1331 0.1 %
Date: 2016-06-14 17:26:59 Functions: 1 22 4.5 %

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

Generated by: LCOV version 1.11