StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
PhaseSpace.cc
1 // PhaseSpace.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2018 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // Function definitions (not found in the header) for the
7 // PhaseSpace and PhaseSpace2to2tauyz classes.
8 
9 #include "Pythia8/PhaseSpace.h"
10 
11 namespace Pythia8 {
12 
13 //==========================================================================
14 
15 // The PhaseSpace class.
16 // Base class for phase space generators.
17 
18 //--------------------------------------------------------------------------
19 
20 // Constants: could be changed here if desired, but normally should not.
21 // These are of technical nature, as described for each.
22 
23 // Number of trial maxima around which maximum search is performed.
24 const int PhaseSpace::NMAXTRY = 2;
25 
26 // Number of three-body trials in phase space optimization.
27 const int PhaseSpace::NTRY3BODY = 20;
28 
29 // Maximum cross section increase, just in case true maximum not found.
30 const double PhaseSpace::SAFETYMARGIN = 1.05;
31 
32 // Small number to avoid division by zero.
33 const double PhaseSpace::TINY = 1e-20;
34 
35 // Fraction of total weight that is shared evenly between all shapes.
36 const double PhaseSpace::EVENFRAC = 0.4;
37 
38 // Two cross sections with a small relative error are assumed same.
39 const double PhaseSpace::SAMESIGMA = 1e-6;
40 
41 // Do not allow resonance to have mass below 2 m_e.
42 const double PhaseSpace::MRESMINABS = 0.001;
43 
44 // Do not include resonances peaked too far outside allowed mass region.
45 const double PhaseSpace::WIDTHMARGIN = 20.;
46 
47 // Special optimization treatment when two resonances at almost same mass.
48 const double PhaseSpace::SAMEMASS = 0.01;
49 
50 // Minimum phase space left when kinematics constraints are combined.
51 const double PhaseSpace::MASSMARGIN = 0.01;
52 
53 // When using Breit-Wigners in 2 -> 2 raise maximum weight estimate.
54 const double PhaseSpace::EXTRABWWTMAX = 1.25;
55 
56 // Size of Breit-Wigner threshold region, for mass selection biasing.
57 const double PhaseSpace::THRESHOLDSIZE = 3.;
58 
59 // Step size in optimal-mass search, for mass selection biasing.
60 const double PhaseSpace::THRESHOLDSTEP = 0.2;
61 
62 // Minimal rapidity range for allowed open range (in 2 -> 3).
63 const double PhaseSpace::YRANGEMARGIN = 1e-6;
64 
65 // Cutoff for f_e^e at x < 1 - 10^{-10} to be used in phase space selection.
66 // Note: the ...MIN quantities come from 1 - x_max or 1 - tau_max.
67 const double PhaseSpace::LEPTONXMIN = 1e-10;
68 const double PhaseSpace::LEPTONXMAX = 1. - 1e-10;
69 const double PhaseSpace::LEPTONXLOGMIN = log(1e-10);
70 const double PhaseSpace::LEPTONXLOGMAX = log(1. - 1e-10);
71 const double PhaseSpace::LEPTONTAUMIN = 2e-10;
72 
73 // Safety to avoid division with unreasonably small value for z selection.
74 const double PhaseSpace::SHATMINZ = 1.;
75 
76 // Regularization for small pT2min in z = cos(theta) selection.
77 const double PhaseSpace::PT2RATMINZ = 0.0001;
78 
79 // These numbers are hardwired empirical parameters,
80 // intended to speed up the M-generator.
81 const double PhaseSpace::WTCORRECTION[11] = { 1., 1., 1.,
82  2., 5., 15., 60., 250., 1250., 7000., 50000. };
83 
84 //--------------------------------------------------------------------------
85 
86 // Perform simple initialization and store pointers.
87 
88 void PhaseSpace::init(bool isFirst, SigmaProcess* sigmaProcessPtrIn,
89  Info* infoPtrIn, Settings* settingsPtrIn, ParticleData* particleDataPtrIn,
90  Rndm* rndmPtrIn, BeamParticle* beamAPtrIn, BeamParticle* beamBPtrIn,
91  Couplings* couplingsPtrIn, SigmaTotal* sigmaTotPtrIn,
92  UserHooks* userHooksPtrIn) {
93 
94  // Store input pointers for future use.
95  sigmaProcessPtr = sigmaProcessPtrIn;
96  infoPtr = infoPtrIn;
97  settingsPtr = settingsPtrIn;
98  particleDataPtr = particleDataPtrIn;
99  rndmPtr = rndmPtrIn;
100  beamAPtr = beamAPtrIn;
101  beamBPtr = beamBPtrIn;
102  couplingsPtr = couplingsPtrIn;
103  sigmaTotPtr = sigmaTotPtrIn;
104  userHooksPtr = userHooksPtrIn;
105 
106  // Some commonly used beam information.
107  idA = beamAPtr->id();
108  idB = beamBPtr->id();
109  mA = beamAPtr->m();
110  mB = beamBPtr->m();
111  eCM = infoPtr->eCM();
112  s = eCM * eCM;
113 
114  // Flag if lepton beams, and if non-resolved ones.
115  hasLeptonBeamA = beamAPtr->isLepton();
116  hasLeptonBeamB = beamBPtr->isLepton();
117  hasTwoLeptonBeams = hasLeptonBeamA && hasLeptonBeamB;
118  hasOneLeptonBeam = (hasLeptonBeamA || hasLeptonBeamB) && !hasTwoLeptonBeams;
119  bool hasPointLepton = (hasLeptonBeamA && beamAPtr->isUnresolved())
120  || (hasLeptonBeamB && beamBPtr->isUnresolved());
121 
122  // Flags also for unresolved photons.
123  hasPointGammaA = beamAPtr->isGamma() && beamAPtr->isUnresolved();
124  hasPointGammaB = beamBPtr->isGamma() && beamBPtr->isUnresolved();
125  hasOnePointParticle = (hasOneLeptonBeam && hasPointLepton)
126  || ( hasPointGammaA && !hasPointGammaB)
127  || (!hasPointGammaA && hasPointGammaB);
128  hasTwoPointParticles = (hasTwoLeptonBeams && hasPointLepton)
129  || ( hasPointGammaA && hasPointGammaB);
130 
131  // Flag if photons from leptons.
132  bool beamHasResGamma = beamAPtr->hasResGamma() && beamBPtr->hasResGamma();
133 
134  // Set flags for (un)resolved photons according to gammaModes.
135  if ( beamAPtr->isGamma() && beamBPtr->isGamma() ) {
136 
137  int beamAGammaMode = beamAPtr->getGammaMode();
138  int beamBGammaMode = beamBPtr->getGammaMode();
139 
140  if ( beamAGammaMode == 2 && beamBGammaMode != 2 ) {
141  hasOnePointParticle = true;
142  hasPointGammaA = true;
143  }
144  if ( beamBGammaMode == 2 && beamAGammaMode != 2 ) {
145  hasOnePointParticle = true;
146  hasPointGammaB = true;
147  }
148  if ( beamAGammaMode == 2 && beamBGammaMode == 2 ) {
149  hasTwoPointParticles = true;
150  hasPointGammaA = true;
151  hasPointGammaB = true;
152  }
153  }
154 
155  // Standard phase space cuts.
156  if (isFirst || settingsPtr->flag("PhaseSpace:sameForSecond")) {
157  mHatGlobalMin = settingsPtr->parm("PhaseSpace:mHatMin");
158  mHatGlobalMax = settingsPtr->parm("PhaseSpace:mHatMax");
159  pTHatGlobalMin = settingsPtr->parm("PhaseSpace:pTHatMin");
160  pTHatGlobalMax = settingsPtr->parm("PhaseSpace:pTHatMax");
161 
162  // Optionally separate phase space cuts for second hard process.
163  } else {
164  mHatGlobalMin = settingsPtr->parm("PhaseSpace:mHatMinSecond");
165  mHatGlobalMax = settingsPtr->parm("PhaseSpace:mHatMaxSecond");
166  pTHatGlobalMin = settingsPtr->parm("PhaseSpace:pTHatMinSecond");
167  pTHatGlobalMax = settingsPtr->parm("PhaseSpace:pTHatMaxSecond");
168  }
169 
170  // Cutoff against divergences at pT -> 0.
171  pTHatMinDiverge = settingsPtr->parm("PhaseSpace:pTHatMinDiverge");
172 
173  // Special cut on DIS Q2 = -tHat.
174  Q2GlobalMin = settingsPtr->parm("PhaseSpace:Q2Min");
175  hasQ2Min = ( Q2GlobalMin >= pow2(pTHatMinDiverge) );
176 
177  // For photons from lepton beams match the cuts to gm+gm system cuts.
178  if ( beamHasResGamma ) {
179  double Wmax = settingsPtr->parm("Photon:Wmax");
180  if ( (mHatGlobalMax > Wmax) || mHatGlobalMax < 0.) mHatGlobalMax = Wmax;
181  }
182 
183  // When to use Breit-Wigners.
184  useBreitWigners = settingsPtr->flag("PhaseSpace:useBreitWigners");
185  minWidthBreitWigners = settingsPtr->parm("PhaseSpace:minWidthBreitWigners");
186 
187  // Whether generation is with variable energy.
188  doEnergySpread = settingsPtr->flag("Beams:allowMomentumSpread");
189 
190  // Flags for maximization information and violation handling.
191  showSearch = settingsPtr->flag("PhaseSpace:showSearch");
192  showViolation = settingsPtr->flag("PhaseSpace:showViolation");
193  increaseMaximum = settingsPtr->flag("PhaseSpace:increaseMaximum");
194 
195  // Know whether a Z0 is pure Z0 or admixed with gamma*.
196  gmZmodeGlobal = settingsPtr->mode("WeakZ0:gmZmode");
197 
198  // Flags if user should be allowed to reweight cross section.
199  canModifySigma = (userHooksPtr != 0)
200  ? userHooksPtr->canModifySigma() : false;
201  canBiasSelection = (userHooksPtr != 0)
202  ? userHooksPtr->canBiasSelection() : false;
203 
204  // Parameters for simplified reweighting of 2 -> 2 processes.
205  canBias2Sel = settingsPtr->flag("PhaseSpace:bias2Selection");
206  bias2SelPow = settingsPtr->parm("PhaseSpace:bias2SelectionPow");
207  bias2SelRef = settingsPtr->parm("PhaseSpace:bias2SelectionRef");
208  if (canBias2Sel) pTHatGlobalMin = max( pTHatGlobalMin, pTHatMinDiverge);
209 
210  // Default event-specific kinematics properties.
211  x1H = 1.;
212  x2H = 1.;
213  m3 = 0.;
214  m4 = 0.;
215  m5 = 0.;
216  s3 = m3 * m3;
217  s4 = m4 * m4;
218  s5 = m5 * m5;
219  mHat = eCM;
220  sH = s;
221  tH = 0.;
222  uH = 0.;
223  pTH = 0.;
224  theta = 0.;
225  phi = 0.;
226  runBW3H = 1.;
227  runBW4H = 1.;
228  runBW5H = 1.;
229 
230  // Default cross section information.
231  sigmaNw = 0.;
232  sigmaMx = 0.;
233  sigmaPos = 0.;
234  sigmaNeg = 0.;
235  newSigmaMx = false;
236  biasWt = 1.;
237 
238 }
239 
240 //--------------------------------------------------------------------------
241 
242 // Allow for nonisotropic decays when ME's available.
243 
244 void PhaseSpace::decayKinematics( Event& process) {
245 
246  // Identify sets of sister partons.
247  int iResEnd = 4;
248  for (int iResBeg = 5; iResBeg < process.size(); ++iResBeg) {
249  if (iResBeg <= iResEnd) continue;
250  iResEnd = iResBeg;
251  while ( iResEnd < process.size() - 1
252  && process[iResEnd + 1].mother1() == process[iResBeg].mother1()
253  && process[iResEnd + 1].mother2() == process[iResBeg].mother2() )
254  ++iResEnd;
255 
256  // Check that at least one of them is a resonance.
257  bool hasRes = false;
258  for (int iRes = iResBeg; iRes <= iResEnd; ++iRes)
259  if ( !process[iRes].isFinal() ) hasRes = true;
260  if ( !hasRes ) continue;
261 
262  // Evaluate matrix element and decide whether to keep kinematics.
263  double decWt = sigmaProcessPtr->weightDecay( process, iResBeg, iResEnd);
264  if (decWt < 0.) infoPtr->errorMsg("Warning in PhaseSpace::decay"
265  "Kinematics: negative angular weight");
266  if (decWt > 1.) infoPtr->errorMsg("Warning in PhaseSpace::decay"
267  "Kinematics: angular weight above unity");
268  while (decWt < rndmPtr->flat() ) {
269 
270  // Find resonances for which to redo decay angles.
271  for (int iRes = iResBeg; iRes < process.size(); ++iRes) {
272  if ( process[iRes].isFinal() ) continue;
273  int iResMother = iRes;
274  while (iResMother > iResEnd)
275  iResMother = process[iResMother].mother1();
276  if (iResMother < iResBeg) continue;
277 
278  // Do decay of this mother isotropically in phase space.
279  decayKinematicsStep( process, iRes);
280 
281  // End loop over resonance decay chains.
282  }
283 
284  // Ready to allow new test of matrix element.
285  decWt = sigmaProcessPtr->weightDecay( process, iResBeg, iResEnd);
286  if (decWt < 0.) infoPtr->errorMsg("Warning in PhaseSpace::decay"
287  "Kinematics: negative angular weight");
288  if (decWt > 1.) infoPtr->errorMsg("Warning in PhaseSpace::decay"
289  "Kinematics: angular weight above unity");
290  }
291 
292  // End loop over sets of sister resonances/partons.
293  }
294 
295 }
296 
297 //--------------------------------------------------------------------------
298 
299 // Reselect decay products momenta isotropically in phase space.
300 // Does not redo secondary vertex position!
301 
302 void PhaseSpace::decayKinematicsStep( Event& process, int iRes) {
303 
304  // Multiplicity and mother mass and four-momentum.
305  int i1 = process[iRes].daughter1();
306  int mult = process[iRes].daughter2() + 1 - i1;
307  double m0 = process[iRes].m();
308  Vec4 pRes = process[iRes].p();
309 
310  // Description of two-body decays as simple special case.
311  if (mult == 2) {
312 
313  // Products and product masses.
314  int i2 = i1 + 1;
315  double m1t = process[i1].m();
316  double m2t = process[i2].m();
317 
318  // Energies and absolute momentum in the rest frame.
319  double e1 = 0.5 * (m0*m0 + m1t*m1t - m2t*m2t) / m0;
320  double e2 = 0.5 * (m0*m0 + m2t*m2t - m1t*m1t) / m0;
321  double p12 = 0.5 * sqrtpos( (m0 - m1t - m2t) * (m0 + m1t + m2t)
322  * (m0 + m1t - m2t) * (m0 - m1t + m2t) ) / m0;
323 
324  // Pick isotropic angles to give three-momentum.
325  double cosTheta = 2. * rndmPtr->flat() - 1.;
326  double sinTheta = sqrt(1. - cosTheta*cosTheta);
327  double phi12 = 2. * M_PI * rndmPtr->flat();
328  double pX = p12 * sinTheta * cos(phi12);
329  double pY = p12 * sinTheta * sin(phi12);
330  double pZ = p12 * cosTheta;
331 
332  // Fill four-momenta in mother rest frame and then boost to lab frame.
333  Vec4 p1( pX, pY, pZ, e1);
334  Vec4 p2( -pX, -pY, -pZ, e2);
335  p1.bst( pRes );
336  p2.bst( pRes );
337 
338  // Done for two-body decay.
339  process[i1].p( p1 );
340  process[i2].p( p2 );
341  return;
342  }
343 
344  // Description of three-body decays as semi-simple special case.
345  if (mult == 3) {
346 
347  // Products and product masses.
348  int i2 = i1 + 1;
349  int i3 = i2 + 1;
350  double m1t = process[i1].m();
351  double m2t = process[i2].m();
352  double m3t = process[i3].m();
353  double mDiff = m0 - (m1t + m2t + m3t);
354 
355  // Kinematical limits for 2+3 mass. Maximum phase-space weight.
356  double m23Min = m2t + m3t;
357  double m23Max = m0 - m1t;
358  double p1Max = 0.5 * sqrtpos( (m0 - m1t - m23Min)
359  * (m0 + m1t + m23Min) * (m0 + m1t - m23Min)
360  * (m0 - m1t + m23Min) ) / m0;
361  double p23Max = 0.5 * sqrtpos( (m23Max - m2t - m3t)
362  * (m23Max + m2t + m3t) * (m23Max + m2t - m3t)
363  * (m23Max - m2t + m3t) ) / m23Max;
364  double wtPSmax = 0.5 * p1Max * p23Max;
365 
366  // Pick an intermediate mass m23 flat in the allowed range.
367  double wtPS, m23, p1Abs, p23Abs;
368  do {
369  m23 = m23Min + rndmPtr->flat() * mDiff;
370 
371  // Translate into relative momenta and find phase-space weight.
372  p1Abs = 0.5 * sqrtpos( (m0 - m1t - m23) * (m0 + m1t + m23)
373  * (m0 + m1t - m23) * (m0 - m1t + m23) ) / m0;
374  p23Abs = 0.5 * sqrtpos( (m23 - m2t - m3t) * (m23 + m2t + m3t)
375  * (m23 + m2t - m3t) * (m23 - m2t + m3t) ) / m23;
376  wtPS = p1Abs * p23Abs;
377 
378  // If rejected, try again with new invariant masses.
379  } while ( wtPS < rndmPtr->flat() * wtPSmax );
380 
381  // Set up m23 -> m2 + m3 isotropic in its rest frame.
382  double cosTheta = 2. * rndmPtr->flat() - 1.;
383  double sinTheta = sqrt(1. - cosTheta*cosTheta);
384  double phi23 = 2. * M_PI * rndmPtr->flat();
385  double pX = p23Abs * sinTheta * cos(phi23);
386  double pY = p23Abs * sinTheta * sin(phi23);
387  double pZ = p23Abs * cosTheta;
388  double e2 = sqrt( m2t*m2t + p23Abs*p23Abs);
389  double e3 = sqrt( m3t*m3t + p23Abs*p23Abs);
390  Vec4 p2( pX, pY, pZ, e2);
391  Vec4 p3( -pX, -pY, -pZ, e3);
392 
393  // Set up 0 -> 1 + 23 isotropic in its rest frame.
394  cosTheta = 2. * rndmPtr->flat() - 1.;
395  sinTheta = sqrt(1. - cosTheta*cosTheta);
396  phi23 = 2. * M_PI * rndmPtr->flat();
397  pX = p1Abs * sinTheta * cos(phi23);
398  pY = p1Abs * sinTheta * sin(phi23);
399  pZ = p1Abs * cosTheta;
400  double e1 = sqrt( m1t*m1t + p1Abs*p1Abs);
401  double e23 = sqrt( m23*m23 + p1Abs*p1Abs);
402  Vec4 p1( pX, pY, pZ, e1);
403 
404  // Boost 2 + 3 to the 0 rest frame and then boost to lab frame.
405  Vec4 p23( -pX, -pY, -pZ, e23);
406  p2.bst( p23 );
407  p3.bst( p23 );
408  p1.bst( pRes );
409  p2.bst( pRes );
410  p3.bst( pRes );
411 
412  // Done for three-body decay.
413  process[i1].p( p1 );
414  process[i2].p( p2 );
415  process[i3].p( p3 );
416  return;
417  }
418 
419  // Do a multibody decay using the M-generator algorithm.
420 
421  // Set up masses and four-momenta in a vector, with mother in slot 0.
422  vector<double> mProd;
423  mProd.push_back( m0);
424  for (int i = i1; i <= process[iRes].daughter2(); ++i)
425  mProd.push_back( process[i].m() );
426  vector<Vec4> pProd;
427  pProd.push_back( pRes);
428 
429  // Sum of daughter masses.
430  double mSum = mProd[1];
431  for (int i = 2; i <= mult; ++i) mSum += mProd[i];
432  double mDiff = m0 - mSum;
433 
434  // Begin setup of intermediate invariant masses.
435  vector<double> mInv;
436  for (int i = 0; i <= mult; ++i) mInv.push_back( mProd[i]);
437 
438  // Calculate the maximum weight in the decay.
439  double wtPSmax = 1. / WTCORRECTION[mult];
440  double mMaxWT = mDiff + mProd[mult];
441  double mMinWT = 0.;
442  for (int i = mult - 1; i > 0; --i) {
443  mMaxWT += mProd[i];
444  mMinWT += mProd[i+1];
445  double mNow = mProd[i];
446  wtPSmax *= 0.5 * sqrtpos( (mMaxWT - mMinWT - mNow)
447  * (mMaxWT + mMinWT + mNow) * (mMaxWT + mMinWT - mNow)
448  * (mMaxWT - mMinWT + mNow) ) / mMaxWT;
449  }
450 
451  // Begin loop to find the set of intermediate invariant masses.
452  vector<double> rndmOrd;
453  double wtPS;
454  do {
455  wtPS = 1.;
456 
457  // Find and order random numbers in descending order.
458  rndmOrd.resize(0);
459  rndmOrd.push_back(1.);
460  for (int i = 1; i < mult - 1; ++i) {
461  double rndm = rndmPtr->flat();
462  rndmOrd.push_back(rndm);
463  for (int j = i - 1; j > 0; --j) {
464  if (rndm > rndmOrd[j]) swap( rndmOrd[j], rndmOrd[j+1] );
465  else break;
466  }
467  }
468  rndmOrd.push_back(0.);
469 
470  // Translate into intermediate masses and find weight.
471  for (int i = mult - 1; i > 0; --i) {
472  mInv[i] = mInv[i+1] + mProd[i] + (rndmOrd[i-1] - rndmOrd[i]) * mDiff;
473  wtPS *= 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - mProd[i])
474  * (mInv[i] + mInv[i+1] + mProd[i]) * (mInv[i] + mInv[i+1] - mProd[i])
475  * (mInv[i] - mInv[i+1] + mProd[i]) ) / mInv[i];
476  }
477 
478  // If rejected, try again with new invariant masses.
479  } while ( wtPS < rndmPtr->flat() * wtPSmax );
480 
481  // Perform two-particle decays in the respective rest frame.
482  vector<Vec4> pInv;
483  pInv.resize(mult + 1);
484  for (int i = 1; i < mult; ++i) {
485  double p12 = 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - mProd[i])
486  * (mInv[i] + mInv[i+1] + mProd[i]) * (mInv[i] + mInv[i+1] - mProd[i])
487  * (mInv[i] - mInv[i+1] + mProd[i]) ) / mInv[i];
488 
489  // Isotropic angles give three-momentum.
490  double cosTheta = 2. * rndmPtr->flat() - 1.;
491  double sinTheta = sqrt(1. - cosTheta*cosTheta);
492  double phiLoc = 2. * M_PI * rndmPtr->flat();
493  double pX = p12 * sinTheta * cos(phiLoc);
494  double pY = p12 * sinTheta * sin(phiLoc);
495  double pZ = p12 * cosTheta;
496 
497  // Calculate energies, fill four-momenta.
498  double eHad = sqrt( mProd[i]*mProd[i] + p12*p12);
499  double eInv = sqrt( mInv[i+1]*mInv[i+1] + p12*p12);
500  pProd.push_back( Vec4( pX, pY, pZ, eHad) );
501  pInv[i+1].p( -pX, -pY, -pZ, eInv);
502  }
503  pProd.push_back( pInv[mult] );
504 
505  // Boost decay products to the mother rest frame and on to lab frame.
506  pInv[1] = pProd[0];
507  for (int iFrame = mult - 1; iFrame > 0; --iFrame)
508  for (int i = iFrame; i <= mult; ++i) pProd[i].bst(pInv[iFrame]);
509 
510  // Done for multibody decay.
511  for (int i = 1; i <= mult; ++i)
512  process[i1 + i - 1].p( pProd[i] );
513  return;
514 
515 }
516 
517 //--------------------------------------------------------------------------
518 
519 // Determine how 3-body phase space should be sampled.
520 
521 void PhaseSpace::setup3Body() {
522 
523  // Check for massive t-channel propagator particles.
524  int idTchan1 = abs( sigmaProcessPtr->idTchan1() );
525  int idTchan2 = abs( sigmaProcessPtr->idTchan2() );
526  mTchan1 = (idTchan1 == 0) ? pTHatMinDiverge
527  : particleDataPtr->m0(idTchan1);
528  mTchan2 = (idTchan2 == 0) ? pTHatMinDiverge
529  : particleDataPtr->m0(idTchan2);
530  sTchan1 = mTchan1 * mTchan1;
531  sTchan2 = mTchan2 * mTchan2;
532 
533  // Find coefficients of different pT2 selection terms. Mirror choice.
534  frac3Pow1 = sigmaProcessPtr->tChanFracPow1();
535  frac3Pow2 = sigmaProcessPtr->tChanFracPow2();
536  frac3Flat = 1. - frac3Pow1 - frac3Pow2;
537  useMirrorWeight = sigmaProcessPtr->useMirrorWeight();
538 
539 }
540 
541 //--------------------------------------------------------------------------
542 
543 // Determine how phase space should be sampled.
544 
545 bool PhaseSpace::setupSampling123(bool is2, bool is3) {
546 
547  // Optional printout.
548  if (showSearch) cout << "\n PYTHIA Optimization printout for "
549  << sigmaProcessPtr->name() << "\n \n" << scientific << setprecision(3);
550 
551  // Check that open range in tau (+ set tauMin, tauMax).
552  if (!limitTau(is2, is3)) return false;
553 
554  // Reset coefficients and matrices of equation system to solve.
555  int binTau[8], binY[8], binZ[8];
556  double vecTau[8], matTau[8][8], vecY[8], matY[8][8], vecZ[8], matZ[8][8];
557  for (int i = 0; i < 8; ++i) {
558  tauCoef[i] = 0.;
559  yCoef[i] = 0.;
560  zCoef[i] = 0.;
561  binTau[i] = 0;
562  binY[i] = 0;
563  binZ[i] = 0;
564  vecTau[i] = 0.;
565  vecY[i] = 0.;
566  vecZ[i] = 0.;
567  for (int j = 0; j < 8; ++j) {
568  matTau[i][j] = 0.;
569  matY[i][j] = 0.;
570  matZ[i][j] = 0.;
571  }
572  }
573  sigmaMx = 0.;
574  sigmaNeg = 0.;
575 
576  // Number of used coefficients/points for each dimension: tau, y, c.
577  nTau = (hasTwoPointParticles) ? 1 : 2;
578  nY = (hasOnePointParticle || hasTwoPointParticles) ? 1 : 5;
579  nZ = (is2) ? 5 : 1;
580 
581  // Identify if any resonances contribute in s-channel.
582  idResA = sigmaProcessPtr->resonanceA();
583  if (idResA != 0) {
584  mResA = particleDataPtr->m0(idResA);
585  GammaResA = particleDataPtr->mWidth(idResA);
586  if (mHatMin > mResA + WIDTHMARGIN * GammaResA || (mHatMax > 0.
587  && mHatMax < mResA - WIDTHMARGIN * GammaResA) ) idResA = 0;
588  }
589  idResB = sigmaProcessPtr->resonanceB();
590  if (idResB != 0) {
591  mResB = particleDataPtr->m0(idResB);
592  GammaResB = particleDataPtr->mWidth(idResB);
593  if (mHatMin > mResB + WIDTHMARGIN * GammaResB || (mHatMax > 0.
594  && mHatMax < mResB - WIDTHMARGIN * GammaResB) ) idResB = 0;
595  }
596  if (idResA == 0 && idResB != 0) {
597  idResA = idResB;
598  mResA = mResB;
599  GammaResA = GammaResB;
600  idResB = 0;
601  }
602 
603  // More sampling in tau if resonances in s-channel.
604  if (idResA !=0 && !hasTwoPointParticles) {
605  nTau += 2;
606  tauResA = mResA * mResA / s;
607  widResA = mResA * GammaResA / s;
608  }
609  if (idResB != 0 && !hasTwoPointParticles) {
610  nTau += 2;
611  tauResB = mResB * mResB / s;
612  widResB = mResB * GammaResB / s;
613  }
614 
615  // More sampling in tau (and different in y) if incoming lepton beams.
616  if (hasTwoLeptonBeams && !hasTwoPointParticles) ++nTau;
617 
618  // Special case when both resonances have same mass.
619  sameResMass = false;
620  if (idResB != 0 && abs(mResA - mResB) < SAMEMASS * (GammaResA + GammaResB))
621  sameResMass = true;
622 
623  // Default z value and weight required for 2 -> 1. Number of dimensions.
624  z = 0.;
625  wtZ = 1.;
626  int nVar = (is2) ? 3 : 2;
627 
628  // Initial values, to be modified later.
629  tauCoef[0] = 1.;
630  yCoef[1] = 0.5;
631  yCoef[2] = 0.5;
632  zCoef[0] = 1.;
633 
634  // Step through grid in tau. Set limits on y and z generation.
635  for (int iTau = 0; iTau < nTau; ++iTau) {
636  double posTau = 0.5;
637  if (sameResMass && iTau > 1 && iTau < 6) posTau = (iTau < 4) ? 0.4 : 0.6;
638  selectTau( iTau, posTau, is2);
639  if (!limitY()) continue;
640  if (is2 && !limitZ()) continue;
641 
642  // Step through grids in y and z.
643  for (int iY = 0; iY < nY; ++iY) {
644  selectY( iY, 0.5);
645  for (int iZ = 0; iZ < nZ; ++iZ) {
646  if (is2) selectZ( iZ, 0.5);
647  double sigmaTmp = 0.;
648 
649  // 2 -> 1: calculate cross section, weighted by phase-space volume.
650  if (!is2 && !is3) {
651  sigmaProcessPtr->set1Kin( x1H, x2H, sH);
652  sigmaTmp = sigmaProcessPtr->sigmaPDF(true);
653  sigmaTmp *= wtTau * wtY;
654 
655  // 2 -> 2: calculate cross section, weighted by phase-space volume
656  // and Breit-Wigners for masses
657  } else if (is2) {
658  sigmaProcessPtr->set2Kin( x1H, x2H, sH, tH, m3, m4,
659  runBW3H, runBW4H);
660  sigmaTmp = sigmaProcessPtr->sigmaPDF(true);
661  sigmaTmp *= wtTau * wtY * wtZ * wtBW;
662 
663  // 2 -> 3: repeat internal 3-body phase space several times and
664  // keep maximal cross section, weighted by phase-space volume
665  // and Breit-Wigners for masses
666  } else if (is3) {
667  for (int iTry3 = 0; iTry3 < NTRY3BODY; ++iTry3) {
668  if (!select3Body()) continue;
669  sigmaProcessPtr->set3Kin( x1H, x2H, sH, p3cm, p4cm, p5cm,
670  m3, m4, m5, runBW3H, runBW4H, runBW5H);
671  double sigmaTry = sigmaProcessPtr->sigmaPDF(true);
672  sigmaTry *= wtTau * wtY * wt3Body * wtBW;
673  if (sigmaTry > sigmaTmp) sigmaTmp = sigmaTry;
674  }
675  }
676 
677  // Allow possibility for user to modify cross section. (3body??)
678  if (canModifySigma) sigmaTmp
679  *= userHooksPtr->multiplySigmaBy( sigmaProcessPtr, this, false);
680  if (canBiasSelection) sigmaTmp
681  *= userHooksPtr->biasSelectionBy( sigmaProcessPtr, this, false);
682  if (canBias2Sel) sigmaTmp *= pow( pTH / bias2SelRef, bias2SelPow);
683 
684  // Check if current maximum exceeded.
685  if (sigmaTmp > sigmaMx) sigmaMx = sigmaTmp;
686 
687  // Optional printout. Protect against negative cross sections.
688  if (showSearch) cout << " tau =" << setw(11) << tau << " y ="
689  << setw(11) << y << " z =" << setw(11) << z
690  << " sigma =" << setw(11) << sigmaTmp << "\n";
691  if (sigmaTmp < 0.) sigmaTmp = 0.;
692 
693  // Sum up tau cross-section pieces in points used.
694  if (!hasTwoPointParticles) {
695  binTau[iTau] += 1;
696  vecTau[iTau] += sigmaTmp;
697  matTau[iTau][0] += 1. / intTau0;
698  matTau[iTau][1] += (1. / intTau1) / tau;
699  if (idResA != 0) {
700  matTau[iTau][2] += (1. / intTau2) / (tau + tauResA);
701  matTau[iTau][3] += (1. / intTau3)
702  * tau / ( pow2(tau - tauResA) + pow2(widResA) );
703  }
704  if (idResB != 0) {
705  matTau[iTau][4] += (1. / intTau4) / (tau + tauResB);
706  matTau[iTau][5] += (1. / intTau5)
707  * tau / ( pow2(tau - tauResB) + pow2(widResB) );
708  }
709  if (hasTwoLeptonBeams) matTau[iTau][nTau - 1] += (1. / intTau6)
710  * tau / max( LEPTONTAUMIN, 1. - tau);
711  }
712 
713  // Sum up y cross-section pieces in points used.
714  if (!hasOnePointParticle && !hasTwoPointParticles) {
715  binY[iY] += 1;
716  vecY[iY] += sigmaTmp;
717  matY[iY][0] += (yMax / intY0) / cosh(y);
718  matY[iY][1] += (yMax / intY12) * (y + yMax);
719  matY[iY][2] += (yMax / intY12) * (yMax - y);
720  if (!hasTwoLeptonBeams) {
721  matY[iY][3] += (yMax / intY34) * exp(y);
722  matY[iY][4] += (yMax / intY34) * exp(-y);
723  } else {
724  matY[iY][3] += (yMax / intY56)
725  / max( LEPTONXMIN, 1. - exp( y - yMax) );
726  matY[iY][4] += (yMax / intY56)
727  / max( LEPTONXMIN, 1. - exp(-y - yMax) );
728  }
729  }
730 
731  // Integrals over z expressions at tauMax, to be used below.
732  if (is2) {
733  double p2AbsMax = 0.25 * (pow2(tauMax * s - s3 - s4)
734  - 4. * s3 * s4) / (tauMax * s);
735  double zMaxMax = sqrtpos( 1. - pT2HatMin / p2AbsMax );
736  double zPosMaxMax = max(ratio34, unity34 + zMaxMax);
737  double zNegMaxMax = max(ratio34, unity34 - zMaxMax);
738  double intZ0Max = 2. * zMaxMax;
739  double intZ12Max = log( zPosMaxMax / zNegMaxMax);
740  double intZ34Max = 1. / zNegMaxMax - 1. / zPosMaxMax;
741 
742  // Sum up z cross-section pieces in points used.
743  binZ[iZ] += 1;
744  vecZ[iZ] += sigmaTmp;
745  matZ[iZ][0] += 1.;
746  matZ[iZ][1] += (intZ0Max / intZ12Max) / zNeg;
747  matZ[iZ][2] += (intZ0Max / intZ12Max) / zPos;
748  matZ[iZ][3] += (intZ0Max / intZ34Max) / pow2(zNeg);
749  matZ[iZ][4] += (intZ0Max / intZ34Max) / pow2(zPos);
750  }
751 
752  // End of loops over phase space points.
753  }
754  }
755  }
756 
757  // Fail if no non-vanishing cross sections.
758  if (sigmaMx <= 0.) {
759  sigmaMx = 0.;
760  return false;
761  }
762 
763 
764  // Solve respective equation system for better phase space coefficients.
765  if (!hasTwoPointParticles) solveSys( nTau, binTau, vecTau, matTau, tauCoef);
766  if (!hasOnePointParticle && !hasTwoPointParticles)
767  solveSys( nY, binY, vecY, matY, yCoef);
768  if (is2) solveSys( nZ, binZ, vecZ, matZ, zCoef);
769  if (showSearch) cout << "\n";
770 
771  // Provide cumulative sum of coefficients.
772  tauCoefSum[0] = tauCoef[0];
773  yCoefSum[0] = yCoef[0];
774  zCoefSum[0] = zCoef[0];
775  for (int i = 1; i < 8; ++ i) {
776  tauCoefSum[i] = tauCoefSum[i - 1] + tauCoef[i];
777  yCoefSum[i] = yCoefSum[i - 1] + yCoef[i];
778  zCoefSum[i] = zCoefSum[i - 1] + zCoef[i];
779  }
780  // The last element should be > 1 to be on safe side in selection below.
781  tauCoefSum[nTau - 1] = 2.;
782  yCoefSum[nY - 1] = 2.;
783  zCoefSum[nZ - 1] = 2.;
784 
785 
786  // Begin find two most promising maxima among same points as before.
787  int iMaxTau[NMAXTRY + 2], iMaxY[NMAXTRY + 2], iMaxZ[NMAXTRY + 2];
788  double sigMax[NMAXTRY + 2];
789  int nMax = 0;
790 
791  // Scan same grid as before in tau, y, z.
792  for (int iTau = 0; iTau < nTau; ++iTau) {
793  double posTau = 0.5;
794  if (sameResMass && iTau > 1 && iTau < 6) posTau = (iTau < 4) ? 0.4 : 0.6;
795  selectTau( iTau, posTau, is2);
796  if (!limitY()) continue;
797  if (is2 && !limitZ()) continue;
798  for (int iY = 0; iY < nY; ++iY) {
799  selectY( iY, 0.5);
800  for (int iZ = 0; iZ < nZ; ++iZ) {
801  if (is2) selectZ( iZ, 0.5);
802  double sigmaTmp = 0.;
803 
804  // 2 -> 1: calculate cross section, weighted by phase-space volume.
805  if (!is2 && !is3) {
806  sigmaProcessPtr->set1Kin( x1H, x2H, sH);
807  sigmaTmp = sigmaProcessPtr->sigmaPDF(true);
808  sigmaTmp *= wtTau * wtY;
809 
810  // 2 -> 2: calculate cross section, weighted by phase-space volume
811  // and Breit-Wigners for masses
812  } else if (is2) {
813  sigmaProcessPtr->set2Kin( x1H, x2H, sH, tH, m3, m4,
814  runBW3H, runBW4H);
815  sigmaTmp = sigmaProcessPtr->sigmaPDF(true);
816  sigmaTmp *= wtTau * wtY * wtZ * wtBW;
817 
818  // 2 -> 3: repeat internal 3-body phase space several times and
819  // keep maximal cross section, weighted by phase-space volume
820  // and Breit-Wigners for masses
821  } else if (is3) {
822  for (int iTry3 = 0; iTry3 < NTRY3BODY; ++iTry3) {
823  if (!select3Body()) continue;
824  sigmaProcessPtr->set3Kin( x1H, x2H, sH, p3cm, p4cm, p5cm,
825  m3, m4, m5, runBW3H, runBW4H, runBW5H);
826  double sigmaTry = sigmaProcessPtr->sigmaPDF(true);
827  sigmaTry *= wtTau * wtY * wt3Body * wtBW;
828  if (sigmaTry > sigmaTmp) sigmaTmp = sigmaTry;
829  }
830  }
831 
832  // Allow possibility for user to modify cross section. (3body??)
833  if (canModifySigma) sigmaTmp
834  *= userHooksPtr->multiplySigmaBy( sigmaProcessPtr, this, false);
835  if (canBiasSelection) sigmaTmp
836  *= userHooksPtr->biasSelectionBy( sigmaProcessPtr, this, false);
837  if (canBias2Sel) sigmaTmp *= pow( pTH / bias2SelRef, bias2SelPow);
838 
839  // Optional printout. Protect against negative cross section.
840  if (showSearch) cout << " tau =" << setw(11) << tau << " y ="
841  << setw(11) << y << " z =" << setw(11) << z
842  << " sigma =" << setw(11) << sigmaTmp << "\n";
843  if (sigmaTmp < 0.) sigmaTmp = 0.;
844 
845  // Check that point is not simply mirror of already found one.
846  bool mirrorPoint = false;
847  for (int iMove = 0; iMove < nMax; ++iMove)
848  if (abs(sigmaTmp - sigMax[iMove]) < SAMESIGMA
849  * (sigmaTmp + sigMax[iMove])) mirrorPoint = true;
850 
851  // Add to or insert in maximum list. Only first two count.
852  if (!mirrorPoint) {
853  int iInsert = 0;
854  for (int iMove = nMax - 1; iMove >= -1; --iMove) {
855  iInsert = iMove + 1;
856  if (iInsert == 0 || sigmaTmp < sigMax[iMove]) break;
857  iMaxTau[iMove + 1] = iMaxTau[iMove];
858  iMaxY[iMove + 1] = iMaxY[iMove];
859  iMaxZ[iMove + 1] = iMaxZ[iMove];
860  sigMax[iMove + 1] = sigMax[iMove];
861  }
862  iMaxTau[iInsert] = iTau;
863  iMaxY[iInsert] = iY;
864  iMaxZ[iInsert] = iZ;
865  sigMax[iInsert] = sigmaTmp;
866  if (nMax < NMAXTRY) ++nMax;
867  }
868 
869  // Found two most promising maxima.
870  }
871  }
872  }
873  if (showSearch) cout << "\n";
874 
875  // Read out starting position for search.
876  sigmaMx = sigMax[0];
877  int beginVar = (hasTwoPointParticles) ? 2 : 0;
878  if (hasOnePointParticle) beginVar = 1;
879  for (int iMax = 0; iMax < nMax; ++iMax) {
880  int iTau = iMaxTau[iMax];
881  int iY = iMaxY[iMax];
882  int iZ = iMaxZ[iMax];
883  double tauVal = 0.5;
884  double yVal = 0.5;
885  double zVal = 0.5;
886  int iGrid;
887  double varVal, varNew, deltaVar, marginVar, sigGrid[3];
888 
889  // Starting point and step size in parameter space.
890  for (int iRepeat = 0; iRepeat < 2; ++iRepeat) {
891  // Run through (possibly a subset of) tau, y and z.
892  for (int iVar = beginVar; iVar < nVar; ++iVar) {
893  bool isTauVar = iVar == 0 || (beginVar == 1 && iVar == 1);
894  if (isTauVar) varVal = tauVal;
895  else if (iVar == 1) varVal = yVal;
896  else varVal = zVal;
897  deltaVar = (iRepeat == 0) ? 0.1
898  : max( 0.01, min( 0.05, min( varVal - 0.02, 0.98 - varVal) ) );
899  marginVar = (iRepeat == 0) ? 0.02 : 0.002;
900  int moveStart = (iRepeat == 0 && isTauVar) ? 0 : 1;
901  for (int move = moveStart; move < 9; ++move) {
902 
903  // Define new parameter-space point by step in one dimension.
904  if (move == 0) {
905  iGrid = 1;
906  varNew = varVal;
907  } else if (move == 1) {
908  iGrid = 2;
909  varNew = varVal + deltaVar;
910  } else if (move == 2) {
911  iGrid = 0;
912  varNew = varVal - deltaVar;
913  } else if (sigGrid[2] >= max( sigGrid[0], sigGrid[1])
914  && varVal + 2. * deltaVar < 1. - marginVar) {
915  varVal += deltaVar;
916  sigGrid[0] = sigGrid[1];
917  sigGrid[1] = sigGrid[2];
918  iGrid = 2;
919  varNew = varVal + deltaVar;
920  } else if (sigGrid[0] >= max( sigGrid[1], sigGrid[2])
921  && varVal - 2. * deltaVar > marginVar) {
922  varVal -= deltaVar;
923  sigGrid[2] = sigGrid[1];
924  sigGrid[1] = sigGrid[0];
925  iGrid = 0;
926  varNew = varVal - deltaVar;
927  } else if (sigGrid[2] >= sigGrid[0]) {
928  deltaVar *= 0.5;
929  varVal += deltaVar;
930  sigGrid[0] = sigGrid[1];
931  iGrid = 1;
932  varNew = varVal;
933  } else {
934  deltaVar *= 0.5;
935  varVal -= deltaVar;
936  sigGrid[2] = sigGrid[1];
937  iGrid = 1;
938  varNew = varVal;
939  }
940 
941  // Convert to relevant variables and find derived new limits.
942  bool insideLimits = true;
943  if (isTauVar) {
944  tauVal = varNew;
945  selectTau( iTau, tauVal, is2);
946  if (!limitY()) insideLimits = false;
947  if (is2 && !limitZ()) insideLimits = false;
948  if (insideLimits) {
949  selectY( iY, yVal);
950  if (is2) selectZ( iZ, zVal);
951  }
952  } else if (iVar == 1) {
953  yVal = varNew;
954  selectY( iY, yVal);
955  } else if (iVar == 2) {
956  zVal = varNew;
957  selectZ( iZ, zVal);
958  }
959 
960  // Evaluate cross-section.
961  double sigmaTmp = 0.;
962  if (insideLimits) {
963 
964  // 2 -> 1: calculate cross section, weighted by phase-space volume.
965  if (!is2 && !is3) {
966  sigmaProcessPtr->set1Kin( x1H, x2H, sH);
967  sigmaTmp = sigmaProcessPtr->sigmaPDF(true);
968  sigmaTmp *= wtTau * wtY;
969 
970  // 2 -> 2: calculate cross section, weighted by phase-space volume
971  // and Breit-Wigners for masses
972  } else if (is2) {
973  sigmaProcessPtr->set2Kin( x1H, x2H, sH, tH, m3, m4,
974  runBW3H, runBW4H);
975  sigmaTmp = sigmaProcessPtr->sigmaPDF(true);
976  sigmaTmp *= wtTau * wtY * wtZ * wtBW;
977 
978  // 2 -> 3: repeat internal 3-body phase space several times and
979  // keep maximal cross section, weighted by phase-space volume
980  // and Breit-Wigners for masses
981  } else if (is3) {
982  for (int iTry3 = 0; iTry3 < NTRY3BODY; ++iTry3) {
983  if (!select3Body()) continue;
984  sigmaProcessPtr->set3Kin( x1H, x2H, sH, p3cm, p4cm, p5cm,
985  m3, m4, m5, runBW3H, runBW4H, runBW5H);
986  double sigmaTry = sigmaProcessPtr->sigmaPDF(true);
987  sigmaTry *= wtTau * wtY * wt3Body * wtBW;
988  if (sigmaTry > sigmaTmp) sigmaTmp = sigmaTry;
989  }
990  }
991 
992  // Allow possibility for user to modify cross section.
993  if (canModifySigma) sigmaTmp
994  *= userHooksPtr->multiplySigmaBy( sigmaProcessPtr, this, false);
995  if (canBiasSelection) sigmaTmp
996  *= userHooksPtr->biasSelectionBy( sigmaProcessPtr, this, false);
997  if (canBias2Sel) sigmaTmp *= pow( pTH / bias2SelRef, bias2SelPow);
998 
999  // Optional printout. Protect against negative cross section.
1000  if (showSearch) cout << " tau =" << setw(11) << tau << " y ="
1001  << setw(11) << y << " z =" << setw(11) << z
1002  << " sigma =" << setw(11) << sigmaTmp << "\n";
1003  if (sigmaTmp < 0.) sigmaTmp = 0.;
1004  }
1005 
1006  // Save new maximum. Final maximum.
1007  sigGrid[iGrid] = sigmaTmp;
1008  if (sigmaTmp > sigmaMx) sigmaMx = sigmaTmp;
1009  }
1010  }
1011  }
1012  }
1013  sigmaMx *= SAFETYMARGIN;
1014  sigmaPos = sigmaMx;
1015 
1016  // Optional printout.
1017  if (showSearch) cout << "\n Final maximum = " << setw(11) << sigmaMx
1018  << endl;
1019 
1020  // Done.
1021  return true;
1022 }
1023 
1024 //--------------------------------------------------------------------------
1025 
1026 // Select a trial kinematics phase space point.
1027 // Note: by In is meant the integral over the quantity multiplying
1028 // coefficient cn. The sum of cn is normalized to unity.
1029 
1030 bool PhaseSpace::trialKin123(bool is2, bool is3, bool inEvent) {
1031 
1032  // Allow for possibility that energy varies from event to event.
1033  if (doEnergySpread) {
1034  eCM = infoPtr->eCM();
1035  s = eCM * eCM;
1036 
1037  // Find shifted tauRes values.
1038  if (idResA !=0 && !hasTwoPointParticles) {
1039  tauResA = mResA * mResA / s;
1040  widResA = mResA * GammaResA / s;
1041  }
1042  if (idResB != 0 && !hasTwoPointParticles) {
1043  tauResB = mResB * mResB / s;
1044  widResB = mResB * GammaResB / s;
1045  }
1046  }
1047 
1048  // Choose tau according to h1(tau)/tau, where
1049  // h1(tau) = c0/I0 + (c1/I1) * 1/tau
1050  // + (c2/I2) / (tau + tauResA)
1051  // + (c3/I3) * tau / ((tau - tauResA)^2 + widResA^2)
1052  // + (c4/I4) / (tau + tauResB)
1053  // + (c5/I5) * tau / ((tau - tauResB)^2 + widResB^2)
1054  // + (c6/I6) * tau / (1 - tau).
1055  if (!limitTau(is2, is3)) return false;
1056  int iTau = 0;
1057  if (!hasTwoPointParticles) {
1058  double rTau = rndmPtr->flat();
1059  while (rTau > tauCoefSum[iTau]) ++iTau;
1060  }
1061  selectTau( iTau, rndmPtr->flat(), is2);
1062 
1063  // Choose y according to h2(y), where
1064  // h2(y) = (c0/I0) * 1/cosh(y)
1065  // + (c1/I1) * (y-ymin) + (c2/I2) * (ymax-y)
1066  // + (c3/I3) * exp(y) + (c4/i4) * exp(-y) (for hadron; for lepton instead)
1067  // + (c5/I5) * 1 / (1 - exp(y-ymax)) + (c6/I6) * 1 / (1 - exp(ymin-y)).
1068  if (!limitY()) return false;
1069  int iY = 0;
1070  if (!hasOnePointParticle && !hasTwoPointParticles) {
1071  double rY = rndmPtr->flat();
1072  while (rY > yCoefSum[iY]) ++iY;
1073  }
1074  selectY( iY, rndmPtr->flat());
1075 
1076  // Choose z = cos(thetaHat) according to h3(z), where
1077  // h3(z) = c0/I0 + (c1/I1) * 1/(A - z) + (c2/I2) * 1/(A + z)
1078  // + (c3/I3) * 1/(A - z)^2 + (c4/I4) * 1/(A + z)^2,
1079  // where A = 1 + 2*(m3*m4/sH)^2 (= 1 for massless products).
1080  if (is2) {
1081  if (!limitZ()) return false;
1082  int iZ = 0;
1083  double rZ = rndmPtr->flat();
1084  while (rZ > zCoefSum[iZ]) ++iZ;
1085  selectZ( iZ, rndmPtr->flat());
1086  }
1087 
1088  // 2 -> 1: calculate cross section, weighted by phase-space volume.
1089  if (!is2 && !is3) {
1090  sigmaProcessPtr->set1Kin( x1H, x2H, sH);
1091  sigmaNw = sigmaProcessPtr->sigmaPDF();
1092  sigmaNw *= wtTau * wtY;
1093 
1094  // 2 -> 2: calculate cross section, weighted by phase-space volume
1095  // and Breit-Wigners for masses
1096  } else if (is2) {
1097  sigmaProcessPtr->set2Kin( x1H, x2H, sH, tH, m3, m4, runBW3H, runBW4H);
1098  sigmaNw = sigmaProcessPtr->sigmaPDF();
1099  sigmaNw *= wtTau * wtY * wtZ * wtBW;
1100 
1101  // 2 -> 3: also sample internal 3-body phase, weighted by
1102  // 2 -> 1 phase-space volume and Breit-Wigners for masses
1103  } else if (is3) {
1104  if (!select3Body()) sigmaNw = 0.;
1105  else {
1106  sigmaProcessPtr->set3Kin( x1H, x2H, sH, p3cm, p4cm, p5cm,
1107  m3, m4, m5, runBW3H, runBW4H, runBW5H);
1108  sigmaNw = sigmaProcessPtr->sigmaPDF();
1109  sigmaNw *= wtTau * wtY * wt3Body * wtBW;
1110  }
1111  }
1112 
1113  // Allow possibility for user to modify cross section.
1114  if (canModifySigma) sigmaNw
1115  *= userHooksPtr->multiplySigmaBy( sigmaProcessPtr, this, inEvent);
1116  if (canBiasSelection) sigmaNw
1117  *= userHooksPtr->biasSelectionBy( sigmaProcessPtr, this, inEvent);
1118  if (canBias2Sel) sigmaNw *= pow( pTH / bias2SelRef, bias2SelPow);
1119 
1120  // Check if maximum violated.
1121  newSigmaMx = false;
1122  if (sigmaNw > sigmaMx) {
1123  infoPtr->errorMsg("Warning in PhaseSpace2to2tauyz::trialKin: "
1124  "maximum for cross section violated");
1125 
1126  // Violation strategy 1: increase maximum (always during initialization).
1127  if (increaseMaximum || !inEvent) {
1128  double violFact = SAFETYMARGIN * sigmaNw / sigmaMx;
1129  sigmaMx = SAFETYMARGIN * sigmaNw;
1130  newSigmaMx = true;
1131  if (showViolation) {
1132  if (violFact < 9.99) cout << fixed;
1133  else cout << scientific;
1134  cout << " PYTHIA Maximum for " << sigmaProcessPtr->name()
1135  << " increased by factor " << setprecision(3) << violFact
1136  << " to " << scientific << sigmaMx << endl;
1137  }
1138 
1139  // Violation strategy 2: weight event (done in ProcessContainer).
1140  } else if (showViolation && sigmaNw > sigmaPos) {
1141  double violFact = sigmaNw / sigmaMx;
1142  if (violFact < 9.99) cout << fixed;
1143  else cout << scientific;
1144  cout << " PYTHIA Maximum for " << sigmaProcessPtr->name()
1145  << " exceeded by factor " << setprecision(3) << violFact << endl;
1146  sigmaPos = sigmaNw;
1147  }
1148  }
1149 
1150  // Check if negative cross section.
1151  if (sigmaNw < sigmaNeg) {
1152  infoPtr->errorMsg("Warning in PhaseSpace2to2tauyz::trialKin:"
1153  " negative cross section set 0", "for " + sigmaProcessPtr->name() );
1154  sigmaNeg = sigmaNw;
1155 
1156  // Optional printout of (all) violations.
1157  if (showViolation) cout << " PYTHIA Negative minimum for "
1158  << sigmaProcessPtr->name() << " changed to " << scientific
1159  << setprecision(3) << sigmaNeg << endl;
1160  }
1161  if (sigmaNw < 0.) sigmaNw = 0.;
1162 
1163  // Set event weight, where relevant.
1164  biasWt = (canBiasSelection) ? userHooksPtr->biasedSelectionWeight() : 1.;
1165  if (canBias2Sel) biasWt /= pow( pTH / bias2SelRef, bias2SelPow);
1166 
1167  // Done.
1168  return true;
1169 }
1170 
1171 //--------------------------------------------------------------------------
1172 
1173 // Find range of allowed tau values.
1174 
1175 bool PhaseSpace::limitTau(bool is2, bool is3) {
1176 
1177  // Trivial reply for unresolved lepton beams.
1178  if (hasTwoPointParticles) {
1179  tauMin = 1.;
1180  tauMax = 1.;
1181  return true;
1182  }
1183 
1184  // Requirements from allowed mHat range and allowed Q2Min.
1185  tauMin = sHatMin / s;
1186  if (is2 && hasQ2Min && Q2GlobalMin + s3 + s4 > sHatMin)
1187  tauMin = (Q2GlobalMin + s3 + s4) / s;
1188  tauMax = (mHatMax < mHatMin) ? 1. : min( 1., sHatMax / s);
1189 
1190  // Requirements from allowed pT range and masses.
1191  if (is2 || is3) {
1192  double mT3Min = sqrt(s3 + pT2HatMin);
1193  double mT4Min = sqrt(s4 + pT2HatMin);
1194  double mT5Min = (is3) ? sqrt(s5 + pT2HatMin) : 0.;
1195  tauMin = max( tauMin, pow2(mT3Min + mT4Min + mT5Min) / s);
1196  }
1197 
1198  // Check that there is an open range.
1199  return (tauMax > tauMin);
1200 }
1201 
1202 //--------------------------------------------------------------------------
1203 
1204 // Find range of allowed y values.
1205 
1206 bool PhaseSpace::limitY() {
1207 
1208  // Trivial reply for unresolved lepton beams.
1209  if (hasTwoPointParticles) {
1210  yMax = 1.;
1211  return true;
1212  }
1213 
1214  // Requirements from selected tau value. Trivial for one unresolved beam.
1215  yMax = -0.5 * log(tau);
1216  if (hasOnePointParticle) return true;
1217 
1218  // For lepton beams requirements from cutoff for f_e^e.
1219  double yMaxMargin = (hasTwoLeptonBeams) ? yMax + LEPTONXLOGMAX : yMax;
1220 
1221  // Check that there is an open range.
1222  return (yMaxMargin > 0.);
1223 }
1224 
1225 //--------------------------------------------------------------------------
1226 
1227 // Find range of allowed z = cos(theta) values.
1228 
1229 bool PhaseSpace::limitZ() {
1230 
1231  // Default limits.
1232  zMin = 0.;
1233  zMax = 1.;
1234 
1235  // Requirements from pTHat limits.
1236  zMax = sqrtpos( 1. - pT2HatMin / p2Abs );
1237  if (pTHatMax > pTHatMin) zMin = sqrtpos( 1. - pT2HatMax / p2Abs );
1238 
1239  // Check that there is an open range so far.
1240  hasNegZ = false;
1241  hasPosZ = false;
1242  if (zMax < zMin) return false;
1243 
1244  // Define two individual ranges.
1245  hasNegZ = true;
1246  hasPosZ = true;
1247  zNegMin = -zMax;
1248  zNegMax = -zMin;
1249  zPosMin = zMin;
1250  zPosMax = zMax;
1251 
1252  // Optionally introduce Q2 = -tHat cut.
1253  if (hasQ2Min) {
1254  double zMaxQ2 = (sH - s3 - s4 - 2. * Q2GlobalMin) / (2. * pAbs * mHat);
1255  if (zMaxQ2 > zPosMin) {
1256  if (zMaxQ2 < zPosMax) zPosMax = zMaxQ2;
1257  } else {
1258  hasPosZ = false;
1259  zPosMax = zPosMin;
1260  if (zMaxQ2 > zNegMin) {
1261  if (zMaxQ2 < zNegMax) zNegMax = zMaxQ2;
1262  } else {
1263  hasNegZ = false;
1264  zNegMin = zNegMax;
1265  }
1266  }
1267  }
1268 
1269  // Check that there is an open range.
1270  return hasNegZ;
1271 }
1272 
1273 //--------------------------------------------------------------------------
1274 
1275 // Select tau according to a choice of shapes.
1276 
1277 void PhaseSpace::selectTau(int iTau, double tauVal, bool is2) {
1278 
1279  // Trivial reply for unresolved lepton beams.
1280  if (hasTwoPointParticles) {
1281  tau = 1.;
1282  wtTau = 1.;
1283  sH = s;
1284  mHat = sqrt(sH);
1285  if (is2) {
1286  p2Abs = 0.25 * (pow2(sH - s3 - s4) - 4. * s3 * s4) / sH;
1287  pAbs = sqrtpos( p2Abs );
1288  }
1289  return;
1290  }
1291 
1292  // Contributions from s-channel resonances.
1293  double tRatA = 0.;
1294  double aLowA = 0.;
1295  double aUppA = 0.;
1296  if (idResA !=0) {
1297  tRatA = ((tauResA + tauMax) / (tauResA + tauMin)) * (tauMin / tauMax);
1298  aLowA = atan( (tauMin - tauResA) / widResA);
1299  aUppA = atan( (tauMax - tauResA) / widResA);
1300  }
1301  double tRatB = 0.;
1302  double aLowB = 0.;
1303  double aUppB = 0.;
1304  if (idResB != 0) {
1305  tRatB = ((tauResB + tauMax) / (tauResB + tauMin)) * (tauMin / tauMax);
1306  aLowB = atan( (tauMin - tauResB) / widResB);
1307  aUppB = atan( (tauMax - tauResB) / widResB);
1308  }
1309 
1310  // Contributions from 1 / (1 - tau) for lepton beams.
1311  double aLowT = 0.;
1312  double aUppT = 0.;
1313  if (hasTwoLeptonBeams) {
1314  aLowT = log( max( LEPTONTAUMIN, 1. - tauMin) );
1315  aUppT = log( max( LEPTONTAUMIN, 1. - tauMax) );
1316  intTau6 = aLowT - aUppT;
1317  }
1318 
1319  // Select according to 1/tau or 1/tau^2.
1320  if (iTau == 0) tau = tauMin * pow( tauMax / tauMin, tauVal);
1321  else if (iTau == 1) tau = tauMax * tauMin
1322  / (tauMin + (tauMax - tauMin) * tauVal);
1323 
1324  // Select according to 1 / (1 - tau) for lepton beams.
1325  else if (hasTwoLeptonBeams && iTau == nTau - 1)
1326  tau = 1. - exp( aUppT + intTau6 * tauVal );
1327 
1328  // Select according to 1 / (tau * (tau + tauRes)) or
1329  // 1 / ((tau - tauRes)^2 + widRes^2) for resonances A and B.
1330  else if (iTau == 2) tau = tauResA * tauMin
1331  / ((tauResA + tauMin) * pow( tRatA, tauVal) - tauMin);
1332  else if (iTau == 3) tau = tauResA + widResA
1333  * tan( aLowA + (aUppA - aLowA) * tauVal);
1334  else if (iTau == 4) tau = tauResB * tauMin
1335  / ((tauResB + tauMin) * pow( tRatB, tauVal) - tauMin);
1336  else if (iTau == 5) tau = tauResB + widResB
1337  * tan( aLowB + (aUppB - aLowB) * tauVal);
1338 
1339  // Phase space weight in tau.
1340  intTau0 = log( tauMax / tauMin);
1341  intTau1 = (tauMax - tauMin) / (tauMax * tauMin);
1342  double invWtTau = (tauCoef[0] / intTau0) + (tauCoef[1] / intTau1) / tau;
1343  if (idResA != 0) {
1344  intTau2 = -log(tRatA) / tauResA;
1345  intTau3 = (aUppA - aLowA) / widResA;
1346  invWtTau += (tauCoef[2] / intTau2) / (tau + tauResA)
1347  + (tauCoef[3] / intTau3) * tau / ( pow2(tau - tauResA) + pow2(widResA) );
1348  }
1349  if (idResB != 0) {
1350  intTau4 = -log(tRatB) / tauResB;
1351  intTau5 = (aUppB - aLowB) / widResB;
1352  invWtTau += (tauCoef[4] / intTau4) / (tau + tauResB)
1353  + (tauCoef[5] / intTau5) * tau / ( pow2(tau - tauResB) + pow2(widResB) );
1354  }
1355  if (hasTwoLeptonBeams)
1356  invWtTau += (tauCoef[nTau - 1] / intTau6)
1357  * tau / max( LEPTONTAUMIN, 1. - tau);
1358  wtTau = 1. / invWtTau;
1359 
1360  // Calculate sHat and absolute momentum of outgoing partons.
1361  sH = tau * s;
1362  mHat = sqrt(sH);
1363  if (is2) {
1364  p2Abs = 0.25 * (pow2(sH - s3 - s4) - 4. * s3 * s4) / sH;
1365  pAbs = sqrtpos( p2Abs );
1366  }
1367 
1368 }
1369 
1370 //--------------------------------------------------------------------------
1371 
1372 // Select y according to a choice of shapes.
1373 
1374 void PhaseSpace::selectY(int iY, double yVal) {
1375 
1376  // Trivial reply for two unresolved lepton beams.
1377  if (hasTwoPointParticles) {
1378  y = 0.;
1379  wtY = 1.;
1380  x1H = 1.;
1381  x2H = 1.;
1382  return;
1383  }
1384 
1385  // Trivial replies for one unresolved lepton beam.
1386  if (hasOnePointParticle) {
1387  if (hasLeptonBeamA || hasPointGammaA) {
1388  y = yMax;
1389  x1H = 1.;
1390  x2H = tau;
1391  } else {
1392  y = -yMax;
1393  x1H = tau;
1394  x2H = 1.;
1395  }
1396  wtY = 1.;
1397  return;
1398  }
1399 
1400  // For lepton beams skip options 3&4 and go straight to 5&6.
1401  if (hasTwoLeptonBeams && iY > 2) iY += 2;
1402 
1403  // Standard expressions used below.
1404  double expYMax = exp( yMax );
1405  double expYMin = exp(-yMax );
1406  double atanMax = atan( expYMax );
1407  double atanMin = atan( expYMin );
1408  double aUppY = (hasTwoLeptonBeams)
1409  ? log( max( LEPTONXMIN, LEPTONXMAX / tau - 1. ) ) : 0.;
1410  double aLowY = LEPTONXLOGMIN;
1411 
1412  // 1 / cosh(y).
1413  if (iY == 0) y = log( tan( atanMin + (atanMax - atanMin) * yVal ) );
1414 
1415  // y - y_min or mirrored y_max - y.
1416  else if (iY <= 2) y = yMax * (2. * sqrt(yVal) - 1.);
1417 
1418  // exp(y) or mirrored exp(-y).
1419  else if (iY <= 4) y = log( expYMin + (expYMax - expYMin) * yVal );
1420 
1421  // 1 / (1 - exp(y - y_max)) or mirrored 1 / (1 - exp(y_min - y)).
1422  else y = yMax - log( 1. + exp(aLowY + (aUppY - aLowY) * yVal) );
1423 
1424  // Mirror two cases.
1425  if (iY == 2 || iY == 4 || iY == 6) y = -y;
1426 
1427  // Phase space integral in y.
1428  intY0 = 2. * (atanMax - atanMin);
1429  intY12 = 0.5 * pow2(2. * yMax);
1430  intY34 = expYMax - expYMin;
1431  intY56 = aUppY - aLowY;
1432  double invWtY = (yCoef[0] / intY0) / cosh(y)
1433  + (yCoef[1] / intY12) * (y + yMax) + (yCoef[2] / intY12) * (yMax - y);
1434  if (!hasTwoLeptonBeams) invWtY
1435  += (yCoef[3] / intY34) * exp(y) + (yCoef[4] / intY34) * exp(-y);
1436  else invWtY
1437  += (yCoef[3] / intY56) / max( LEPTONXMIN, 1. - exp( y - yMax) )
1438  + (yCoef[4] / intY56) / max( LEPTONXMIN, 1. - exp(-y - yMax) );
1439  wtY = 1. / invWtY;
1440 
1441  // Calculate x1 and x2.
1442  x1H = sqrt(tau) * exp(y);
1443  x2H = sqrt(tau) * exp(-y);
1444 }
1445 
1446 //--------------------------------------------------------------------------
1447 
1448 // Select z = cos(theta) according to a choice of shapes.
1449 // The selection is split in the positive- and negative-z regions,
1450 // since a pTmax cut can remove the region around z = 0.
1451 // Furthermore, a Q2 (= -tHat) cut can make the two regions asymmetric.
1452 
1453 void PhaseSpace::selectZ(int iZ, double zVal) {
1454 
1455  // Mass-dependent dampening of pT -> 0 limit.
1456  ratio34 = max(TINY, 2. * s3 * s4 / pow2(sH));
1457  unity34 = 1. + ratio34;
1458  double ratiopT2 = 2. * pT2HatMin / max( SHATMINZ, sH);
1459  if (ratiopT2 < PT2RATMINZ) ratio34 = max( ratio34, ratiopT2);
1460 
1461  // Common expressions of unity - z and unity + z limits, protected from 0.
1462  double zNegMinM = max(ratio34, unity34 - zNegMin);
1463  double zNegMaxM = max(ratio34, unity34 - zNegMax);
1464  double zPosMinM = max(ratio34, unity34 - zPosMin);
1465  double zPosMaxM = max(ratio34, unity34 - zPosMax);
1466  double zNegMinP = max(ratio34, unity34 + zNegMin);
1467  double zNegMaxP = max(ratio34, unity34 + zNegMax);
1468  double zPosMinP = max(ratio34, unity34 + zPosMin);
1469  double zPosMaxP = max(ratio34, unity34 + zPosMax);
1470 
1471  // Evaluate integrals over negative and positive z ranges.
1472  // Flat in z.
1473  double area0Neg = zNegMax - zNegMin;
1474  double area0Pos = zPosMax - zPosMin;
1475  double area0 = area0Neg + area0Pos;
1476  // 1 / (unity34 - z).
1477  double area1Neg = log(zNegMinM / zNegMaxM);
1478  double area1Pos = log(zPosMinM / zPosMaxM);
1479  double area1 = area1Neg + area1Pos;
1480  // 1 / (unity34 + z).
1481  double area2Neg = log(zNegMaxP / zNegMinP);
1482  double area2Pos = log(zPosMaxP / zPosMinP);
1483  double area2 = area2Neg + area2Pos;
1484  // 1 / (unity34 - z)^2.
1485  double area3Neg = 1. / zNegMaxM - 1. / zNegMinM;
1486  double area3Pos = 1. / zPosMaxM - 1. / zPosMinM;
1487  double area3 = area3Neg + area3Pos;
1488  // 1 / (unity34 + z)^2.
1489  double area4Neg = 1. / zNegMinP - 1. / zNegMaxP;
1490  double area4Pos = 1. / zPosMinP - 1. / zPosMaxP;
1491  double area4 = area4Neg + area4Pos;
1492 
1493  // Pick z value according to alternatives.
1494  // Flat in z.
1495  if (iZ == 0) {
1496  if (!hasPosZ || zVal * area0 < area0Neg) {
1497  double zValMod = zVal * area0 / area0Neg;
1498  z = zNegMin + zValMod * area0Neg;
1499  } else {
1500  double zValMod = (zVal * area0 - area0Neg) / area0Pos;
1501  z = zPosMin + zValMod * area0Pos;
1502  }
1503 
1504  // 1 / (unity34 - z).
1505  } else if (iZ == 1) {
1506  if (!hasPosZ || zVal * area1 < area1Neg) {
1507  double zValMod = zVal * area1 / area1Neg;
1508  z = unity34 - zNegMinM * pow(zNegMaxM / zNegMinM, zValMod);
1509  } else {
1510  double zValMod = (zVal * area1 - area1Neg)/ area1Pos;
1511  z = unity34 - zPosMinM * pow(zPosMaxM / zPosMinM, zValMod);
1512  }
1513 
1514  // 1 / (unity34 + z).
1515  } else if (iZ == 2) {
1516  if (!hasPosZ || zVal * area2 < area2Neg) {
1517  double zValMod = zVal * area2 / area2Neg;
1518  z = zNegMinP * pow(zNegMaxP / zNegMinP, zValMod) - unity34;
1519  } else {
1520  double zValMod = (zVal * area2 - area2Neg)/ area2Pos;
1521  z = zPosMinP * pow(zPosMaxP / zPosMinP, zValMod) - unity34;
1522  }
1523 
1524  // 1 / (unity34 - z)^2.
1525  } else if (iZ == 3) {
1526  if (!hasPosZ || zVal * area3 < area3Neg) {
1527  double zValMod = zVal * area3 / area3Neg;
1528  z = unity34 - 1. / (1./zNegMinM + area3Neg * zValMod);
1529  } else {
1530  double zValMod = (zVal * area3 - area3Neg)/ area3Pos;
1531  z = unity34 - 1. / (1./zPosMinM + area3Pos * zValMod);
1532  }
1533 
1534  // 1 / (unity34 + z)^2.
1535  } else if (iZ == 4) {
1536  if (!hasPosZ || zVal * area4 < area4Neg) {
1537  double zValMod = zVal * area4 / area4Neg;
1538  z = 1. / (1./zNegMinP - area4Neg * zValMod) - unity34;
1539  } else {
1540  double zValMod = (zVal * area4 - area4Neg)/ area4Pos;
1541  z = 1. / (1./zPosMinP - area4Pos * zValMod) - unity34;
1542  }
1543  }
1544 
1545  // Safety check for roundoff errors. Combinations with z.
1546  if (z < 0.) z = min( zNegMax, max( zNegMin, z));
1547  else z = min( zPosMax, max( zPosMin, z) );
1548  zNeg = max(ratio34, unity34 - z);
1549  zPos = max(ratio34, unity34 + z);
1550 
1551  // Phase space integral in z.
1552  wtZ = mHat * pAbs / ( (zCoef[0] / area0) + (zCoef[1] / area1) / zNeg
1553  + (zCoef[2] / area2) / zPos + (zCoef[3] / area3) / pow2(zNeg)
1554  + (zCoef[4] / area4) / pow2(zPos) );
1555 
1556  // Calculate tHat and uHat. Also gives pTHat.
1557  double sH34 = -0.5 * (sH - s3 - s4);
1558  double tHuH = pow2(sH34) * (1. - z) * (1. + z) + s3 * s4 * pow2(z);
1559  if (z < 0.) {
1560  tH = sH34 + mHat * pAbs * z;
1561  uH = tHuH / tH;
1562  } else {
1563  uH = sH34 - mHat * pAbs * z;
1564  tH = tHuH / uH;
1565  }
1566  pTH = sqrtpos( (tH * uH - s3 * s4) / sH);
1567 
1568 }
1569 
1570 //--------------------------------------------------------------------------
1571 
1572 // Select three-body phase space according to a cylindrically based form
1573 // that can be chosen to favour low pT based on the form of propagators.
1574 
1575 bool PhaseSpace::select3Body() {
1576 
1577  // Upper and lower limits of pT choice for 4 and 5.
1578  double m35S = pow2(m3 + m5);
1579  double pT4Smax = 0.25 * ( pow2(sH - s4 - m35S) - 4. * s4 * m35S ) / sH;
1580  if (pTHatMax > pTHatMin) pT4Smax = min( pT2HatMax, pT4Smax);
1581  double pT4Smin = pT2HatMin;
1582  double m34S = pow2(m3 + m4);
1583  double pT5Smax = 0.25 * ( pow2(sH - s5 - m34S) - 4. * s5 * m34S ) / sH;
1584  if (pTHatMax > pTHatMin) pT5Smax = min( pT2HatMax, pT5Smax);
1585  double pT5Smin = pT2HatMin;
1586 
1587  // Check that pT ranges not closed.
1588  if ( pT4Smax < pow2(pTHatMin + MASSMARGIN) ) return false;
1589  if ( pT5Smax < pow2(pTHatMin + MASSMARGIN) ) return false;
1590 
1591  // Select pT4S according to c0 + c1/(M^2 + pT^2) + c2/(M^2 + pT^2)^2.
1592  double pTSmaxProp = pT4Smax + sTchan1;
1593  double pTSminProp = pT4Smin + sTchan1;
1594  double pTSratProp = pTSmaxProp / pTSminProp;
1595  double pTSdiff = pT4Smax - pT4Smin;
1596  double rShape = rndmPtr->flat();
1597  double pT4S = 0.;
1598  if (rShape < frac3Flat) pT4S = pT4Smin + rndmPtr->flat() * pTSdiff;
1599  else if (rShape < frac3Flat + frac3Pow1) pT4S = max( pT2HatMin,
1600  pTSminProp * pow( pTSratProp, rndmPtr->flat() ) - sTchan1 );
1601  else pT4S = max( pT2HatMin, pTSminProp * pTSmaxProp
1602  / (pTSminProp + rndmPtr->flat()* pTSdiff) - sTchan1 );
1603  double wt4 = pTSdiff / ( frac3Flat
1604  + frac3Pow1 * pTSdiff / (log(pTSratProp) * (pT4S + sTchan1))
1605  + frac3Pow2 * pTSminProp * pTSmaxProp / pow2(pT4S + sTchan1) );
1606 
1607  // Select pT5S according to c0 + c1/(M^2 + pT^2) + c2/(M^2 + pT^2)^2.
1608  pTSmaxProp = pT5Smax + sTchan2;
1609  pTSminProp = pT5Smin + sTchan2;
1610  pTSratProp = pTSmaxProp / pTSminProp;
1611  pTSdiff = pT5Smax - pT5Smin;
1612  rShape = rndmPtr->flat();
1613  double pT5S = 0.;
1614  if (rShape < frac3Flat) pT5S = pT5Smin + rndmPtr->flat() * pTSdiff;
1615  else if (rShape < frac3Flat + frac3Pow1) pT5S = max( pT2HatMin,
1616  pTSminProp * pow( pTSratProp, rndmPtr->flat() ) - sTchan2 );
1617  else pT5S = max( pT2HatMin, pTSminProp * pTSmaxProp
1618  / (pTSminProp + rndmPtr->flat()* pTSdiff) - sTchan2 );
1619  double wt5 = pTSdiff / ( frac3Flat
1620  + frac3Pow1 * pTSdiff / (log(pTSratProp) * (pT5S + sTchan2))
1621  + frac3Pow2 * pTSminProp * pTSmaxProp / pow2(pT5S + sTchan2) );
1622 
1623  // Select azimuthal angles and check that third pT in range.
1624  double phi4 = 2. * M_PI * rndmPtr->flat();
1625  double phi5 = 2. * M_PI * rndmPtr->flat();
1626  double pT3S = max( 0., pT4S + pT5S + 2. * sqrt(pT4S * pT5S)
1627  * cos(phi4 - phi5) );
1628  if ( pT3S < pT2HatMin || (pTHatMax > pTHatMin && pT3S > pT2HatMax) )
1629  return false;
1630 
1631  // Calculate transverse masses and check that phase space not closed.
1632  double sT3 = s3 + pT3S;
1633  double sT4 = s4 + pT4S;
1634  double sT5 = s5 + pT5S;
1635  double mT3 = sqrt(sT3);
1636  double mT4 = sqrt(sT4);
1637  double mT5 = sqrt(sT5);
1638  if ( mT3 + mT4 + mT5 + MASSMARGIN > mHat ) return false;
1639 
1640  // Select rapidity for particle 3 and check that phase space not closed.
1641  double m45S = pow2(mT4 + mT5);
1642  double y3max = log( ( sH + sT3 - m45S + sqrtpos( pow2(sH - sT3 - m45S)
1643  - 4 * sT3 * m45S ) ) / (2. * mHat * mT3) );
1644  if (y3max < YRANGEMARGIN) return false;
1645  double y3 = (2. * rndmPtr->flat() - 1.) * (1. - YRANGEMARGIN) * y3max;
1646  double pz3 = mT3 * sinh(y3);
1647  double e3 = mT3 * cosh(y3);
1648 
1649  // Find momentum transfers in the two mirror solutions (in 4-5 frame).
1650  double pz45 = -pz3;
1651  double e45 = mHat - e3;
1652  double sT45 = e45 * e45 - pz45 * pz45;
1653  double lam45 = sqrtpos( pow2(sT45 - sT4 - sT5) - 4. * sT4 * sT5 );
1654  if (lam45 < YRANGEMARGIN * sH) return false;
1655  double lam4e = sT45 + sT4 - sT5;
1656  double lam5e = sT45 + sT5 - sT4;
1657  double tFac = -0.5 * mHat / sT45;
1658  double t1Pos = tFac * (e45 - pz45) * (lam4e - lam45);
1659  double t1Neg = tFac * (e45 - pz45) * (lam4e + lam45);
1660  double t2Pos = tFac * (e45 + pz45) * (lam5e - lam45);
1661  double t2Neg = tFac * (e45 + pz45) * (lam5e + lam45);
1662 
1663  // Construct relative mirror weights and make choice.
1664  double wtPosUnnorm = 1.;
1665  double wtNegUnnorm = 1.;
1666  if (useMirrorWeight) {
1667  wtPosUnnorm = 1./ pow2( (t1Pos - sTchan1) * (t2Pos - sTchan2) );
1668  wtNegUnnorm = 1./ pow2( (t1Neg - sTchan1) * (t2Neg - sTchan2) );
1669  }
1670  double wtPos = wtPosUnnorm / (wtPosUnnorm + wtNegUnnorm);
1671  double wtNeg = wtNegUnnorm / (wtPosUnnorm + wtNegUnnorm);
1672  double epsilon = (rndmPtr->flat() < wtPos) ? 1. : -1.;
1673 
1674  // Construct four-vectors in rest frame of subprocess.
1675  double px4 = sqrt(pT4S) * cos(phi4);
1676  double py4 = sqrt(pT4S) * sin(phi4);
1677  double px5 = sqrt(pT5S) * cos(phi5);
1678  double py5 = sqrt(pT5S) * sin(phi5);
1679  double pz4 = 0.5 * (pz45 * lam4e + epsilon * e45 * lam45) / sT45;
1680  double pz5 = pz45 - pz4;
1681  double e4 = sqrt(sT4 + pz4 * pz4);
1682  double e5 = sqrt(sT5 + pz5 * pz5);
1683  p3cm = Vec4( -(px4 + px5), -(py4 + py5), pz3, e3);
1684  p4cm = Vec4( px4, py4, pz4, e4);
1685  p5cm = Vec4( px5, py5, pz5, e5);
1686 
1687  // Total weight to associate with kinematics choice.
1688  wt3Body = wt4 * wt5 * (2. * y3max) / (128. * pow3(M_PI) * lam45);
1689  wt3Body *= (epsilon > 0.) ? 1. / wtPos : 1. / wtNeg;
1690 
1691  // Cross section of form |M|^2/(2 sHat) dPS_3 so need 1/(2 sHat).
1692  wt3Body /= (2. * sH);
1693 
1694  // Done.
1695  return true;
1696 
1697 }
1698 
1699 //--------------------------------------------------------------------------
1700 
1701 // Solve linear equation system for better phase space coefficients.
1702 
1703 void PhaseSpace::solveSys( int n, int bin[8], double vec[8],
1704  double mat[8][8], double coef[8]) {
1705 
1706  // Optional printout.
1707  if (showSearch) {
1708  cout << "\n Equation system: " << setw(5) << bin[0];
1709  for (int j = 0; j < n; ++j) cout << setw(12) << mat[0][j];
1710  cout << setw(12) << vec[0] << "\n";
1711  for (int i = 1; i < n; ++i) {
1712  cout << " " << setw(5) << bin[i];
1713  for (int j = 0; j < n; ++j) cout << setw(12) << mat[i][j];
1714  cout << setw(12) << vec[i] << "\n";
1715  }
1716  }
1717 
1718  // Local variables.
1719  double vecNor[8], coefTmp[8];
1720  for (int i = 0; i < n; ++i) coefTmp[i] = 0.;
1721 
1722  // Check if equation system solvable.
1723  bool canSolve = true;
1724  for (int i = 0; i < n; ++i) if (bin[i] == 0) canSolve = false;
1725  double vecSum = 0.;
1726  for (int i = 0; i < n; ++i) vecSum += vec[i];
1727  if (abs(vecSum) < TINY) canSolve = false;
1728 
1729  // Solve to find relative importance of cross-section pieces.
1730  if (canSolve) {
1731  for (int i = 0; i < n; ++i) vecNor[i] = max( 0.1, vec[i] / vecSum);
1732  for (int k = 0; k < n - 1; ++k) {
1733  for (int i = k + 1; i < n; ++i) {
1734  if (abs(mat[k][k]) < TINY) {canSolve = false; break;}
1735  double ratio = mat[i][k] / mat[k][k];
1736  vec[i] -= ratio * vec[k];
1737  for (int j = k; j < n; ++j) mat[i][j] -= ratio * mat[k][j];
1738  }
1739  if (!canSolve) break;
1740  }
1741  if (canSolve) {
1742  for (int k = n - 1; k >= 0; --k) {
1743  for (int j = k + 1; j < n; ++j) vec[k] -= mat[k][j] * coefTmp[j];
1744  coefTmp[k] = vec[k] / mat[k][k];
1745  }
1746  }
1747  }
1748 
1749  // Share evenly if failure.
1750  if (!canSolve) for (int i = 0; i < n; ++i) {
1751  coefTmp[i] = 1.;
1752  vecNor[i] = 0.1;
1753  if (vecSum > TINY) vecNor[i] = max(0.1, vec[i] / vecSum);
1754  }
1755 
1756  // Normalize coefficients, with piece shared democratically.
1757  double coefSum = 0.;
1758  vecSum = 0.;
1759  for (int i = 0; i < n; ++i) {
1760  coefTmp[i] = max( 0., coefTmp[i]);
1761  coefSum += coefTmp[i];
1762  vecSum += vecNor[i];
1763  }
1764  if (coefSum > 0.) for (int i = 0; i < n; ++i) coef[i] = EVENFRAC / n
1765  + (1. - EVENFRAC) * 0.5 * (coefTmp[i] / coefSum + vecNor[i] / vecSum);
1766  else for (int i = 0; i < n; ++i) coef[i] = 1. / n;
1767 
1768  // Optional printout.
1769  if (showSearch) {
1770  cout << " Solution: ";
1771  for (int i = 0; i < n; ++i) cout << setw(12) << coef[i];
1772  cout << "\n";
1773  }
1774 }
1775 
1776 //--------------------------------------------------------------------------
1777 
1778 // Setup mass selection for one resonance at a time - part 1.
1779 
1780 void PhaseSpace::setupMass1(int iM) {
1781 
1782  // Identity for mass seletion; is 0 also for light quarks (not yet selected).
1783  if (iM == 3) idMass[iM] = abs(sigmaProcessPtr->id3Mass());
1784  if (iM == 4) idMass[iM] = abs(sigmaProcessPtr->id4Mass());
1785  if (iM == 5) idMass[iM] = abs(sigmaProcessPtr->id5Mass());
1786 
1787  // Masses and widths of resonances.
1788  if (idMass[iM] == 0) {
1789  mPeak[iM] = 0.;
1790  mWidth[iM] = 0.;
1791  mMin[iM] = 0.;
1792  mMax[iM] = 0.;
1793  } else {
1794  mPeak[iM] = particleDataPtr->m0(idMass[iM]);
1795  mWidth[iM] = particleDataPtr->mWidth(idMass[iM]);
1796  mMin[iM] = max( MRESMINABS, particleDataPtr->mMin(idMass[iM]) );
1797  mMax[iM] = particleDataPtr->mMax(idMass[iM]);
1798  // gmZmode == 1 means pure photon propagator; set at lower mass limit.
1799  if (idMass[iM] == 23 && gmZmode == 1) mPeak[iM] = mMin[iM];
1800  }
1801 
1802  // Mass and width combinations for Breit-Wigners.
1803  sPeak[iM] = mPeak[iM] * mPeak[iM];
1804  useBW[iM] = useBreitWigners && (mWidth[iM] > minWidthBreitWigners);
1805  if (!useBW[iM]) mWidth[iM] = 0.;
1806  mw[iM] = mPeak[iM] * mWidth[iM];
1807  wmRat[iM] = (idMass[iM] == 0 || mPeak[iM] == 0.)
1808  ? 0. : mWidth[iM] / mPeak[iM];
1809 
1810  // Simple Breit-Wigner range, upper edge to be corrected subsequently.
1811  if (useBW[iM]) {
1812  mLower[iM] = mMin[iM];
1813  mUpper[iM] = mHatMax;
1814  }
1815 
1816 }
1817 
1818 //--------------------------------------------------------------------------
1819 
1820 // Setup mass selection for one resonance at a time - part 2.
1821 
1822 void PhaseSpace::setupMass2(int iM, double distToThresh) {
1823 
1824  // Store reduced Breit-Wigner range.
1825  if (mMax[iM] > mMin[iM]) mUpper[iM] = min( mUpper[iM], mMax[iM]);
1826  sLower[iM] = mLower[iM] * mLower[iM];
1827  sUpper[iM] = mUpper[iM] * mUpper[iM];
1828 
1829  // Prepare to select m3 by BW + flat + 1/s_3.
1830  // Determine relative coefficients by allowed mass range.
1831  if (distToThresh > THRESHOLDSIZE) {
1832  fracFlatS[iM] = 0.1;
1833  fracFlatM[iM] = 0.1;
1834  fracInv[iM] = 0.1;
1835  } else if (distToThresh > - THRESHOLDSIZE) {
1836  fracFlatS[iM] = 0.25 - 0.15 * distToThresh / THRESHOLDSIZE;
1837  fracInv [iM] = 0.15 - 0.05 * distToThresh / THRESHOLDSIZE;
1838  } else {
1839  fracFlatS[iM] = 0.3;
1840  fracFlatM[iM] = 0.1;
1841  fracInv[iM] = 0.2;
1842  }
1843 
1844  // For gamma*/Z0: increase 1/s_i part and introduce 1/s_i^2 part.
1845  fracInv2[iM] = 0.;
1846  if (idMass[iM] == 23 && gmZmode == 0) {
1847  fracFlatS[iM] *= 0.5;
1848  fracFlatM[iM] *= 0.5;
1849  fracInv[iM] = 0.5 * fracInv[iM] + 0.25;
1850  fracInv2[iM] = 0.25;
1851  } else if (idMass[iM] == 23 && gmZmode == 1) {
1852  fracFlatS[iM] = 0.1;
1853  fracFlatM[iM] = 0.1;
1854  fracInv[iM] = 0.35;
1855  fracInv2[iM] = 0.35;
1856  }
1857 
1858  // Normalization integrals for the respective contribution.
1859  atanLower[iM] = atan( (sLower[iM] - sPeak[iM])/ mw[iM] );
1860  atanUpper[iM] = atan( (sUpper[iM] - sPeak[iM])/ mw[iM] );
1861  intBW[iM] = atanUpper[iM] - atanLower[iM];
1862  intFlatS[iM] = sUpper[iM] - sLower[iM];
1863  intFlatM[iM] = mUpper[iM] - mLower[iM];
1864  intInv[iM] = log( sUpper[iM] / sLower[iM] );
1865  intInv2[iM] = 1./sLower[iM] - 1./sUpper[iM];
1866 
1867 }
1868 
1869 //--------------------------------------------------------------------------
1870 
1871 // Select Breit-Wigner-distributed or fixed masses.
1872 
1873 void PhaseSpace::trialMass(int iM) {
1874 
1875  // References to masses to be set.
1876  double& mSet = (iM == 3) ? m3 : ( (iM == 4) ? m4 : m5 );
1877  double& sSet = (iM == 3) ? s3 : ( (iM == 4) ? s4 : s5 );
1878 
1879  // Distribution for m_i is BW + flat(s) + 1/sqrt(s_i) + 1/s_i + 1/s_i^2.
1880  if (useBW[iM]) {
1881  double pickForm = rndmPtr->flat();
1882  if (pickForm > fracFlatS[iM] + fracFlatM[iM] + fracInv[iM] + fracInv2[iM])
1883  sSet = sPeak[iM] + mw[iM] * tan( atanLower[iM]
1884  + rndmPtr->flat() * intBW[iM] );
1885  else if (pickForm > fracFlatM[iM] + fracInv[iM] + fracInv2[iM])
1886  sSet = sLower[iM] + rndmPtr->flat() * (sUpper[iM] - sLower[iM]);
1887  else if (pickForm > fracInv[iM] + fracInv2[iM])
1888  sSet = pow2(mLower[iM] + rndmPtr->flat() * (mUpper[iM] - mLower[iM]));
1889  else if (pickForm > fracInv2[iM])
1890  sSet = sLower[iM] * pow( sUpper[iM] / sLower[iM], rndmPtr->flat() );
1891  else sSet = sLower[iM] * sUpper[iM]
1892  / (sLower[iM] + rndmPtr->flat() * (sUpper[iM] - sLower[iM]));
1893  mSet = sqrt(sSet);
1894 
1895  // Else m_i is fixed at peak value.
1896  } else {
1897  mSet = mPeak[iM];
1898  sSet = sPeak[iM];
1899  }
1900 
1901 }
1902 
1903 //--------------------------------------------------------------------------
1904 
1905 // Naively a fixed-width Breit-Wigner is used to pick the mass.
1906 // Here come the correction factors for
1907 // (i) preselection from BW + flat in s_i + 1/sqrt(s_i) + 1/s_i + 1/s_i^2,
1908 // (ii) reduced allowed mass range,
1909 // (iii) running width, i.e. m0*Gamma0 -> s*Gamma0/m0.
1910 // In the end, the weighted distribution is a running-width BW.
1911 
1912 double PhaseSpace::weightMass(int iM) {
1913 
1914  // Reference to mass and to Breit-Wigner weight to be set.
1915  double& mSet = (iM == 3) ? m3 : ( (iM == 4) ? m4 : m5 );
1916  double& sSet = (iM == 3) ? s3 : ( (iM == 4) ? s4 : s5 );
1917  double& runBWH = (iM == 3) ? runBW3H : ( (iM == 4) ? runBW4H : runBW5H );
1918 
1919  // Default weight if no Breit-Wigner.
1920  runBWH = 1.;
1921  if (!useBW[iM]) return 1.;
1922 
1923  // Weight of generated distribution.
1924  double genBW
1925  = (1. - fracFlatS[iM] - fracFlatM[iM] - fracInv[iM] - fracInv2[iM])
1926  * mw[iM] / ( (pow2(sSet - sPeak[iM]) + pow2(mw[iM])) * intBW[iM])
1927  + fracFlatS[iM] / intFlatS[iM]
1928  + fracFlatM[iM] / (2. * mSet * intFlatM[iM])
1929  + fracInv[iM] / (sSet * intInv[iM])
1930  + fracInv2[iM] / (sSet*sSet * intInv2[iM]);
1931 
1932  // Weight of distribution with running width in Breit-Wigner.
1933  double mwRun = sSet * wmRat[iM];
1934  //?? Alternative recipe, taking into account that decay channels close
1935  // at different mass thresholds Needs refining, e.g. no doublecouting
1936  // with openFrac and difference numerator/denominator.
1937  //double mwRun = mSet * particleDataPtr->resWidthOpen(idMass[iM], mSet);
1938  runBWH = mwRun / (pow2(sSet - sPeak[iM]) + pow2(mwRun)) / M_PI;
1939 
1940  // Done.
1941  return (runBWH / genBW);
1942 
1943 }
1944 
1945 //==========================================================================
1946 
1947 // PhaseSpace2to1tauy class.
1948 // 2 -> 1 kinematics for normal subprocesses.
1949 
1950 //--------------------------------------------------------------------------
1951 
1952 // Set limits for resonance mass selection.
1953 
1954 bool PhaseSpace2to1tauy::setupMass() {
1955 
1956  // Treat Z0 as such or as gamma*/Z0
1957  gmZmode = gmZmodeGlobal;
1958  int gmZmodeProc = sigmaProcessPtr->gmZmode();
1959  if (gmZmodeProc >= 0) gmZmode = gmZmodeProc;
1960 
1961  // Mass limits for current resonance.
1962  int idRes = abs(sigmaProcessPtr->resonanceA());
1963  int idTmp = abs(sigmaProcessPtr->resonanceB());
1964  if (idTmp > 0) idRes = idTmp;
1965  double mResMin = (idRes == 0) ? 0. : particleDataPtr->mMin(idRes);
1966  double mResMax = (idRes == 0) ? 0. : particleDataPtr->mMax(idRes);
1967 
1968  // Compare with global mass limits and pick tighter of them.
1969  mHatMin = max( mResMin, mHatGlobalMin);
1970  sHatMin = mHatMin*mHatMin;
1971  mHatMax = eCM;
1972  if (mResMax > mResMin) mHatMax = min( mHatMax, mResMax);
1973  if (mHatGlobalMax > mHatGlobalMin) mHatMax = min( mHatMax, mHatGlobalMax);
1974  sHatMax = mHatMax*mHatMax;
1975 
1976  // Default Breit-Wigner weight.
1977  wtBW = 1.;
1978 
1979  // Fail if mass window (almost) closed.
1980  return (mHatMax > mHatMin + MASSMARGIN);
1981 
1982 }
1983 
1984 //--------------------------------------------------------------------------
1985 
1986 // Construct the four-vector kinematics from the trial values.
1987 
1988 bool PhaseSpace2to1tauy::finalKin() {
1989 
1990  // Particle masses; incoming always on mass shell.
1991  mH[1] = 0.;
1992  mH[2] = 0.;
1993  mH[3] = mHat;
1994 
1995  // Incoming partons along beam axes. Outgoing has sum of momenta.
1996  pH[1] = Vec4( 0., 0., 0.5 * eCM * x1H, 0.5 * eCM * x1H);
1997  pH[2] = Vec4( 0., 0., -0.5 * eCM * x2H, 0.5 * eCM * x2H);
1998  pH[3] = pH[1] + pH[2];
1999 
2000  // Done.
2001  return true;
2002 }
2003 
2004 //==========================================================================
2005 
2006 // PhaseSpace2to2tauyz class.
2007 // 2 -> 2 kinematics for normal subprocesses.
2008 
2009 //--------------------------------------------------------------------------
2010 
2011 // Set up for fixed or Breit-Wigner mass selection.
2012 
2013 bool PhaseSpace2to2tauyz::setupMasses() {
2014 
2015  // Treat Z0 as such or as gamma*/Z0
2016  gmZmode = gmZmodeGlobal;
2017  int gmZmodeProc = sigmaProcessPtr->gmZmode();
2018  if (gmZmodeProc >= 0) gmZmode = gmZmodeProc;
2019 
2020  // Set sHat limits - based on global limits only.
2021  mHatMin = mHatGlobalMin;
2022  sHatMin = mHatMin*mHatMin;
2023  mHatMax = eCM;
2024  if (mHatGlobalMax > mHatGlobalMin) mHatMax = min( eCM, mHatGlobalMax);
2025  sHatMax = mHatMax*mHatMax;
2026 
2027  // Masses and widths of resonances.
2028  setupMass1(3);
2029  setupMass1(4);
2030 
2031  // Reduced mass range when two massive particles.
2032  if (useBW[3]) mUpper[3] -= (useBW[4]) ? mMin[4] : mPeak[4];
2033  if (useBW[4]) mUpper[4] -= (useBW[3]) ? mMin[3] : mPeak[3];
2034 
2035  // If closed phase space then unallowed process.
2036  bool physical = true;
2037  if (useBW[3] && mUpper[3] < mLower[3] + MASSMARGIN) physical = false;
2038  if (useBW[4] && mUpper[4] < mLower[4] + MASSMARGIN) physical = false;
2039  if (!useBW[3] && !useBW[4] && mHatMax < mPeak[3] + mPeak[4] + MASSMARGIN)
2040  physical = false;
2041  if (!physical) return false;
2042 
2043  // If either particle is massless then need extra pTHat cut.
2044  pTHatMin = pTHatGlobalMin;
2045  if (mPeak[3] < pTHatMinDiverge || mPeak[4] < pTHatMinDiverge)
2046  pTHatMin = max( pTHatMin, pTHatMinDiverge);
2047  pT2HatMin = pTHatMin * pTHatMin;
2048  pTHatMax = pTHatGlobalMax;
2049  pT2HatMax = pTHatMax * pTHatMax;
2050 
2051  // Prepare to select m3 by BW + flat + 1/s_3.
2052  if (useBW[3]) {
2053  double distToThreshA = (mHatMax - mPeak[3] - mPeak[4]) * mWidth[3]
2054  / (pow2(mWidth[3]) + pow2(mWidth[4]));
2055  double distToThreshB = (mHatMax - mPeak[3] - mMin[4]) / mWidth[3];
2056  double distToThresh = min( distToThreshA, distToThreshB);
2057  setupMass2(3, distToThresh);
2058  }
2059 
2060  // Prepare to select m4 by BW + flat + 1/s_4.
2061  if (useBW[4]) {
2062  double distToThreshA = (mHatMax - mPeak[3] - mPeak[4]) * mWidth[4]
2063  / (pow2(mWidth[3]) + pow2(mWidth[4]));
2064  double distToThreshB = (mHatMax - mMin[3] - mPeak[4]) / mWidth[4];
2065  double distToThresh = min( distToThreshA, distToThreshB);
2066  setupMass2(4, distToThresh);
2067  }
2068 
2069  // Initialization masses. Special cases when constrained phase space.
2070  m3 = (useBW[3]) ? min(mPeak[3], mUpper[3]) : mPeak[3];
2071  m4 = (useBW[4]) ? min(mPeak[4], mUpper[4]) : mPeak[4];
2072  if (m3 + m4 + THRESHOLDSIZE * (mWidth[3] + mWidth[4]) + MASSMARGIN
2073  > mHatMax) {
2074  if (useBW[3] && useBW[4]) physical = constrainedM3M4();
2075  else if (useBW[3]) physical = constrainedM3();
2076  else if (useBW[4]) physical = constrainedM4();
2077  }
2078  s3 = m3*m3;
2079  s4 = m4*m4;
2080 
2081  // Correct selected mass-spectrum to running-width Breit-Wigner.
2082  // Extra safety margin for maximum search.
2083  wtBW = 1.;
2084  if (useBW[3]) wtBW *= weightMass(3) * EXTRABWWTMAX;
2085  if (useBW[4]) wtBW *= weightMass(4) * EXTRABWWTMAX;
2086 
2087  // Done.
2088  return physical;
2089 
2090 }
2091 
2092 
2093 //--------------------------------------------------------------------------
2094 
2095 // Select Breit-Wigner-distributed or fixed masses.
2096 
2097 bool PhaseSpace2to2tauyz::trialMasses() {
2098 
2099  // By default vanishing cross section.
2100  sigmaNw = 0.;
2101  wtBW = 1.;
2102 
2103  // Pick m3 and m4 independently.
2104  trialMass(3);
2105  trialMass(4);
2106 
2107  // If outside phase space then reject event.
2108  if (m3 + m4 + MASSMARGIN > mHatMax) return false;
2109 
2110  // Correct selected mass-spectrum to running-width Breit-Wigner.
2111  if (useBW[3]) wtBW *= weightMass(3);
2112  if (useBW[4]) wtBW *= weightMass(4);
2113 
2114  // Done.
2115  return true;
2116 }
2117 
2118 //--------------------------------------------------------------------------
2119 
2120 // Construct the four-vector kinematics from the trial values.
2121 
2122 bool PhaseSpace2to2tauyz::finalKin() {
2123 
2124  // Assign masses to particles assumed massless in matrix elements.
2125  int id3 = sigmaProcessPtr->id(3);
2126  int id4 = sigmaProcessPtr->id(4);
2127  if (idMass[3] == 0) { m3 = particleDataPtr->m0(id3); s3 = m3*m3; }
2128  if (idMass[4] == 0) { m4 = particleDataPtr->m0(id4); s4 = m4*m4; }
2129 
2130  // Sometimes swap tHat <-> uHat to reflect chosen final-state order.
2131  if (sigmaProcessPtr->swappedTU()) {
2132  swap(tH, uH);
2133  z = -z;
2134  }
2135 
2136  // Check that phase space still open after new mass assignment.
2137  if (m3 + m4 + MASSMARGIN > mHat) {
2138  infoPtr->errorMsg("Warning in PhaseSpace2to2tauyz::finalKin: "
2139  "failed after mass assignment");
2140  return false;
2141  }
2142  p2Abs = 0.25 * (pow2(sH - s3 - s4) - 4. * s3 * s4) / sH;
2143  pAbs = sqrtpos( p2Abs );
2144 
2145  // Particle masses; incoming always on mass shell.
2146  mH[1] = 0.;
2147  mH[2] = 0.;
2148  mH[3] = m3;
2149  mH[4] = m4;
2150 
2151  // Special kinematics for direct photon+hadron (massless+massive) to fulfill
2152  // s = x1 * x2 * sHat and to retain the momentum of the massless photon beam.
2153  if ( hasPointGammaA && beamBPtr->isHadron() ) {
2154  double eCM1 = 0.5 * ( s + pow2(mA) - pow2(mB) ) / eCM;
2155  double eCM2 = 0.25 * x2H * s / eCM1;
2156  pH[1] = Vec4( 0., 0., eCM1, eCM1);
2157  pH[2] = Vec4( 0., 0., -eCM2, eCM2);
2158  } else if ( hasPointGammaB && beamAPtr->isHadron() ) {
2159  double eCM2 = 0.5 * ( s - pow2(mA) + pow2(mB) ) / eCM;
2160  double eCM1 = 0.25 * x1H * s / eCM2;
2161  pH[1] = Vec4( 0., 0., eCM1, eCM1);
2162  pH[2] = Vec4( 0., 0., -eCM2, eCM2);
2163 
2164  // Special kinematics for DIS to preserve lepton mass.
2165  } else if ( ( (beamAPtr->isLepton() && beamBPtr->isHadron())
2166  || (beamBPtr->isLepton() && beamAPtr->isHadron()) )
2167  && !settingsPtr->flag("PDF:lepton2gamma") ) {
2168  mH[1] = mA;
2169  mH[2] = mB;
2170  double pzAcm = 0.5 * sqrtpos( (eCM + mA + mB) * (eCM - mA - mB)
2171  * (eCM - mA + mB) * (eCM + mA - mB) ) / eCM;
2172  double eAcm = sqrt( mH[1]*mH[1] + pzAcm*pzAcm);
2173  double pzBcm = -pzAcm;
2174  double eBcm = sqrt( mH[2]*mH[2] + pzBcm*pzBcm);
2175  pH[1] = Vec4( 0., 0., pzAcm * x1H, eAcm * x1H);
2176  pH[2] = Vec4( 0., 0., pzBcm * x2H, eBcm * x2H);
2177 
2178  // Default kinematics with incoming partons along beam axes.
2179  } else {
2180  pH[1] = Vec4( 0., 0., 0.5 * eCM * x1H, 0.5 * eCM * x1H);
2181  pH[2] = Vec4( 0., 0., -0.5 * eCM * x2H, 0.5 * eCM * x2H);
2182  }
2183 
2184  // Outgoing partons initially in collision CM frame along beam axes.
2185  pH[3] = Vec4( 0., 0., pAbs, 0.5 * (sH + s3 - s4) / mHat);
2186  pH[4] = Vec4( 0., 0., -pAbs, 0.5 * (sH + s4 - s3) / mHat);
2187 
2188  // Then rotate and boost them to overall CM frame.
2189  theta = acos(z);
2190  phi = 2. * M_PI * rndmPtr->flat();
2191  betaZ = (x1H - x2H)/(x1H + x2H);
2192  pH[3].rot( theta, phi);
2193  pH[4].rot( theta, phi);
2194  pH[3].bst( 0., 0., betaZ);
2195  pH[4].bst( 0., 0., betaZ);
2196  pTH = pAbs * sin(theta);
2197 
2198  // Done.
2199  return true;
2200 }
2201 
2202 //--------------------------------------------------------------------------
2203 
2204 // Special choice of m3 and m4 when mHatMax push them off mass shell.
2205 // Vary x in expression m3 + m4 = mHatMax - x * (Gamma3 + Gamma4).
2206 // For each x try to put either 3 or 4 as close to mass shell as possible.
2207 // Maximize BW_3 * BW_4 * beta_34, where latter approximate phase space.
2208 
2209 bool PhaseSpace2to2tauyz::constrainedM3M4() {
2210 
2211  // Initial values.
2212  bool foundNonZero = false;
2213  double wtMassMax = 0.;
2214  double m3WtMax = 0.;
2215  double m4WtMax = 0.;
2216  double xMax = (mHatMax - mLower[3] - mLower[4]) / (mWidth[3] + mWidth[4]);
2217  double xStep = THRESHOLDSTEP * min(1., xMax);
2218  double xNow = 0.;
2219  double wtMassXbin, wtMassMaxOld, m34, mT34Min, wtMassNow,
2220  wtBW3Now, wtBW4Now, beta34Now;
2221 
2222  // Step through increasing x values.
2223  do {
2224  xNow += xStep;
2225  wtMassXbin = 0.;
2226  wtMassMaxOld = wtMassMax;
2227  m34 = mHatMax - xNow * (mWidth[3] + mWidth[4]);
2228 
2229  // Study point where m3 as close as possible to on-shell.
2230  m3 = min( mUpper[3], m34 - mLower[4]);
2231  if (m3 > mPeak[3]) m3 = max( mLower[3], mPeak[3]);
2232  m4 = m34 - m3;
2233  if (m4 < mLower[4]) {m4 = mLower[4]; m3 = m34 - m4;}
2234 
2235  // Check that inside phase space limit set by pTmin.
2236  mT34Min = sqrt(m3*m3 + pT2HatMin) + sqrt(m4*m4 + pT2HatMin);
2237  if (mT34Min < mHatMax) {
2238 
2239  // Breit-Wigners and beta factor give total weight.
2240  wtMassNow = 0.;
2241  if (m3 > mLower[3] && m3 < mUpper[3] && m4 > mLower[4]
2242  && m4 < mUpper[4]) {
2243  wtBW3Now = mw[3] / ( pow2(m3*m3 - sPeak[3]) + pow2(mw[3]) );
2244  wtBW4Now = mw[4] / ( pow2(m4*m4 - sPeak[4]) + pow2(mw[4]) );
2245  beta34Now = sqrt( pow2(mHatMax*mHatMax - m3*m3 - m4*m4)
2246  - pow2(2. * m3 * m4) ) / (mHatMax*mHatMax);
2247  wtMassNow = wtBW3Now * wtBW4Now * beta34Now;
2248  }
2249 
2250  // Store new maximum, if any.
2251  if (wtMassNow > wtMassXbin) wtMassXbin = wtMassNow;
2252  if (wtMassNow > wtMassMax) {
2253  foundNonZero = true;
2254  wtMassMax = wtMassNow;
2255  m3WtMax = m3;
2256  m4WtMax = m4;
2257  }
2258  }
2259 
2260  // Study point where m4 as close as possible to on-shell.
2261  m4 = min( mUpper[4], m34 - mLower[3]);
2262  if (m4 > mPeak[4]) m4 = max( mLower[4], mPeak[4]);
2263  m3 = m34 - m4;
2264  if (m3 < mLower[3]) {m3 = mLower[3]; m4 = m34 - m3;}
2265 
2266  // Check that inside phase space limit set by pTmin.
2267  mT34Min = sqrt(m3*m3 + pT2HatMin) + sqrt(m4*m4 + pT2HatMin);
2268  if (mT34Min < mHatMax) {
2269 
2270  // Breit-Wigners and beta factor give total weight.
2271  wtMassNow = 0.;
2272  if (m3 > mLower[3] && m3 < mUpper[3] && m4 > mLower[4]
2273  && m4 < mUpper[4]) {
2274  wtBW3Now = mw[3] / ( pow2(m3*m3 - sPeak[3]) + pow2(mw[3]) );
2275  wtBW4Now = mw[4] / ( pow2(m4*m4 - sPeak[4]) + pow2(mw[4]) );
2276  beta34Now = sqrt( pow2(mHatMax*mHatMax - m3*m3 - m4*m4)
2277  - pow2(2. * m3 * m4) ) / (mHatMax*mHatMax);
2278  wtMassNow = wtBW3Now * wtBW4Now * beta34Now;
2279  }
2280 
2281  // Store new maximum, if any.
2282  if (wtMassNow > wtMassXbin) wtMassXbin = wtMassNow;
2283  if (wtMassNow > wtMassMax) {
2284  foundNonZero = true;
2285  wtMassMax = wtMassNow;
2286  m3WtMax = m3;
2287  m4WtMax = m4;
2288  }
2289  }
2290 
2291  // Continue stepping if increasing trend and more x range available.
2292  } while ( (!foundNonZero || wtMassXbin > wtMassMaxOld)
2293  && xNow < xMax - xStep);
2294 
2295  // Restore best values for subsequent maximization. Return.
2296  m3 = m3WtMax;
2297  m4 = m4WtMax;
2298  return foundNonZero;
2299 
2300 }
2301 
2302 //--------------------------------------------------------------------------
2303 
2304 // Special choice of m3 when mHatMax pushes it off mass shell.
2305 // Vary x in expression m3 = mHatMax - m4 - x * Gamma3.
2306 // Maximize BW_3 * beta_34, where latter approximate phase space.
2307 
2308 bool PhaseSpace2to2tauyz::constrainedM3() {
2309 
2310  // Initial values.
2311  bool foundNonZero = false;
2312  double wtMassMax = 0.;
2313  double m3WtMax = 0.;
2314  double mT4Min = sqrt(m4*m4 + pT2HatMin);
2315  double xMax = (mHatMax - mLower[3] - m4) / mWidth[3];
2316  double xStep = THRESHOLDSTEP * min(1., xMax);
2317  double xNow = 0.;
2318  double wtMassNow, mT34Min, wtBW3Now, beta34Now;
2319 
2320  // Step through increasing x values; gives m3 unambiguously.
2321  do {
2322  xNow += xStep;
2323  wtMassNow = 0.;
2324  m3 = mHatMax - m4 - xNow * mWidth[3];
2325 
2326  // Check that inside phase space limit set by pTmin.
2327  mT34Min = sqrt(m3*m3 + pT2HatMin) + mT4Min;
2328  if (mT34Min < mHatMax) {
2329 
2330  // Breit-Wigner and beta factor give total weight.
2331  wtBW3Now = mw[3] / ( pow2(m3*m3 - sPeak[3]) + pow2(mw[3]) );
2332  beta34Now = sqrt( pow2(mHatMax*mHatMax - m3*m3 - m4*m4)
2333  - pow2(2. * m3 * m4) ) / (mHatMax*mHatMax);
2334  wtMassNow = wtBW3Now * beta34Now;
2335 
2336  // Store new maximum, if any.
2337  if (wtMassNow > wtMassMax) {
2338  foundNonZero = true;
2339  wtMassMax = wtMassNow;
2340  m3WtMax = m3;
2341  }
2342  }
2343 
2344  // Continue stepping if increasing trend and more x range available.
2345  } while ( (!foundNonZero || wtMassNow > wtMassMax)
2346  && xNow < xMax - xStep);
2347 
2348  // Restore best value for subsequent maximization. Return.
2349  m3 = m3WtMax;
2350  return foundNonZero;
2351 
2352 }
2353 
2354 //--------------------------------------------------------------------------
2355 
2356 // Special choice of m4 when mHatMax pushes it off mass shell.
2357 // Vary x in expression m4 = mHatMax - m3 - x * Gamma4.
2358 // Maximize BW_4 * beta_34, where latter approximate phase space.
2359 
2360 bool PhaseSpace2to2tauyz::constrainedM4() {
2361 
2362  // Initial values.
2363  bool foundNonZero = false;
2364  double wtMassMax = 0.;
2365  double m4WtMax = 0.;
2366  double mT3Min = sqrt(m3*m3 + pT2HatMin);
2367  double xMax = (mHatMax - mLower[4] - m3) / mWidth[4];
2368  double xStep = THRESHOLDSTEP * min(1., xMax);
2369  double xNow = 0.;
2370  double wtMassNow, mT34Min, wtBW4Now, beta34Now;
2371 
2372  // Step through increasing x values; gives m4 unambiguously.
2373  do {
2374  xNow += xStep;
2375  wtMassNow = 0.;
2376  m4 = mHatMax - m3 - xNow * mWidth[4];
2377 
2378  // Check that inside phase space limit set by pTmin.
2379  mT34Min = mT3Min + sqrt(m4*m4 + pT2HatMin);
2380  if (mT34Min < mHatMax) {
2381 
2382  // Breit-Wigner and beta factor give total weight.
2383  wtBW4Now = mw[4] / ( pow2(m4*m4 - sPeak[4]) + pow2(mw[4]) );
2384  beta34Now = sqrt( pow2(mHatMax*mHatMax - m3*m3 - m4*m4)
2385  - pow2(2. * m3 * m4) ) / (mHatMax*mHatMax);
2386  wtMassNow = wtBW4Now * beta34Now;
2387 
2388  // Store new maximum, if any.
2389  if (wtMassNow > wtMassMax) {
2390  foundNonZero = true;
2391  wtMassMax = wtMassNow;
2392  m4WtMax = m4;
2393  }
2394  }
2395 
2396  // Continue stepping if increasing trend and more x range available.
2397  } while ( (!foundNonZero || wtMassNow > wtMassMax)
2398  && xNow < xMax - xStep);
2399 
2400  // Restore best value for subsequent maximization.
2401  m4 = m4WtMax;
2402  return foundNonZero;
2403 
2404 }
2405 
2406 //--------------------------------------------------------------------------
2407 
2408 // Calculate the cross section with rescaled sHat.
2409 
2410 void PhaseSpace2to2tauyz::rescaleSigma(double sHatNew){
2411 
2412  // With massless matrix element derive tHat without masses.
2413  if ( idMass[3] == 0 ) s3 = 0.;
2414  if ( idMass[4] == 0 ) s4 = 0.;
2415 
2416  // Update variables according to new sHat.
2417  sH = sHatNew;
2418  double sH34 = -0.5 * (sH - s3 - s4);
2419  p2Abs = 0.25 * (pow2(sH - s3 - s4) - 4. * s3 * s4) / sH;
2420  pAbs = sqrtpos( p2Abs );
2421  mHat = sqrt(sH);
2422  tH = sH34 + mHat * pAbs * z;
2423  uH = sH34 - mHat * pAbs * z;
2424  pTH = sqrtpos( (tH * uH - s3 * s4) / sH);
2425 
2426  // Calculate the cross section for the process with rescaled kinematics
2427  // if original cross section non-zero.
2428  if (sigmaNw > TINY) {
2429  sigmaProcessPtr->set2Kin( x1H, x2H, sH, tH, m3, m4, runBW3H, runBW4H);
2430  sigmaNw = sigmaProcessPtr->sigmaPDF(false, true);
2431  sigmaNw *= wtTau * wtY * wtZ * wtBW;
2432  if (canBias2Sel) sigmaNw *= pow( pTH / bias2SelRef, bias2SelPow);
2433  }
2434 
2435 }
2436 
2437 //--------------------------------------------------------------------------
2438 
2439 // Rescales the momenta of incoming and outgoing partons according to
2440 // new sHat sampled in GammaKinematics.
2441 
2442 void PhaseSpace2to2tauyz::rescaleMomenta( double sHatNew){
2443 
2444  // Loop over initial and final partons.
2445  for (int i = 0; i <= 1; ++i){
2446 
2447  // Either final or initial partons.
2448  int iPartonA = (i == 0) ? 1 : 3;
2449  int iPartonB = (i == 0) ? 2 : 4;
2450 
2451  // Original momenta of partons.
2452  Vec4 pA = p( iPartonA);
2453  Vec4 pB = p( iPartonB);
2454 
2455  // Calculate new momenta in CM-frame.
2456  double m2A = pow2( m( iPartonA) );
2457  double m2B = pow2( m( iPartonB) );
2458  double eA = 0.5 * ( sHatNew + m2A - m2B) / sqrt( sHatNew);
2459  double eB = 0.5 * ( sHatNew + m2B - m2A) / sqrt( sHatNew);
2460  double pz = 0.5 * sqrtpos( pow2(sHatNew - m2A - m2B) - 4.0 * m2A * m2B )
2461  / sqrt( sHatNew);
2462  Vec4 pANew( 0, 0, pz, eA );
2463  Vec4 pBNew( 0, 0, -pz, eB );
2464 
2465  // Find boost to original frame.
2466  RotBstMatrix MtoCMinc;
2467  MtoCMinc.toCMframe( pA, pB);
2468  MtoCMinc.invert();
2469 
2470  // Boost outgoing partons to original frame and replace the momenta.
2471  pANew.rotbst( MtoCMinc);
2472  pBNew.rotbst( MtoCMinc);
2473  setP( iPartonA, pANew);
2474  setP( iPartonB, pBNew);
2475  }
2476 }
2477 
2478 //--------------------------------------------------------------------------
2479 
2480 // Calculates the cross-section weight for overestimated photon flux.
2481 
2482 double PhaseSpace2to2tauyz::weightGammaPDFApprox(){
2483 
2484  // No need for reweighting if only direct photons.
2485  if (beamAPtr->getGammaMode() == 2 && beamBPtr->getGammaMode() == 2)
2486  return 1.;
2487  if ( (beamAPtr->getGammaMode() == 2 && beamBPtr->isHadron())
2488  || (beamBPtr->getGammaMode() == 2 && beamAPtr->isHadron()) )
2489  return 1.;
2490 
2491  // Get the combined x and x_gamma values and derive x'.
2492  double x1GammaHadr = beamAPtr->xGammaHadr();
2493  double x2GammaHadr = beamBPtr->xGammaHadr();
2494  double x1Gamma = beamAPtr->xGamma();
2495  double x2Gamma = beamBPtr->xGamma();
2496  double x1Hadr = x1GammaHadr / x1Gamma;
2497  double x2Hadr = x2GammaHadr / x2Gamma;
2498 
2499  // For photon-hadron case do not reweight the hadron side.
2500  if ( beamAPtr->isHadron() || beamAPtr->getGammaMode() == 2 ) {
2501  x1GammaHadr = -1.;
2502  x1Gamma = -1.;
2503  }
2504  if ( beamBPtr->isHadron() || beamBPtr->getGammaMode() == 2 ) {
2505  x2GammaHadr = -1.;
2506  x2Gamma = -1.;
2507  }
2508 
2509  // Calculate the over-estimated PDF convolution and the current one.
2510  double sigmaOver = sigmaProcessPtr->sigmaPDF(false, false, true,
2511  x1GammaHadr, x2GammaHadr);
2512  double sigmaCorr = sigmaProcessPtr->sigmaPDF(false, false, true,
2513  x1Hadr, x2Hadr);
2514 
2515  // Make sure that the over estimate is finite.
2516  if (sigmaOver < TINY) return 0.;
2517 
2518  // Return weight.
2519  return sigmaCorr / sigmaOver;
2520 
2521 }
2522 
2523 //==========================================================================
2524 
2525 // PhaseSpace2to2elastic class.
2526 // 2 -> 2 kinematics set up for elastic scattering.
2527 
2528 //--------------------------------------------------------------------------
2529 
2530 // Constants: could be changed here if desired, but normally should not.
2531 // These are of technical nature, as described for each.
2532 
2533 // Max number of tries to find acceptable t.
2534 const int PhaseSpace2to2elastic::NTRY = 1000;
2535 
2536 // Conversion coefficient (mb <-> GeV^2).
2537 const double PhaseSpace2to2elastic::HBARC2 = 0.38938;
2538 
2539 // Width and relative importance of two exponentials.
2540 const double PhaseSpace2to2elastic::BNARROW = 10.;
2541 const double PhaseSpace2to2elastic::BWIDE = 1.;
2542 const double PhaseSpace2to2elastic::WIDEFRAC = 0.1;
2543 const double PhaseSpace2to2elastic::TOFFSET = -0.2;
2544 
2545 //--------------------------------------------------------------------------
2546 
2547 // Form of phase space sampling already fixed, so no optimization.
2548 // However, need to read out relevant parameters from SigmaTotal.
2549 
2550 bool PhaseSpace2to2elastic::setupSampling() {
2551 
2552  // Find maximum = value of cross section.
2553  sigmaNw = sigmaProcessPtr->sigmaHatWrap();
2554  sigmaMx = sigmaNw;
2555 
2556  // Squared and outgoing masses of particles.
2557  s1 = mA * mA;
2558  s2 = mB * mB;
2559  m3 = mA;
2560  m4 = mB;
2561 
2562  // Character of elastic generation.
2563  isOneExp = sigmaTotPtr->bElIsExp();
2564  useCoulomb = sigmaTotPtr->hasCoulomb();
2565  alphaEM0 = settingsPtr->parm("StandardModel:alphaEM0");
2566 
2567  // Determine maximum possible t range.
2568  lambda12S = pow2(s - s1 - s2) - 4. * s1 * s2 ;
2569  tLow = - lambda12S / s;
2570  tUpp = (useCoulomb) ? -settingsPtr->parm("SigmaElastic:tAbsMin") : 0.;
2571 
2572  // Upper estimate as sum of two exponentials and a Coulomb.
2573  bSlope1 = (isOneExp) ? sigmaTotPtr->bSlopeEl() : BNARROW;
2574  bSlope2 = BWIDE;
2575  sigRef1 = sigmaTotPtr->dsigmaEl( tUpp, false);
2576  if (isOneExp) {
2577  sigNorm1 = sigRef1 / bSlope1;
2578  if (useCoulomb) sigNorm1 *= 2.;
2579  sigNorm2 = 0.;
2580  } else {
2581  sigRef2 = sigmaTotPtr->dsigmaEl( tUpp + TOFFSET, false);
2582  sigRef = (sigRef1 > 2. * sigRef2) ? 2. * sigRef1 : 5. * sigRef2;
2583  rel2 = exp((bSlope2 - bSlope1) * tUpp) * WIDEFRAC / (1. - WIDEFRAC);
2584  sigNorm1 = sigRef / (bSlope1 + rel2 * bSlope2);
2585  sigNorm2 = sigNorm1 * rel2;
2586  }
2587  sigNorm3 = (useCoulomb) ? -2. * HBARC2 * 4. * M_PI * pow2(alphaEM0)
2588  / tUpp : 0.;
2589  sigNormSum = sigNorm1 + sigNorm2 + sigNorm3;
2590 
2591  // Done.
2592  return true;
2593 
2594 }
2595 
2596 //--------------------------------------------------------------------------
2597 
2598 // Select a trial kinematics phase space point. Perform full
2599 // Monte Carlo acceptance/rejection at this stage.
2600 
2601 bool PhaseSpace2to2elastic::trialKin( bool, bool ) {
2602 
2603  // Allow for possibility that energy varies from event to event.
2604  if (doEnergySpread) {
2605  eCM = infoPtr->eCM();
2606  s = eCM * eCM;
2607  lambda12S = pow2(s - s1 - s2) - 4. * s1 * s2 ;
2608  tLow = - lambda12S / s;
2609  }
2610 
2611  // Repeated tries until accepted.
2612  double rNow, bNow, sigNow, sigEst;
2613  int loop = 0;
2614  do {
2615  ++loop;
2616  if (loop == NTRY) {
2617  infoPtr->errorMsg("Error in PhaseSpace2to2elastic::trialKin: "
2618  " quit after repeated tries");
2619  return false;
2620  }
2621  rNow = rndmPtr->flat() * sigNormSum;
2622  if (useCoulomb && rNow > sigNorm1 + sigNorm2) tH = tUpp / rndmPtr->flat();
2623  else {
2624  bNow = (rNow < sigNorm1) ? bSlope1 : bSlope2;
2625  tH = tUpp + log( rndmPtr->flat() ) / bNow;
2626  }
2627  sigNow = sigmaTotPtr->dsigmaEl( tH, useCoulomb);
2628  sigEst = sigNorm1 * bSlope1 * exp( bSlope1 * (tH - tUpp))
2629  + sigNorm2 * bSlope2 * exp( bSlope2 * (tH - tUpp));
2630  if (useCoulomb) sigEst += sigNorm3 * (-tUpp) / pow2(tH);
2631  } while (tH < tLow || sigNow < sigEst * rndmPtr->flat());
2632  if (sigNow > 1.01 * sigEst) infoPtr->errorMsg("Warning in "
2633  "PhaseSpace2to2elastic::trialKin: cross section maximum violated");
2634 
2635  // Careful reconstruction of scattering angle.
2636  double tRat = s * tH / lambda12S;
2637  double cosTheta = min(1., max(-1., 1. + 2. * tRat ) );
2638  double sinTheta = 2. * sqrtpos( -tRat * (1. + tRat) );
2639  theta = asin( min(1., sinTheta));
2640  if (cosTheta < 0.) theta = M_PI - theta;
2641 
2642  // Done.
2643  return true;
2644 
2645 }
2646 
2647 //--------------------------------------------------------------------------
2648 
2649 // Construct the four-vector kinematics from the trial values.
2650 
2651 bool PhaseSpace2to2elastic::finalKin() {
2652 
2653  // Particle masses.
2654  mH[1] = mA;
2655  mH[2] = mB;
2656  mH[3] = m3;
2657  mH[4] = m4;
2658 
2659  // Incoming particles along beam axes.
2660  pAbs = 0.5 * sqrtpos(lambda12S) / eCM;
2661  pH[1] = Vec4( 0., 0., pAbs, 0.5 * (s + s1 - s2) / eCM);
2662  pH[2] = Vec4( 0., 0., -pAbs, 0.5 * (s + s2 - s1) / eCM);
2663 
2664  // Outgoing particles initially along beam axes.
2665  pH[3] = Vec4( 0., 0., pAbs, 0.5 * (s + s1 - s2) / eCM);
2666  pH[4] = Vec4( 0., 0., -pAbs, 0.5 * (s + s2 - s1) / eCM);
2667 
2668  // Then rotate them
2669  phi = 2. * M_PI * rndmPtr->flat();
2670  pH[3].rot( theta, phi);
2671  pH[4].rot( theta, phi);
2672 
2673  // Set some further info for completeness.
2674  x1H = 1.;
2675  x2H = 1.;
2676  sH = s;
2677  uH = 2. * (s1 + s2) - sH - tH;
2678  mHat = eCM;
2679  p2Abs = pAbs * pAbs;
2680  betaZ = 0.;
2681  pTH = pAbs * sin(theta);
2682 
2683  // Done.
2684  return true;
2685 
2686 }
2687 
2688 //==========================================================================
2689 
2690 // PhaseSpace2to2diffractive class.
2691 // 2 -> 2 kinematics set up for diffractive scattering.
2692 
2693 //--------------------------------------------------------------------------
2694 
2695 // Constants: could be changed here if desired, but normally should not.
2696 // These are of technical nature, as described for each.
2697 
2698 // Number of tries to find acceptable (m^2, t) set.
2699 const int PhaseSpace2to2diffractive::NTRY = 2500;
2700 
2701 // t is sampled according to sum of four distributions.
2702 const double PhaseSpace2to2diffractive::BWID1 = 8.;
2703 const double PhaseSpace2to2diffractive::BWID2 = 2.;
2704 const double PhaseSpace2to2diffractive::BWID3 = 0.5;
2705 const double PhaseSpace2to2diffractive::BWID4 = 0.2;
2706 const double PhaseSpace2to2diffractive::FWID1SD = 1.;
2707 const double PhaseSpace2to2diffractive::FWID2SD = 0.2;
2708 const double PhaseSpace2to2diffractive::FWID3SD = 0.1;
2709 const double PhaseSpace2to2diffractive::FWID4SD = 0.1;
2710 const double PhaseSpace2to2diffractive::FWID1DD = 0.1;
2711 const double PhaseSpace2to2diffractive::FWID2DD = 1.;
2712 const double PhaseSpace2to2diffractive::FWID3DD = 0.5;
2713 const double PhaseSpace2to2diffractive::FWID4DD = 0.2;
2714 
2715 // Safety margins for upper estimate of cross section.
2716 const double PhaseSpace2to2diffractive::MAXFUDGESD = 2.;
2717 const double PhaseSpace2to2diffractive::MAXFUDGEDD = 2.;
2718 const double PhaseSpace2to2diffractive::MAXFUDGET = 4.;
2719 
2720 // Safety margin so sum of masses not too close to eCM.
2721 const double PhaseSpace2to2diffractive::DIFFMASSMARGIN = 0.2;
2722 
2723 // Squared proton mass.
2724 const double PhaseSpace2to2diffractive::SPROTON = 0.8803544;
2725 
2726 //--------------------------------------------------------------------------
2727 
2728 // Form of phase space sampling already fixed, so no optimization.
2729 // However, need to find upper estimate at t = 0.
2730 
2731 bool PhaseSpace2to2diffractive::setupSampling() {
2732 
2733  // Find maximum = value of cross section.
2734  sigmaNw = sigmaProcessPtr->sigmaHatWrap();
2735  sigmaMx = sigmaNw;
2736 
2737  // Masses of particles and minimal masses of diffractive states.
2738  double mPi = particleDataPtr->m0(211);
2739  m3ElDiff = (isDiffA) ? mA + mPi : mA;
2740  m4ElDiff = (isDiffB) ? mB + mPi : mB;
2741  s1 = mA * mA;
2742  s2 = mB * mB;
2743  s3 = pow2( m3ElDiff);
2744  s4 = pow2( m4ElDiff);
2745 
2746  // Initial kinematics value.
2747  lambda12 = sqrtpos( pow2( s - s1 - s2) - 4. * s1 * s2 );
2748 
2749  // Scenarios with separate handling of xi and t (currently only MBR).
2750  // Step 0 = both xi and t, 1 = xi only, 2 = t only.
2751  splitxit = sigmaTotPtr->splitDiff();
2752  int step = (splitxit) ? 1 : 0;
2753 
2754  // Find maximal cross section xi * dsigma / (dxi dt) at t = 0.
2755  sigMax = 0.;
2756  if (isSD) {
2757  xiMin = (isDiffA) ? s3 / s : s4 / s;
2758  for (int i = 0; i < 100; ++i) {
2759  xiNow = pow( xiMin, 0.01 * i + 0.005);
2760  sigNow = sigmaTotPtr->dsigmaSD( xiNow, 0., isDiffA, step);
2761  if (sigNow > sigMax) sigMax = sigNow;
2762  }
2763 
2764  // Find maximal cross section xi1 * xi2 * dsigma / (dxi1 dxi2 dt) at t = 0.
2765  } else {
2766  xiMin = max( s3, s4) / s;
2767  xiMax = sqrt( SPROTON / s);
2768  for (int i = 0; i < 100; ++i) {
2769  xiNow = xiMin * pow( xiMax / xiMin, 0.01 * i + 0.005);
2770  sigNow = sigmaTotPtr->dsigmaDD( xiNow, xiNow, 0., step);
2771  if (sigNow > sigMax) sigMax = sigNow;
2772  }
2773  }
2774  sigMax *= (isSD ? MAXFUDGESD : MAXFUDGEDD);
2775 
2776  // Combinations of t sampling parameters.
2777  fWid1 = (isSD ? FWID1SD : FWID1DD);
2778  fWid2 = (isSD ? FWID2SD : FWID2DD);
2779  fWid3 = (isSD ? FWID3SD : FWID3DD);
2780  fWid4 = (isSD ? FWID4SD : FWID4DD);
2781  fbWid1 = fWid1 * BWID1;
2782  fbWid2 = fWid2 * BWID2;
2783  fbWid3 = fWid3 * BWID3;
2784  fbWid4 = fWid4 * BWID4;
2785  fbWid1234 = fbWid1 + fbWid2 + fbWid3 + fbWid4;
2786 
2787  // Done.
2788  return true;
2789 
2790 }
2791 
2792 //--------------------------------------------------------------------------
2793 
2794 // Select a trial kinematics phase space point. Perform full
2795 // Monte Carlo acceptance/rejection at this stage.
2796 
2797 bool PhaseSpace2to2diffractive::trialKin( bool, bool ) {
2798 
2799  // Allow for possibility that energy varies from event to event.
2800  if (doEnergySpread) {
2801  eCM = infoPtr->eCM();
2802  s = eCM * eCM;
2803  lambda12 = sqrtpos( pow2( s - s1 - s2) - 4. * s1 * s2 );
2804  }
2805 
2806  // Normally xi and t in one step, but possible to split into two.
2807  int nStep = (splitxit) ? 2 : 1;
2808  for (int iStep = 0; iStep < nStep; ++iStep) {
2809  int step = (splitxit) ? iStep + 1 : 0;
2810 
2811  // Loop over attempts to set up masses and t consistently.
2812  for (int loop = 0; ; ++loop) {
2813  if (loop == NTRY) {
2814  infoPtr->errorMsg("Error in PhaseSpace2to2diffractive::trialKin: "
2815  " quit after repeated tries");
2816  return false;
2817  }
2818 
2819  // Select diffractive mass(es) according to dm^2/m^2.
2820  if (iStep == 0) {
2821  m3 = (isDiffA) ? m3ElDiff * pow( max(mA, eCM - m4ElDiff) / m3ElDiff,
2822  rndmPtr->flat()) : m3ElDiff;
2823  m4 = (isDiffB) ? m4ElDiff * pow( max(mB, eCM - m3ElDiff) / m4ElDiff,
2824  rndmPtr->flat()) : m4ElDiff;
2825  if (m3 + m4 + DIFFMASSMARGIN >= eCM) continue;
2826  s3 = m3 * m3;
2827  s4 = m4 * m4;
2828  }
2829 
2830  // Select t according to exp(b*t), b picked among four options.
2831  if (step != 1) {
2832  double pickb = rndmPtr->flat() * (fWid1 + fWid2 + fWid3 + fWid4);
2833  bNow = (pickb < fWid1) ? BWID1
2834  : ( (pickb < fWid1 + fWid2) ? BWID2
2835  : ( (pickb < fWid1 + fWid2 + fWid3) ? BWID3 : BWID4 ) );
2836  tH = log(rndmPtr->flat()) / bNow;
2837 
2838  // Check whether m^2 and t choices are consistent.
2839  lambda34 = sqrtpos( pow2( s - s3 - s4) - 4. * s3 * s4 );
2840  tempA = s - (s1 + s2 + s3 + s4) + (s1 - s2) * (s3 - s4) / s;
2841  tempB = lambda12 * lambda34 / s;
2842  tempC = (s3 - s1) * (s4 - s2) + (s1 + s4 - s2 - s3)
2843  * (s1 * s4 - s2 * s3) / s;
2844  tLow = -0.5 * (tempA + tempB);
2845  tUpp = tempC / tLow;
2846  if (tH < tLow || tH > tUpp) continue;
2847  }
2848 
2849  // Evaluate single or double diffractive cross section.
2850  if (isSD) {
2851  xiNow = (isDiffA) ? s3 / s : s4 / s;
2852  sigNow = sigmaTotPtr->dsigmaSD( xiNow, tH, isDiffA, step);
2853  } else {
2854  sigNow = sigmaTotPtr->dsigmaDD( s3 / s, s4 / s, tH, step);
2855  }
2856 
2857  // Maximum weight based on sampling strategy.
2858  tWeight = ( fbWid1 * exp( BWID1 * tH) + fbWid2 * exp(BWID2 * tH)
2859  + fbWid3 * exp(BWID3 * tH) + fbWid4 * exp(BWID4 * tH) ) / fbWid1234;
2860  sigMaxNow = (step == 0) ? sigMax * tWeight
2861  : ( (step == 1) ? sigMax : MAXFUDGET * tWeight );
2862 
2863  // Check for maximum violations. Possibly break out of the loop.
2864  if (sigNow > sigMaxNow) infoPtr->errorMsg("Error in PhaseSpace2to2"
2865  "diffractive::trialKin: maximum cross section violated");
2866  if (sigNow > rndmPtr->flat() * sigMaxNow) break;
2867 
2868  // End of loops over tries and steps.
2869  }
2870  }
2871 
2872  // Careful reconstruction of scattering angle.
2873  double cosTheta = min(1., max(-1., (tempA + 2. * tH) / tempB));
2874  double sinTheta = 2. * sqrtpos( -(tempC + tempA * tH + tH * tH) ) / tempB;
2875  theta = asin( min(1., sinTheta));
2876  if (cosTheta < 0.) theta = M_PI - theta;
2877 
2878  // Done.
2879  return true;
2880 
2881 }
2882 
2883 //--------------------------------------------------------------------------
2884 
2885 // Construct the four-vector kinematics from the trial values.
2886 
2887 bool PhaseSpace2to2diffractive::finalKin() {
2888 
2889  // Particle masses; incoming always on mass shell.
2890  mH[1] = mA;
2891  mH[2] = mB;
2892  mH[3] = m3;
2893  mH[4] = m4;
2894 
2895  // Incoming particles along beam axes.
2896  pAbs = 0.5 * lambda12 / eCM;
2897  pH[1] = Vec4( 0., 0., pAbs, 0.5 * (s + s1 - s2) / eCM);
2898  pH[2] = Vec4( 0., 0., -pAbs, 0.5 * (s + s2 - s1) / eCM);
2899 
2900  // Outgoing particles initially along beam axes.
2901  pAbs = 0.5 * lambda34 / eCM;
2902  pH[3] = Vec4( 0., 0., pAbs, 0.5 * (s + s3 - s4) / eCM);
2903  pH[4] = Vec4( 0., 0., -pAbs, 0.5 * (s + s4 - s3) / eCM);
2904 
2905  // Then rotate them
2906  phi = 2. * M_PI * rndmPtr->flat();
2907  pH[3].rot( theta, phi);
2908  pH[4].rot( theta, phi);
2909 
2910  // Set some further info for completeness (but Info can be for subprocess).
2911  x1H = 1.;
2912  x2H = 1.;
2913  sH = s;
2914  uH = s1 + s2 + s3 + s4 - sH - tH;
2915  mHat = eCM;
2916  p2Abs = pAbs * pAbs;
2917  betaZ = 0.;
2918  pTH = pAbs * sin(theta);
2919 
2920  // Done.
2921  return true;
2922 
2923 }
2924 
2925 //==========================================================================
2926 
2927 // PhaseSpace2to3diffractive class.
2928 // 2 -> 3 kinematics set up for central diffractive scattering.
2929 
2930 //--------------------------------------------------------------------------
2931 
2932 // Constants: could be changed here if desired, but normally should not.
2933 // These are of technical nature, as described for each.
2934 
2935 // Number of tries to find acceptable (xi1, xi2, t1, t2) set.
2936 const int PhaseSpace2to3diffractive::NTRY = 2500;
2937 
2938 // t is sampled according to sum of three distributions.
2939 const double PhaseSpace2to3diffractive::BWID1 = 8.;
2940 const double PhaseSpace2to3diffractive::BWID2 = 4.;
2941 const double PhaseSpace2to3diffractive::BWID3 = 1.;
2942 const double PhaseSpace2to3diffractive::FWID1 = 1.;
2943 const double PhaseSpace2to3diffractive::FWID2 = 0.4;
2944 const double PhaseSpace2to3diffractive::FWID3 = 0.1;
2945 
2946 // Safety margins for upper estimate of cross section.
2947 const double PhaseSpace2to3diffractive::MAXFUDGECD = 2.5;
2948 const double PhaseSpace2to3diffractive::MAXFUDGET = 10.0;
2949 
2950 // Safety margin so sum of masses not too close to eCM.
2951 const double PhaseSpace2to3diffractive::DIFFMASSMARGIN = 0.2;
2952 
2953 //--------------------------------------------------------------------------
2954 
2955 // Set up for phase space sampling.
2956 
2957 bool PhaseSpace2to3diffractive::setupSampling() {
2958 
2959  // Find maximum = value of cross section.
2960  sigmaNw = sigmaProcessPtr->sigmaHatWrap();
2961  sigmaMx = sigmaNw;
2962 
2963  // Squared masses of particles and minimal mass of diffractive states.
2964  s1 = mA * mA;
2965  s2 = mB * mB;
2966  s3 = s1;
2967  s4 = s2;
2968  m5min = sigmaTotPtr->mMinCD();
2969  s5min = m5min * m5min;
2970 
2971  // Scenarios with separate handling of xi and t (currently only MBR).
2972  // Step 0 = both xi and t, 1 = xi only, 2 = t only.
2973  splitxit = sigmaTotPtr->splitDiff();
2974  int step = (splitxit) ? 1 : 0;
2975 
2976  // Find maximal cross section xi1 * xi2 * dsigma / (dxi1 dxi2 dt1 dt2)
2977  // at t1 = t2 = 0 and grid in (xi1, xi2).
2978  sigMax = 0.;
2979  xiMin = s5min / s;
2980  for (int i = 0; i < 100; ++i)
2981  for (int j = 0; j <= i; ++j) {
2982  xi1 = pow( xiMin, 0.01 * i + 0.005);
2983  xi2 = pow( xiMin, 0.01 * j + 0.005);
2984  if (xi1 * xi2 > xiMin) {
2985  sigNow = sigmaTotPtr->dsigmaCD( xi1, xi2, 0., 0., step);
2986  if (sigNow > sigMax) sigMax = sigNow;
2987  }
2988  }
2989  sigMax *= MAXFUDGECD;
2990 
2991  // Combinations of t sampling parameters.
2992  fWid1 = FWID1;
2993  fWid2 = FWID2;
2994  fWid3 = FWID3;
2995  fbWid1 = fWid1 * BWID1;
2996  fbWid2 = fWid2 * BWID2;
2997  fbWid3 = fWid3 * BWID3;
2998  fbWid123 = fbWid1 + fbWid2 + fbWid3;
2999 
3000  // Done.
3001  return true;
3002 
3003 }
3004 
3005 //--------------------------------------------------------------------------
3006 
3007 // Select a trial kinematics phase space point. Perform full
3008 // Monte Carlo acceptance/rejection at this stage.
3009 
3010 bool PhaseSpace2to3diffractive::trialKin( bool, bool ) {
3011 
3012  // Allow for possibility that energy varies from event to event.
3013  if (doEnergySpread) {
3014  eCM = infoPtr->eCM();
3015  s = eCM * eCM;
3016  }
3017 
3018  // Trivial kinematics of incoming hadrons.
3019  pAbs = 0.5 * sqrtpos( pow2( s - s1 - s2) - 4. * s1 * s2 ) / eCM;
3020  p1.p( 0., 0., pAbs, 0.5 * (s + s1 - s2) / eCM);
3021  p2.p( 0., 0., -pAbs, 0.5 * (s + s2 - s1) / eCM);
3022 
3023  // Temporary variables during generation.
3024  double pickb, bNow, tNow, sx1, sx2, sx3, sx4, t1, t2, tWeight1, tWeight2,
3025  lambda12, lambda34, tempA, tempB, tempC, cosTheta, sinTheta, pz, pT,
3026  deltaE, p2Esum, facP;
3027  xi1 = xi2 = t1 = t2 = 0.;
3028 
3029  // Normally xi and t in one step, but possible to split into two.
3030  int nStep = (splitxit) ? 2 : 1;
3031  for (int iStep = 0; iStep < nStep; ++iStep) {
3032  int step = (splitxit) ? iStep + 1 : 0;
3033 
3034  // Loop over attempts to set up xi1, xi2, t1, t2 consistently.
3035  for (int loop = 0; ; ++loop) {
3036  if (loop == NTRY) {
3037  infoPtr->errorMsg("Error in PhaseSpace2to3diffractive::trialKin: "
3038  " quit after repeated tries");
3039  return false;
3040  }
3041 
3042  // Select mass^2 = xi1 * xi2 * s according to dxi_1/xi_1 * dxi_2/xi_2.
3043  if (iStep == 0) {
3044  do {
3045  xi1 = pow( s5min / s, rndmPtr->flat());
3046  xi2 = pow( s5min / s, rndmPtr->flat());
3047  s5 = xi1 * xi2 * s;
3048  m5 = sqrt(s5);
3049  } while (m5 < m5min || mA + mB + m5 + DIFFMASSMARGIN > eCM);
3050  }
3051 
3052  // Select t1, t2 according to exp(b*t), b picked among three options.
3053  if (step != 1) {
3054  bool tryAgain = false;
3055  for (int i = 0; i < 2; ++i) {
3056  pickb = rndmPtr->flat() * (fWid1 + fWid2 + fWid3);
3057  bNow = (pickb < fWid1) ? BWID1
3058  : ( (pickb < fWid1 + fWid2) ? BWID2 : BWID3 );
3059  tNow = log(rndmPtr->flat()) / bNow;
3060 
3061  // Check whether xi and t choices are consistent on each side.
3062  sx1 = (i == 0) ? s1 : s2;
3063  sx2 = (i == 0) ? s2 : s1;
3064  sx3 = sx1;
3065  sx4 = (i == 0) ? s2 + xi1 * s : s1 + xi2 * s;
3066  if (sqrt(sx3) + sqrt(sx4) + DIFFMASSMARGIN > eCM) tryAgain = true;
3067  if (!tInRange(tNow, s, sx1, sx2, sx3, sx4)) tryAgain = true;
3068  if (tryAgain) break;
3069  if (i == 0) t1 = tNow;
3070  else t2 = tNow;
3071  }
3072  if (tryAgain) continue;
3073  }
3074 
3075  // Evaluate central diffractive cross section.
3076  sigNow = sigmaTotPtr->dsigmaCD( xi1, xi2, t1, t2, step);
3077 
3078  // Maximum weight based on sampling strategy.
3079  tWeight1 = ( fbWid1 * exp( BWID1 * t1) + fbWid2 * exp(BWID2 * t1)
3080  + fbWid3 * exp(BWID3 * t1) ) / fbWid123;
3081  tWeight2 = ( fbWid1 * exp( BWID1 * t2) + fbWid2 * exp(BWID2 * t2)
3082  + fbWid3 * exp(BWID3 * t2) ) / fbWid123;
3083  sigMaxNow = (step == 0) ? sigMax * tWeight1 * tWeight2
3084  : ( (step == 1) ? sigMax : MAXFUDGET * tWeight1 * tWeight2 );
3085 
3086  // Check for maximum violations. Possibly break out of the loop.
3087  if (sigNow > sigMaxNow) infoPtr->errorMsg("Error in PhaseSpace2to3"
3088  "diffractive::trialKin: maximum cross section violated");
3089  if (sigNow > rndmPtr->flat() * sigMaxNow) break;
3090 
3091  // End of loops over tries and steps.
3092  }
3093  }
3094 
3095  // Careful reconstruction of scattering angles.
3096  for (int i = 0; i < 2; ++i) {
3097  tNow = (i == 0) ? t1 : t2;
3098  sx1 = (i == 0) ? s1 : s2;
3099  sx2 = (i == 0) ? s2 : s1;
3100  sx3 = sx1;
3101  sx4 = (i == 0) ? s2 + xi1 * s : s1 + xi2 * s;
3102  lambda12 = sqrtpos( pow2( s - sx1 - sx2) - 4. * sx1 * sx2 );
3103  lambda34 = sqrtpos( pow2( s - sx3 - sx4) - 4. * sx3 * sx4 );
3104  tempA = s - (sx1 + sx2 + sx3 + sx4) + (sx1 - sx2) * (sx3 - sx4) / s;
3105  tempB = lambda12 * lambda34 / s;
3106  tempC = (sx3 - sx1) * (sx4 - sx2) + (sx1 + sx4 - sx2 - sx3)
3107  * (sx1 * sx4 - sx2 * sx3) / s;
3108  cosTheta = min(1., max(-1., (tempA + 2. * tNow) / tempB));
3109  sinTheta = 2. * sqrtpos( -(tempC + tempA * tNow + tNow * tNow) ) / tempB;
3110  theta = asin( min(1., sinTheta));
3111  if (cosTheta < 0.) theta = M_PI - theta;
3112 
3113  // Pick random phi angles. Save outgoing four-vectors.
3114  pAbs = 0.5 * lambda34 / eCM;
3115  pz = (i == 0) ? pAbs * cos(theta) : -pAbs * cos(theta);
3116  pT = pAbs * sin(theta);
3117  phi = 2. * M_PI * rndmPtr->flat();
3118  Vec4& pNow = (i == 0) ? p3 : p4;
3119  pNow.p( pT * cos(phi), pT * sin(phi), pz, sqrt(pAbs * pAbs + sx1) );
3120  }
3121 
3122  // Force wanted diffractive mass and rescale three-momenta to fix energies.
3123  p5 = (p1 - p3) + (p2 - p4);
3124  p5.e( sqrt(s5 + p5.pAbs2()) );
3125  for (int iter = 0; iter < 5; ++iter) {
3126  deltaE = eCM - p3.e() - p4.e() - p5.e();
3127  if (abs(deltaE) < 1e-10 * eCM) break;
3128  p2Esum = p3.pAbs2() / p3.e() + p4.pAbs2() / p4.e() + p5.pAbs2() / p5.e();
3129  facP = 1. + deltaE / p2Esum;
3130  p3.rescale3(facP);
3131  p4.rescale3(facP);
3132  p5.rescale3(facP);
3133  p3.e( sqrt(s1 + p3.pAbs2()) );
3134  p4.e( sqrt(s2 + p4.pAbs2()) );
3135  p5.e( sqrt(s5 + p5.pAbs2()) );
3136  }
3137 
3138  return true;
3139 }
3140 
3141 //--------------------------------------------------------------------------
3142 
3143 // Construct the four-vector kinematics from the trial values.
3144 
3145 bool PhaseSpace2to3diffractive::finalKin() {
3146 
3147  // Particle four-momenta and masses.
3148  pH[1] = p1;
3149  pH[2] = p2;
3150  pH[3] = p3;
3151  pH[4] = p4;
3152  pH[5] = p5;
3153  mH[1] = mA;
3154  mH[2] = mB;
3155  mH[3] = mA;
3156  mH[4] = mB;
3157  mH[5] = m5;
3158 
3159  // Set some further info for completeness (but Info can be for subprocess).
3160  x1H = 1.;
3161  x2H = 1.;
3162  sH = s;
3163  tH = (p1 - p3).m2Calc();
3164  uH = (p2 - p4).m2Calc();
3165  mHat = eCM;
3166  p2Abs = pAbs * pAbs;
3167  betaZ = 0.;
3168  // Store average pT of three final particles for documentation.
3169  pTH = (p3.pT() + p4.pT() + p5.pT()) / 3.;
3170 
3171  // Done.
3172  return true;
3173 
3174 }
3175 
3176 //==========================================================================
3177 
3178 // PhaseSpace2to2nondiffractiveGamma class.
3179 // 2 -> 2 kinematics for non-diffractive events in gamma+gamma.
3180 
3181 //--------------------------------------------------------------------------
3182 
3183 // Samples the x_gamma and estimates the cross section from convolution
3184 // integral between EPA and sigmaND.
3185 
3186 bool PhaseSpace2to2nondiffractiveGamma::setupSampling() {
3187 
3188  // Read in relevant cuts.
3189  Q2maxGamma = settingsPtr->parm("Photon:Q2max");
3190  Wmin = settingsPtr->parm("Photon:Wmin");
3191  bool hasGamma = settingsPtr->flag("PDF:lepton2gamma");
3192  externalFlux = settingsPtr->mode("PDF:lepton2gammaSet") == 2;
3193  sampleQ2 = settingsPtr->flag("Photon:sampleQ2");
3194 
3195  // Save relevant parameters and calculate sigmaND.
3196  alphaEM = couplingsPtr->alphaEM(Q2maxGamma);
3197  sCM = s;
3198  gammaA = beamAPtr->isGamma() || (beamAPtr->isLepton() && hasGamma);
3199  gammaB = beamBPtr->isGamma() || (beamBPtr->isLepton() && hasGamma);
3200  idAin = gammaA ? 22 : beamAPtr->id();
3201  idBin = gammaB ? 22 : beamBPtr->id();
3202  sigmaTotPtr->calc( idAin, idBin, eCM);
3203  sigmaNDmax = sigmaTotPtr->sigmaND();
3204 
3205  // Get the masses of beam particles and derive useful ratios.
3206  m2BeamA = pow2( mA );
3207  m2BeamB = pow2( mB );
3208  m2sA = 4. * m2BeamA / sCM;
3209  m2sB = 4. * m2BeamB / sCM;
3210 
3211  // Calculate the square of the minimum invariant mass for sampling.
3212  double m2GmGmMin = pow2(Wmin);
3213  double xGamAMax = 1.;
3214  double xGamBMax = 1.;
3215  double xGamAMin = m2GmGmMin / sCM ;
3216  double xGamBMin = m2GmGmMin / sCM ;
3217 
3218  xGamma1 = 1.;
3219  xGamma2 = 1.;
3220  log2xMinA = 0.;
3221  log2xMaxA = 0.;
3222 
3223  // Calculate limit for x1 (if applicable) and derive useful logs.
3224  if (gammaA) {
3225  xGamAMax = Q2maxGamma / (2. * m2BeamA)
3226  * (sqrt( (1. + 4. * m2BeamA / Q2maxGamma) * (1. - m2sA) ) - 1.);
3227  if ( !externalFlux) {
3228  log2xMinA = pow2( log( Q2maxGamma/ ( m2BeamA * pow2(xGamAMin) ) ) );
3229  log2xMaxA = pow2( log( Q2maxGamma/ ( m2BeamA * pow2(xGamAMax) ) ) );
3230  }
3231  }
3232 
3233  // Calculate limit for x2 (if applicable) and derive useful logs.
3234  if (gammaB) {
3235  xGamBMax = Q2maxGamma / (2. * m2BeamB)
3236  * (sqrt( (1. + 4. * m2BeamB / Q2maxGamma) * (1. - m2sB) ) - 1.);
3237  if ( !externalFlux) {
3238  log2xMinB = pow2( log( Q2maxGamma/ ( m2BeamB * pow2(xGamBMin) ) ) );
3239  log2xMaxB = pow2( log( Q2maxGamma/ ( m2BeamB * pow2(xGamBMax) ) ) );
3240  }
3241  }
3242 
3243  // Derive the overestimate for sigmaND integral with l+l-/p -> gm+gm/p.
3244  if ( !externalFlux) {
3245  if ( gammaA && gammaB) {
3246  sigmaNDestimate = pow2( 0.5 * alphaEM / M_PI ) * 0.25
3247  * (log2xMinA - log2xMaxA) * (log2xMinB - log2xMaxB) * sigmaNDmax;
3248  } else if (gammaA) {
3249  sigmaNDestimate = 0.5 * alphaEM / M_PI
3250  * 0.5 * (log2xMinA - log2xMaxA) * sigmaNDmax;
3251  } else if (gammaB) {
3252  sigmaNDestimate = 0.5 * alphaEM / M_PI
3253  * 0.5 * (log2xMinB - log2xMaxB) * sigmaNDmax;
3254  }
3255 
3256  // Slightly different overestimate for externally provided fluxes.
3257  } else {
3258 
3259  // Get the minimum virtualities and rescalings of the approximated fluxes.
3260  double Q2minA = beamAPtr->Q2minPDF();
3261  double Q2minB = beamBPtr->Q2minPDF();
3262  double rescaleA = beamAPtr->gammaFluxNorm();
3263  double rescaleB = beamBPtr->gammaFluxNorm();
3264 
3265  // Calculate the overestimate for sigmaND.
3266  if ( gammaA && gammaB) {
3267  sigmaNDestimate = pow2( alphaEM / M_PI ) * sigmaNDmax
3268  * rescaleA * log(xGamAMax / xGamAMin) * log(Q2maxGamma / Q2minA)
3269  * rescaleB * log(xGamBMax / xGamBMin) * log(Q2maxGamma / Q2minB);
3270  } else if (gammaA) {
3271  sigmaNDestimate = alphaEM / M_PI * sigmaNDmax
3272  * rescaleA * log(xGamAMax / xGamAMin) * log(Q2maxGamma / Q2minA);
3273  } else if (gammaB) {
3274  sigmaNDestimate = alphaEM / M_PI * sigmaNDmax
3275  * rescaleB * log(xGamBMax / xGamBMin) * log(Q2maxGamma / Q2minB);
3276  }
3277  }
3278 
3279  // Save the cross-section estimate.
3280  sigmaNw = sigmaNDestimate;
3281  sigmaMx = sigmaNDestimate;
3282 
3283  // Done.
3284  return true;
3285 }
3286 
3287 //--------------------------------------------------------------------------
3288 
3289 // Sample the kinematics for the gm+gm sub-collision.
3290 // The virtuality and kT sampled by GammaKinematics.
3291 
3292 bool PhaseSpace2to2nondiffractiveGamma::trialKin(bool , bool) {
3293 
3294  // Current weight.
3295  double wt = 1.0;
3296 
3297  // Sample x_gamma's when using internal photon flux.
3298  if ( !externalFlux) {
3299  if (gammaA) xGamma1 = sqrt( (Q2maxGamma / m2BeamA) * exp( -sqrt( log2xMinA
3300  + rndmPtr->flat() * (log2xMaxA - log2xMinA) ) ) );
3301  if (gammaB) xGamma2 = sqrt( (Q2maxGamma / m2BeamB) * exp( -sqrt( log2xMinB
3302  + rndmPtr->flat() * (log2xMaxB - log2xMinB) ) ) );
3303 
3304  // Save the x_gamma values to beam particles for further use.
3305  beamAPtr->xGamma(xGamma1);
3306  beamBPtr->xGamma(xGamma2);
3307  }
3308 
3309  // Sample the kT of photons, special behaviour for non-diffractive events.
3310  if ( !(gammaKinPtr->sampleKTgamma(true) ) ) return false;
3311 
3312  // Save the sampled x_gamma values with external flux.
3313  if (externalFlux) {
3314  xGamma1 = beamAPtr->xGamma();
3315  xGamma2 = beamBPtr->xGamma();
3316  }
3317 
3318  // Obtain the sampled values.
3319  Q2gamma1 = gammaKinPtr->getQ2gamma1();
3320  Q2gamma2 = gammaKinPtr->getQ2gamma2();
3321  Q2min1 = gammaKinPtr->getQ2min1();
3322  Q2min2 = gammaKinPtr->getQ2min2();
3323  mGmGm = gammaKinPtr->eCMsub();
3324 
3325  // Correct for x1 and x2 oversampling.
3326  double wt1 = 1.;
3327  double wt2 = 1.;
3328 
3329  // Calculate the weight for beam A from oversampling.
3330  if ( gammaA) {
3331  if ( !externalFlux) {
3332  wt1 = ( 0.5 * ( 1. + pow2(1 - xGamma1) ) ) * log( Q2maxGamma/Q2min1 )
3333  / log( Q2maxGamma / ( m2BeamA * pow2( xGamma1 ) ) );
3334 
3335  // For external flux weight depends whether Q2 is sampled.
3336  } else {
3337  wt1 = sampleQ2 ? beamAPtr->xfFlux(22, xGamma1, Q2gamma1)
3338  / beamAPtr->xfApprox(22, xGamma1, Q2gamma1) :
3339  beamAPtr->xfFlux(22, xGamma1, Q2gamma1)
3340  / beamAPtr->xf(22, xGamma1, Q2gamma1);
3341  }
3342  }
3343 
3344  // Calculate the weight for beam B from oversampling.
3345  if ( gammaB) {
3346  if ( !externalFlux) {
3347  wt2 = ( 0.5 * ( 1. + pow2(1 - xGamma2) ) ) * log( Q2maxGamma/Q2min2 )
3348  / log( Q2maxGamma / ( m2BeamB * pow2( xGamma2 ) ) );
3349 
3350  // For external flux weight depends whether Q2 is sampled.
3351  } else {
3352  wt2 = sampleQ2 ? beamBPtr->xfFlux(22, xGamma2, Q2gamma2)
3353  / beamBPtr->xfApprox(22, xGamma2, Q2gamma2) :
3354  beamBPtr->xfFlux(22, xGamma2, Q2gamma2)
3355  / beamBPtr->xf(22, xGamma2, Q2gamma2);
3356  }
3357  }
3358 
3359  // Correct for the estimated sigmaND.
3360  sigmaTotPtr->calc( idAin, idBin, mGmGm );
3361  double sigmaNDnow = sigmaTotPtr->sigmaND();
3362  double wtSigma = sigmaNDnow/sigmaNDmax;
3363 
3364  // Correct for alpha_EM with the sampled Q2 values.
3365  double wtAlphaEM1 = gammaA ? couplingsPtr->alphaEM(Q2gamma1) / alphaEM : 1.;
3366  double wtAlphaEM2 = gammaB ? couplingsPtr->alphaEM(Q2gamma2) / alphaEM : 1.;
3367  double wtAlphaEM = wtAlphaEM1 * wtAlphaEM2;
3368 
3369  // Calculate the total weight and warn if unphysical weight.
3370  wt *= wt1 * wt2 * wtSigma * wtAlphaEM;
3371  if ( wt > 1. ) {
3372  infoPtr->errorMsg("Warning in PhaseSpace2to2nondiffractiveGamma::trialKin:"
3373  " weight above unity");
3374  }
3375 
3376  // Correct for over-estimated cross section and x_gamma limits.
3377  if ( wt < rndmPtr->flat() ) return false;
3378 
3379  // Done.
3380  return true;
3381 
3382 }
3383 
3384 //==========================================================================
3385 
3386 // PhaseSpace2to3tauycyl class.
3387 // 2 -> 3 kinematics for normal subprocesses.
3388 
3389 //--------------------------------------------------------------------------
3390 
3391 // Constants: could be changed here if desired, but normally should not.
3392 // These are of technical nature, as described for each.
3393 
3394 // Number of Newton-Raphson iterations of kinematics when masses introduced.
3395 const int PhaseSpace2to3tauycyl::NITERNR = 5;
3396 
3397 //--------------------------------------------------------------------------
3398 
3399 // Set up for fixed or Breit-Wigner mass selection.
3400 
3401 bool PhaseSpace2to3tauycyl::setupMasses() {
3402 
3403  // Treat Z0 as such or as gamma*/Z0
3404  gmZmode = gmZmodeGlobal;
3405  int gmZmodeProc = sigmaProcessPtr->gmZmode();
3406  if (gmZmodeProc >= 0) gmZmode = gmZmodeProc;
3407 
3408  // Set sHat limits - based on global limits only.
3409  mHatMin = mHatGlobalMin;
3410  sHatMin = mHatMin*mHatMin;
3411  mHatMax = eCM;
3412  if (mHatGlobalMax > mHatGlobalMin) mHatMax = min( eCM, mHatGlobalMax);
3413  sHatMax = mHatMax*mHatMax;
3414 
3415  // Masses and widths of resonances.
3416  setupMass1(3);
3417  setupMass1(4);
3418  setupMass1(5);
3419 
3420  // Reduced mass range - do not make it as fancy as in two-body case.
3421  if (useBW[3]) mUpper[3] -= (mPeak[4] + mPeak[5]);
3422  if (useBW[4]) mUpper[4] -= (mPeak[3] + mPeak[5]);
3423  if (useBW[5]) mUpper[5] -= (mPeak[3] + mPeak[4]);
3424 
3425  // If closed phase space then unallowed process.
3426  bool physical = true;
3427  if (useBW[3] && mUpper[3] < mLower[3] + MASSMARGIN) physical = false;
3428  if (useBW[4] && mUpper[4] < mLower[4] + MASSMARGIN) physical = false;
3429  if (useBW[5] && mUpper[5] < mLower[5] + MASSMARGIN) physical = false;
3430  if (!useBW[3] && !useBW[4] && !useBW[5] && mHatMax < mPeak[3]
3431  + mPeak[4] + mPeak[5] + MASSMARGIN) physical = false;
3432  if (!physical) return false;
3433 
3434  // No extra pT precautions in massless limit - assumed fixed by ME's.
3435  pTHatMin = pTHatGlobalMin;
3436  pT2HatMin = pTHatMin * pTHatMin;
3437  pTHatMax = pTHatGlobalMax;
3438  pT2HatMax = pTHatMax * pTHatMax;
3439 
3440  // Prepare to select m3 by BW + flat + 1/s_3.
3441  if (useBW[3]) {
3442  double distToThreshA = (mHatMax - mPeak[3] - mPeak[4] - mPeak[5])
3443  * mWidth[3] / (pow2(mWidth[3]) + pow2(mWidth[4]) + pow2(mWidth[5]));
3444  double distToThreshB = (mHatMax - mPeak[3] - mMin[4] - mMin[5])
3445  / mWidth[3];
3446  double distToThresh = min( distToThreshA, distToThreshB);
3447  setupMass2(3, distToThresh);
3448  }
3449 
3450  // Prepare to select m4 by BW + flat + 1/s_3.
3451  if (useBW[4]) {
3452  double distToThreshA = (mHatMax - mPeak[3] - mPeak[4] - mPeak[5])
3453  * mWidth[4] / (pow2(mWidth[3]) + pow2(mWidth[4]) + pow2(mWidth[5]));
3454  double distToThreshB = (mHatMax - mPeak[4] - mMin[3] - mMin[5])
3455  / mWidth[4];
3456  double distToThresh = min( distToThreshA, distToThreshB);
3457  setupMass2(4, distToThresh);
3458  }
3459 
3460  // Prepare to select m5 by BW + flat + 1/s_3.
3461  if (useBW[5]) {
3462  double distToThreshA = (mHatMax - mPeak[3] - mPeak[4] - mPeak[5])
3463  * mWidth[5] / (pow2(mWidth[3]) + pow2(mWidth[4]) + pow2(mWidth[5]));
3464  double distToThreshB = (mHatMax - mPeak[5] - mMin[3] - mMin[4])
3465  / mWidth[5];
3466  double distToThresh = min( distToThreshA, distToThreshB);
3467  setupMass2(5, distToThresh);
3468  }
3469 
3470  // Initialization masses. For now give up when constrained phase space.
3471  m3 = (useBW[3]) ? min(mPeak[3], mUpper[3]) : mPeak[3];
3472  m4 = (useBW[4]) ? min(mPeak[4], mUpper[4]) : mPeak[4];
3473  m5 = (useBW[5]) ? min(mPeak[5], mUpper[5]) : mPeak[5];
3474  if (m3 + m4 + m5 + MASSMARGIN > mHatMax) physical = false;
3475  s3 = m3*m3;
3476  s4 = m4*m4;
3477  s5 = m5*m5;
3478 
3479  // Correct selected mass-spectrum to running-width Breit-Wigner.
3480  // Extra safety margin for maximum search.
3481  wtBW = 1.;
3482  if (useBW[3]) wtBW *= weightMass(3) * EXTRABWWTMAX;
3483  if (useBW[4]) wtBW *= weightMass(4) * EXTRABWWTMAX;
3484  if (useBW[5]) wtBW *= weightMass(5) * EXTRABWWTMAX;
3485 
3486  // Done.
3487  return physical;
3488 
3489 }
3490 
3491 //--------------------------------------------------------------------------
3492 
3493 // Select Breit-Wigner-distributed or fixed masses.
3494 
3495 bool PhaseSpace2to3tauycyl::trialMasses() {
3496 
3497  // By default vanishing cross section.
3498  sigmaNw = 0.;
3499  wtBW = 1.;
3500 
3501  // Pick m3, m4 and m5 independently.
3502  trialMass(3);
3503  trialMass(4);
3504  trialMass(5);
3505 
3506  // If outside phase space then reject event.
3507  if (m3 + m4 + m5 + MASSMARGIN > mHatMax) return false;
3508 
3509  // Correct selected mass-spectrum to running-width Breit-Wigner.
3510  if (useBW[3]) wtBW *= weightMass(3);
3511  if (useBW[4]) wtBW *= weightMass(4);
3512  if (useBW[5]) wtBW *= weightMass(5);
3513 
3514  // Done.
3515  return true;
3516 
3517 }
3518 
3519 //--------------------------------------------------------------------------
3520 
3521 // Construct the four-vector kinematics from the trial values.
3522 
3523 bool PhaseSpace2to3tauycyl::finalKin() {
3524 
3525  // Assign masses to particles assumed massless in matrix elements.
3526  int id3 = sigmaProcessPtr->id(3);
3527  int id4 = sigmaProcessPtr->id(4);
3528  int id5 = sigmaProcessPtr->id(5);
3529  if (idMass[3] == 0) { m3 = particleDataPtr->m0(id3); s3 = m3*m3; }
3530  if (idMass[4] == 0) { m4 = particleDataPtr->m0(id4); s4 = m4*m4; }
3531  if (idMass[5] == 0) { m5 = particleDataPtr->m0(id5); s5 = m5*m5; }
3532 
3533  // Check that phase space still open after new mass assignment.
3534  if (m3 + m4 + m5 + MASSMARGIN > mHat) {
3535  infoPtr->errorMsg("Warning in PhaseSpace2to3tauycyl::finalKin: "
3536  "failed after mass assignment");
3537  return false;
3538  }
3539 
3540  // Particle masses; incoming always on mass shell.
3541  mH[1] = 0.;
3542  mH[2] = 0.;
3543  mH[3] = m3;
3544  mH[4] = m4;
3545  mH[5] = m5;
3546 
3547  // Incoming partons along beam axes.
3548  pH[1] = Vec4( 0., 0., 0.5 * eCM * x1H, 0.5 * eCM * x1H);
3549  pH[2] = Vec4( 0., 0., -0.5 * eCM * x2H, 0.5 * eCM * x2H);
3550 
3551  // Begin three-momentum rescaling to compensate for masses.
3552  if (idMass[3] == 0 || idMass[4] == 0 || idMass[5] == 0) {
3553  double p3S = p3cm.pAbs2();
3554  double p4S = p4cm.pAbs2();
3555  double p5S = p5cm.pAbs2();
3556  double fac = 1.;
3557  double e3, e4, e5, value, deriv;
3558 
3559  // Iterate rescaling solution five times, using Newton-Raphson.
3560  for (int i = 0; i < NITERNR; ++i) {
3561  e3 = sqrt(s3 + fac * p3S);
3562  e4 = sqrt(s4 + fac * p4S);
3563  e5 = sqrt(s5 + fac * p5S);
3564  value = e3 + e4 + e5 - mHat;
3565  deriv = 0.5 * (p3S / e3 + p4S / e4 + p5S / e5);
3566  fac -= value / deriv;
3567  }
3568 
3569  // Rescale momenta appropriately.
3570  double facRoot = sqrt(fac);
3571  p3cm.rescale3( facRoot );
3572  p4cm.rescale3( facRoot );
3573  p5cm.rescale3( facRoot );
3574  p3cm.e( sqrt(s3 + fac * p3S) );
3575  p4cm.e( sqrt(s4 + fac * p4S) );
3576  p5cm.e( sqrt(s5 + fac * p5S) );
3577  }
3578 
3579  // Outgoing partons initially in collision CM frame along beam axes.
3580  pH[3] = p3cm;
3581  pH[4] = p4cm;
3582  pH[5] = p5cm;
3583 
3584  // Then boost them to overall CM frame
3585  betaZ = (x1H - x2H)/(x1H + x2H);
3586  pH[3].rot( theta, phi);
3587  pH[4].rot( theta, phi);
3588  pH[3].bst( 0., 0., betaZ);
3589  pH[4].bst( 0., 0., betaZ);
3590  pH[5].bst( 0., 0., betaZ);
3591 
3592  // Store average pT of three final particles for documentation.
3593  pTH = (p3cm.pT() + p4cm.pT() + p5cm.pT()) / 3.;
3594 
3595  // Done.
3596  return true;
3597 }
3598 
3599 //==========================================================================
3600 
3601 // The PhaseSpace2to3yyycyl class.
3602 // Phase space for 2 -> 3 QCD processes, 1 + 2 -> 3 + 4 + 5 set up in
3603 // y3, y4, y5, pT2_3, pT2_5, phi_3 and phi_5, and with R separation cut.
3604 
3605 //--------------------------------------------------------------------------
3606 
3607 // Sample the phase space of the process.
3608 
3609 bool PhaseSpace2to3yyycyl::setupSampling() {
3610 
3611  // Phase space cuts specifically for 2 -> 3 QCD processes.
3612  pTHat3Min = settingsPtr->parm("PhaseSpace:pTHat3Min");
3613  pTHat3Max = settingsPtr->parm("PhaseSpace:pTHat3Max");
3614  pTHat5Min = settingsPtr->parm("PhaseSpace:pTHat5Min");
3615  pTHat5Max = settingsPtr->parm("PhaseSpace:pTHat5Max");
3616  RsepMin = settingsPtr->parm("PhaseSpace:RsepMin");
3617  R2sepMin = pow2(RsepMin);
3618 
3619  // If both beams are baryons then softer PDF's than for mesons/Pomerons.
3620  hasBaryonBeams = ( beamAPtr->isBaryon() && beamBPtr->isBaryon() );
3621 
3622  // Work with massless partons.
3623  for (int i = 0; i < 6; ++i) mH[i] = 0.;
3624 
3625  // Constrain to possible cuts at current CM energy and check consistency.
3626  pT3Min = pTHat3Min;
3627  pT3Max = pTHat3Max;
3628  if (pT3Max < pT3Min) pT3Max = 0.5 * eCM;
3629  pT5Min = pTHat5Min;
3630  pT5Max = pTHat5Max;
3631  if (pT5Max < pT5Min) pT5Max = 0.5 * eCM;
3632  if (pT5Max > pT3Max || pT5Min > pT3Min || pT3Min + 2. * pT5Min > eCM) {
3633  infoPtr->errorMsg("Error in PhaseSpace2to3yyycyl::setupSampling: "
3634  "inconsistent pT limits in 3-body phase space");
3635  return false;
3636  }
3637 
3638  // Loop over some configurations where cross section could be maximal.
3639  // In all cases all sum p_z = 0, for maximal PDF weights.
3640  // Also pT3 and R45 are minimal, while pT5 may vary.
3641  sigmaMx = 0.;
3642  double pT5EffMax = min( pT5Max, 0.5 * pT3Min / cos(0.5 * RsepMin) );
3643  double pT3EffMin = max( pT3Min, 2.0 * pT5Min * cos(0.5 * RsepMin) ) ;
3644  double sinhR = sinh(0.5 * RsepMin);
3645  double coshR = cosh(0.5 * RsepMin);
3646  for (int iStep = 0; iStep < 120; ++iStep) {
3647 
3648  // First kind: |phi4 - phi5| = R, all p_z = 0, i.e. separation in phi.
3649  if (iStep < 10) {
3650  pT3 = pT3EffMin;
3651  pT5 = pT5Min * pow( pT5EffMax / pT5Min, iStep / 9.);
3652  double pTRat = pT5 / pT3;
3653  double sin2Rsep = pow2( sin(RsepMin) );
3654  double cosPhi35 = - cos(RsepMin) * sqrtpos(1. - sin2Rsep
3655  * pow2(pTRat)) - sin2Rsep * pTRat;
3656  cosPhi35 = max( cosPhi35, cos(M_PI - 0.5 * RsepMin) );
3657  double sinPhi35 = sqrt(1. - pow2(cosPhi35));
3658  pT4 = sqrt( pow2(pT3) + pow2(pT5) + 2. * pT3 * pT5 * cosPhi35);
3659  p3cm = pT3 * Vec4( 1., 0., 0., 1.);
3660  p4cm = Vec4(-pT3 - pT5 * cosPhi35, -pT5 * sinPhi35, 0., pT4);
3661  p5cm = pT5 * Vec4( cosPhi35, sinPhi35, 0., 1.);
3662 
3663  // Second kind: |y4 - y5| = R, phi4 = phi5, i.e. separation in y.
3664  } else {
3665  pT5 = pT5Min * pow( pT5Max / pT5Min, iStep%10 / 9. );
3666  pT3 = max( pT3Min, 2. * pT5);
3667  pT4 = pT3 - pT5;
3668  p4cm = pT4 * Vec4( -1., 0., sinhR, coshR );
3669  p5cm = pT5 * Vec4( -1., 0., -sinhR, coshR );
3670  y3 = -1.2 + 0.2 * (iStep/10);
3671  p3cm = pT3 * Vec4( 1., 0., sinh(y3), cosh(y3));
3672  betaZ = (p3cm.pz() + p4cm.pz() + p5cm.pz())
3673  / (p3cm.e() + p4cm.e() + p5cm.e());
3674  p3cm.bst( 0., 0., -betaZ);
3675  p4cm.bst( 0., 0., -betaZ);
3676  p5cm.bst( 0., 0., -betaZ);
3677  }
3678 
3679  // Find cross section in chosen phase space point.
3680  pInSum = p3cm + p4cm + p5cm;
3681  x1H = pInSum.e() / eCM;
3682  x2H = x1H;
3683  sH = pInSum.m2Calc();
3684  sigmaProcessPtr->set3Kin( x1H, x2H, sH, p3cm, p4cm, p5cm,
3685  0., 0., 0., 1., 1., 1.);
3686  sigmaNw = sigmaProcessPtr->sigmaPDF();
3687 
3688  // Multiply by Jacobian.
3689  double flux = 1. /(8. * pow2(sH) * pow5(2. * M_PI));
3690  double pTRng = pow2(M_PI)
3691  * pow4(pT3) * (1./pow2(pT3Min) - 1./pow2(pT3Max))
3692  * pow2(pT5) * 2.* log(pT5Max/pT5Min);
3693  double yRng = 8. * log(eCM / pT3) * log(eCM / pT4) * log(eCM / pT5);
3694  sigmaNw *= SAFETYMARGIN * flux * pTRng * yRng;
3695 
3696  // Update to largest maximum.
3697  if (showSearch && sigmaNw > sigmaMx) cout << "\n New sigmamax is "
3698  << scientific << setprecision(3) << sigmaNw << " for x1 = " << x1H
3699  << " x2 = " << x2H << " sH = " << sH << endl << " p3 = " << p3cm
3700  << " p4 = " << p4cm << " p5 = " << p5cm;
3701  if (sigmaNw > sigmaMx) sigmaMx = sigmaNw;
3702  }
3703  sigmaPos = sigmaMx;
3704 
3705  // Done.
3706  return true;
3707 }
3708 
3709 //--------------------------------------------------------------------------
3710 
3711 // Sample the phase space of the process.
3712 
3713 bool PhaseSpace2to3yyycyl::trialKin(bool inEvent, bool) {
3714 
3715  // Allow for possibility that energy varies from event to event.
3716  if (doEnergySpread) {
3717  eCM = infoPtr->eCM();
3718  s = eCM * eCM;
3719  }
3720  sigmaNw = 0.;
3721 
3722  // Constrain to possible cuts at current CM energy and check consistency.
3723  pT3Min = pTHat3Min;
3724  pT3Max = pTHat3Max;
3725  if (pT3Max < pT3Min) pT3Max = 0.5 * eCM;
3726  pT5Min = pTHat5Min;
3727  pT5Max = pTHat5Max;
3728  if (pT5Max < pT5Min) pT5Max = 0.5 * eCM;
3729  if (pT5Max > pT3Max || pT5Min > pT3Min || pT3Min + 2. * pT5Min > eCM) {
3730  infoPtr->errorMsg("Error in PhaseSpace2to3yyycyl::trialKin: "
3731  "inconsistent pT limits in 3-body phase space");
3732  return false;
3733  }
3734 
3735  // Pick pT3 according to d^2(pT3)/pT3^4 and pT5 to d^2(pT5)/pT5^2.
3736  pT3 = pT3Min * pT3Max / sqrt( pow2(pT3Min) +
3737  rndmPtr->flat() * (pow2(pT3Max) - pow2(pT3Min)) );
3738  pT5Max = min(pT5Max, pT3);
3739  if (pT5Max < pT5Min) return false;
3740  pT5 = pT5Min * pow( pT5Max / pT5Min, rndmPtr->flat() );
3741 
3742  // Pick azimuthal angles flat and reconstruct pT4, between pT3 and pT5.
3743  phi3 = 2. * M_PI * rndmPtr->flat();
3744  phi5 = 2. * M_PI * rndmPtr->flat();
3745  pT4 = sqrt( pow2(pT3) + pow2(pT5) + 2. * pT3 * pT5 * cos(phi3 - phi5) );
3746  if (pT4 > pT3 || pT4 < pT5) return false;
3747  phi4 = atan2( -(pT3 * sin(phi3) + pT5 * sin(phi5)),
3748  -(pT3 * cos(phi3) + pT5 * cos(phi5)) );
3749 
3750  // Pick rapidities flat in allowed ranges.
3751  y3Max = log(eCM / pT3);
3752  y4Max = log(eCM / pT4);
3753  y5Max = log(eCM / pT5);
3754  y3 = y3Max * (2. * rndmPtr->flat() - 1.);
3755  y4 = y4Max * (2. * rndmPtr->flat() - 1.);
3756  y5 = y5Max * (2. * rndmPtr->flat() - 1.);
3757 
3758  // Reject some events at large rapidities to improve efficiency.
3759  // (Works for baryons, not pions or Pomerons if they have hard PDF's.)
3760  double WTy = (hasBaryonBeams) ? (1. - pow2(y3/y3Max))
3761  * (1. - pow2(y4/y4Max)) * (1. - pow2(y5/y5Max)) : 1.;
3762  if (WTy < rndmPtr->flat()) return false;
3763 
3764  // Check that any pair separated more then RsepMin in (y, phi) space.
3765  dphi = abs(phi3 - phi4);
3766  if (dphi > M_PI) dphi = 2. * M_PI - dphi;
3767  if (pow2(y3 - y4) + pow2(dphi) < R2sepMin) return false;
3768  dphi = abs(phi3 - phi5);
3769  if (dphi > M_PI) dphi = 2. * M_PI - dphi;
3770  if (pow2(y3 - y5) + pow2(dphi) < R2sepMin) return false;
3771  dphi = abs(phi4 - phi5);
3772  if (dphi > M_PI) dphi = 2. * M_PI - dphi;
3773  if (pow2(y4 - y5) + pow2(dphi) < R2sepMin) return false;
3774 
3775  // Reconstruct all four-vectors.
3776  pH[3] = pT3 * Vec4( cos(phi3), sin(phi3), sinh(y3), cosh(y3) );
3777  pH[4] = pT4 * Vec4( cos(phi4), sin(phi4), sinh(y4), cosh(y4) );
3778  pH[5] = pT5 * Vec4( cos(phi5), sin(phi5), sinh(y5), cosh(y5) );
3779  pInSum = pH[3] + pH[4] + pH[5];
3780 
3781  // Check that x values physical and sHat in allowed range.
3782  x1H = (pInSum.e() + pInSum.pz()) / eCM;
3783  x2H = (pInSum.e() - pInSum.pz()) / eCM;
3784  if (x1H >= 1. || x2H >= 1.) return false;
3785  sH = pInSum.m2Calc();
3786  if ( sH < pow2(mHatGlobalMin) ||
3787  (mHatGlobalMax > mHatGlobalMin && sH > pow2(mHatGlobalMax)) )
3788  return false;
3789 
3790  // Boost four-vectors to rest frame of collision.
3791  betaZ = (x1H - x2H)/(x1H + x2H);
3792  p3cm = pH[3]; p3cm.bst( 0., 0., -betaZ);
3793  p4cm = pH[4]; p4cm.bst( 0., 0., -betaZ);
3794  p5cm = pH[5]; p5cm.bst( 0., 0., -betaZ);
3795 
3796  // Find cross section in chosen phase space point.
3797  sigmaProcessPtr->set3Kin( x1H, x2H, sH, p3cm, p4cm, p5cm,
3798  0., 0., 0., 1., 1., 1.);
3799  sigmaNw = sigmaProcessPtr->sigmaPDF();
3800 
3801  // Multiply by Jacobian. Correct for rejection of large rapidities.
3802  double flux = 1. /(8. * pow2(sH) * pow5(2. * M_PI));
3803  double yRng = 8. * y3Max * y4Max * y5Max;
3804  double pTRng = pow2(M_PI)
3805  * pow4(pT3) * (1./pow2(pT3Min) - 1./pow2(pT3Max))
3806  * pow2(pT5) * 2.* log(pT5Max/pT5Min);
3807  sigmaNw *= flux * yRng * pTRng / WTy;
3808 
3809  // Allow possibility for user to modify cross section.
3810  if (canModifySigma) sigmaNw
3811  *= userHooksPtr->multiplySigmaBy( sigmaProcessPtr, this, inEvent);
3812  if (canBiasSelection) sigmaNw
3813  *= userHooksPtr->biasSelectionBy( sigmaProcessPtr, this, inEvent);
3814  if (canBias2Sel) sigmaNw *= pow( pTH / bias2SelRef, bias2SelPow);
3815 
3816  // Check if maximum violated.
3817  newSigmaMx = false;
3818  if (sigmaNw > sigmaMx) {
3819  infoPtr->errorMsg("Warning in PhaseSpace2to3yyycyl::trialKin: "
3820  "maximum for cross section violated");
3821 
3822  // Violation strategy 1: increase maximum (always during initialization).
3823  if (increaseMaximum || !inEvent) {
3824  double violFact = SAFETYMARGIN * sigmaNw / sigmaMx;
3825  sigmaMx = SAFETYMARGIN * sigmaNw;
3826  newSigmaMx = true;
3827  if (showViolation) {
3828  if (violFact < 9.99) cout << fixed;
3829  else cout << scientific;
3830  cout << " PYTHIA Maximum for " << sigmaProcessPtr->name()
3831  << " increased by factor " << setprecision(3) << violFact
3832  << " to " << scientific << sigmaMx << endl;
3833  }
3834 
3835  // Violation strategy 2: weight event (done in ProcessContainer).
3836  } else if (showViolation && sigmaNw > sigmaPos) {
3837  double violFact = sigmaNw / sigmaMx;
3838  if (violFact < 9.99) cout << fixed;
3839  else cout << scientific;
3840  cout << " PYTHIA Maximum for " << sigmaProcessPtr->name()
3841  << " exceeded by factor " << setprecision(3) << violFact << endl;
3842  sigmaPos = sigmaNw;
3843  }
3844  }
3845 
3846  // Check if negative cross section.
3847  if (sigmaNw < sigmaNeg) {
3848  infoPtr->errorMsg("Warning in PhaseSpace2to3yyycyl::trialKin:"
3849  " negative cross section set 0", "for " + sigmaProcessPtr->name() );
3850  sigmaNeg = sigmaNw;
3851 
3852  // Optional printout of (all) violations.
3853  if (showViolation) cout << " PYTHIA Negative minimum for "
3854  << sigmaProcessPtr->name() << " changed to " << scientific
3855  << setprecision(3) << sigmaNeg << endl;
3856  }
3857  if (sigmaNw < 0.) sigmaNw = 0.;
3858 
3859 
3860  // Done.
3861  return true;
3862 }
3863 
3864 //--------------------------------------------------------------------------
3865 
3866 // Construct the final kinematics of the process: not much left
3867 
3868 bool PhaseSpace2to3yyycyl::finalKin() {
3869 
3870  // Work with massless partons.
3871  for (int i = 0; i < 6; ++i) mH[i] = 0.;
3872 
3873  // Ibncoming partons to collision.
3874  pH[1] = 0.5 * (pInSum.e() + pInSum.pz()) * Vec4( 0., 0., 1., 1.);
3875  pH[2] = 0.5 * (pInSum.e() - pInSum.pz()) * Vec4( 0., 0., -1., 1.);
3876 
3877  // Some quantities meaningless for 2 -> 3. pT defined as average value.
3878  tH = 0.;
3879  uH = 0.;
3880  pTH = (pH[3].pT() + pH[4].pT() + pH[5].pT()) / 3.;
3881  theta = 0.;
3882  phi = 0.;
3883 
3884  return true;
3885 }
3886 
3887 
3888 //==========================================================================
3889 
3890 // The PhaseSpaceLHA class.
3891 // A derived class for Les Houches events.
3892 // Note: arbitrary subdivision into PhaseSpaceLHA and SigmaLHAProcess tasks.
3893 
3894 //--------------------------------------------------------------------------
3895 
3896 // Constants: could be changed here if desired, but normally should not.
3897 // These are of technical nature, as described for each.
3898 
3899 // LHA convention with cross section in pb forces conversion to mb.
3900 const double PhaseSpaceLHA::CONVERTPB2MB = 1e-9;
3901 
3902 //--------------------------------------------------------------------------
3903 
3904 // Find maximal cross section for comparison with internal processes.
3905 
3906 bool PhaseSpaceLHA::setupSampling() {
3907 
3908  // Find which strategy Les Houches events are produced with.
3909  strategy = lhaUpPtr->strategy();
3910  stratAbs = abs(strategy);
3911  if (strategy == 0 || stratAbs > 4) {
3912  ostringstream stratCode;
3913  stratCode << strategy;
3914  infoPtr->errorMsg("Error in PhaseSpaceLHA::setupSampling: unknown "
3915  "Les Houches Accord weighting stategy", stratCode.str());
3916  return false;
3917  }
3918 
3919  // Number of contributing processes.
3920  nProc = lhaUpPtr->sizeProc();
3921 
3922  // Loop over all processes. Read out maximum and cross section.
3923  xMaxAbsSum = 0.;
3924  xSecSgnSum = 0.;
3925  int idPr;
3926  double xMax, xSec, xMaxAbs;
3927  for (int iProc = 0 ; iProc < nProc; ++iProc) {
3928  idPr = lhaUpPtr->idProcess(iProc);
3929  xMax = lhaUpPtr->xMax(iProc);
3930  xSec = lhaUpPtr->xSec(iProc);
3931 
3932  // Check for inconsistencies between strategy and stored values.
3933  if ( (strategy == 1 || strategy == 2) && xMax < 0.) {
3934  infoPtr->errorMsg("Error in PhaseSpaceLHA::setupSampling: "
3935  "negative maximum not allowed");
3936  return false;
3937  }
3938  if ( ( strategy == 2 || strategy == 3) && xSec < 0.) {
3939  infoPtr->errorMsg("Error in PhaseSpaceLHA::setupSampling: "
3940  "negative cross section not allowed");
3941  return false;
3942  }
3943 
3944  // Store maximal cross sections for later choice.
3945  if (stratAbs == 1) xMaxAbs = abs(xMax);
3946  else if (stratAbs < 4) xMaxAbs = abs(xSec);
3947  else xMaxAbs = 1.;
3948  idProc.push_back( idPr );
3949  xMaxAbsProc.push_back( xMaxAbs );
3950 
3951  // Find sum and convert to mb.
3952  xMaxAbsSum += xMaxAbs;
3953  xSecSgnSum += xSec;
3954  }
3955  sigmaMx = xMaxAbsSum * CONVERTPB2MB;
3956  sigmaSgn = xSecSgnSum * CONVERTPB2MB;
3957 
3958  // Done.
3959  return true;
3960 
3961 }
3962 
3963 //--------------------------------------------------------------------------
3964 
3965 // Construct the next process, by interface to Les Houches class.
3966 
3967 bool PhaseSpaceLHA::trialKin( bool, bool repeatSame ) {
3968 
3969  // Must select process type in some cases.
3970  int idProcNow = 0;
3971  if (repeatSame) idProcNow = idProcSave;
3972  else if (stratAbs <= 2) {
3973  double xMaxAbsRndm = xMaxAbsSum * rndmPtr->flat();
3974  int iProc = -1;
3975  do xMaxAbsRndm -= xMaxAbsProc[++iProc];
3976  while (xMaxAbsRndm > 0. && iProc < nProc - 1);
3977  idProcNow = idProc[iProc];
3978  }
3979 
3980  // Generate Les Houches event. Return if fail (= end of file).
3981  bool physical = lhaUpPtr->setEvent(idProcNow);
3982  if (!physical) return false;
3983 
3984  // Find which process was generated.
3985  int idPr = lhaUpPtr->idProcess();
3986  int iProc = 0;
3987  for (int iP = 0; iP < int(idProc.size()); ++iP)
3988  if (idProc[iP] == idPr) iProc = iP;
3989  idProcSave = idPr;
3990 
3991  // Extract cross section and rescale according to strategy.
3992  double wtPr = lhaUpPtr->weight();
3993  if (stratAbs == 1) sigmaNw = wtPr * CONVERTPB2MB
3994  * xMaxAbsSum / xMaxAbsProc[iProc];
3995  else if (stratAbs == 2) sigmaNw = (wtPr / abs(lhaUpPtr->xMax(iProc)))
3996  * sigmaMx;
3997  else if (strategy == 3) sigmaNw = sigmaMx;
3998  else if (strategy == -3 && wtPr > 0.) sigmaNw = sigmaMx;
3999  else if (strategy == -3) sigmaNw = -sigmaMx;
4000  else if (stratAbs == 4) sigmaNw = wtPr * CONVERTPB2MB;
4001 
4002  // Set x scales.
4003  x1H = lhaUpPtr->x1();
4004  x2H = lhaUpPtr->x2();
4005 
4006  // Done.
4007  return true;
4008 
4009 }
4010 
4011 //==========================================================================
4012 
4013 } // end namespace Pythia8
Definition: AgUStep.h:26