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