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