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