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