source: HiSusy/trunk/Pythia8/pythia8170/src/PhaseSpace.cc @ 1

Last change on this file since 1 was 1, checked in by zerwas, 11 years ago

first import of structure, PYTHIA8 and DELPHES

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