]>
Commit | Line | Data |
---|---|---|
5ad4eb21 | 1 | // SpaceShower.cc is a part of the PYTHIA event generator. |
2 | // Copyright (C) 2008 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 | // SpaceShower class. | |
8 | ||
9 | #include "SpaceShower.h" | |
10 | ||
11 | namespace Pythia8 { | |
12 | ||
13 | //************************************************************************** | |
14 | ||
15 | // The SpaceShower class. | |
16 | ||
17 | //********* | |
18 | ||
19 | // Constants: could be changed here if desired, but normally should not. | |
20 | // These are of technical nature, as described for each. | |
21 | ||
22 | // Leftover companion can give PDF > 0 at small Q2 where other PDF's = 0, | |
23 | // and then one can end in infinite loop of impossible kinematics. | |
24 | const int SpaceShower::MAXLOOPTINYPDF = 10; | |
25 | ||
26 | // Switch to alternative (but equivalent) backwards evolution for | |
27 | // g -> Q Qbar (Q = c or b) when below QTHRESHOLD * mQ2. | |
28 | const double SpaceShower::CTHRESHOLD = 2.0; | |
29 | const double SpaceShower::BTHRESHOLD = 2.0; | |
30 | ||
31 | // Renew evaluation of PDF's when the pT2 step is bigger than this | |
32 | // (in addition to initial scale and c and b thresholds.) | |
33 | const double SpaceShower::EVALPDFSTEP = 0.1; | |
34 | ||
35 | // Lower limit on PDF value in order to avoid division by zero. | |
36 | const double SpaceShower::TINYPDF = 1e-10; | |
37 | ||
38 | // Lower limit on estimated evolution rate, below which stop. | |
39 | const double SpaceShower::TINYKERNELPDF = 1e-6; | |
40 | ||
41 | // Lower limit on pT2, below which branching is rejected. | |
42 | const double SpaceShower::TINYPT2 = 0.25e-6; | |
43 | ||
44 | // No attempt to do backwards evolution of a heavy (c or b) quark | |
45 | // if evolution starts at a scale pT2 < HEAVYPT2EVOL * mQ2. | |
46 | const double SpaceShower::HEAVYPT2EVOL = 1.1; | |
47 | ||
48 | // No attempt to do backwards evolution of a heavy (c or b) quark | |
49 | // if evolution starts at a x > HEAVYXEVOL * x_max, where | |
50 | // x_max is the largest possible x value for a g -> Q Qbar branching. | |
51 | const double SpaceShower::HEAVYXEVOL = 0.9; | |
52 | ||
53 | // When backwards evolution Q -> g + Q creates a heavy quark Q, | |
54 | // an earlier branching g -> Q + Qbar will restrict kinematics | |
55 | // to M_{Q Qbar}^2 > EXTRASPACEQ * 4 m_Q^2. (Smarter to be found??) | |
56 | const double SpaceShower::EXTRASPACEQ = 2.0; | |
57 | ||
58 | // Never pick pT so low that alphaS is evaluated too close to Lambda_3. | |
59 | const double SpaceShower::LAMBDA3MARGIN = 1.1; | |
60 | ||
61 | // Cutoff for f_e^e at x < 1 - 10^{-10} to be used in z selection. | |
62 | // Note: the x_min quantity come from 1 - x_max. | |
63 | const double SpaceShower::LEPTONXMIN = 1e-10; | |
64 | const double SpaceShower::LEPTONXMAX = 1. - 1e-10; | |
65 | ||
66 | // Stop l -> l gamma evolution slightly above m2l. | |
67 | const double SpaceShower::LEPTONPT2MIN = 1.2; | |
68 | ||
69 | // Enhancement of l -> l gamma trial rate to compensate imperfect modelling. | |
70 | const double SpaceShower::LEPTONFUDGE = 10.; | |
71 | ||
72 | //********* | |
73 | ||
74 | // Initialize alphaStrong, alphaEM and related pTmin parameters. | |
75 | ||
76 | void SpaceShower::init( BeamParticle* beamAPtrIn, | |
77 | BeamParticle* beamBPtrIn) { | |
78 | ||
79 | // Store input pointers for future use. | |
80 | beamAPtr = beamAPtrIn; | |
81 | beamBPtr = beamBPtrIn; | |
82 | ||
83 | // Main flags to switch on and off branchings. | |
84 | doQCDshower = Settings::flag("SpaceShower:QCDshower"); | |
85 | doQEDshowerByQ = Settings::flag("SpaceShower:QEDshowerByQ"); | |
86 | doQEDshowerByL = Settings::flag("SpaceShower:QEDshowerByL"); | |
87 | ||
88 | // Matching in pT of hard interaction to shower evolution. | |
89 | pTmaxMatch = Settings::mode("SpaceShower:pTmaxMatch"); | |
90 | pTdampMatch = Settings::mode("SpaceShower:pTdampMatch"); | |
91 | pTmaxFudge = Settings::parm("SpaceShower:pTmaxFudge"); | |
92 | pTdampFudge = Settings::parm("SpaceShower:pTdampFudge"); | |
93 | ||
94 | // Optionally force emissions to be ordered in rapidity/angle. | |
95 | doRapidityOrder = Settings::flag("SpaceShower:rapidityOrder"); | |
96 | ||
97 | // Charm, bottom and lepton mass thresholds. | |
98 | mc = ParticleDataTable::m0(4); | |
99 | mb = ParticleDataTable::m0(5); | |
100 | m2c = pow2(mc); | |
101 | m2b = pow2(mb); | |
102 | ||
103 | // Parameters of alphaStrong generation. | |
104 | alphaSvalue = Settings::parm("SpaceShower:alphaSvalue"); | |
105 | alphaSorder = Settings::mode("SpaceShower:alphaSorder"); | |
106 | alphaS2pi = 0.5 * alphaSvalue / M_PI; | |
107 | ||
108 | // Initialize alpha_strong generation. | |
109 | alphaS.init( alphaSvalue, alphaSorder); | |
110 | ||
111 | // Lambda for 5, 4 and 3 flavours. | |
112 | Lambda5flav = alphaS.Lambda5(); | |
113 | Lambda4flav = alphaS.Lambda4(); | |
114 | Lambda3flav = alphaS.Lambda3(); | |
115 | Lambda5flav2 = pow2(Lambda5flav); | |
116 | Lambda4flav2 = pow2(Lambda4flav); | |
117 | Lambda3flav2 = pow2(Lambda3flav); | |
118 | ||
119 | // Regularization of QCD evolution for pT -> 0. Can be taken | |
120 | // same as for multiple interactions, or be set separately. | |
121 | useSamePTasMI = Settings::flag("SpaceShower:samePTasMI"); | |
122 | if (useSamePTasMI) { | |
123 | pT0Ref = Settings::parm("MultipleInteractions:pT0Ref"); | |
124 | ecmRef = Settings::parm("MultipleInteractions:ecmRef"); | |
125 | ecmPow = Settings::parm("MultipleInteractions:ecmPow"); | |
126 | pTmin = Settings::parm("MultipleInteractions:pTmin"); | |
127 | } else { | |
128 | pT0Ref = Settings::parm("SpaceShower:pT0Ref"); | |
129 | ecmRef = Settings::parm("SpaceShower:ecmRef"); | |
130 | ecmPow = Settings::parm("SpaceShower:ecmPow"); | |
131 | pTmin = Settings::parm("SpaceShower:pTmin"); | |
132 | } | |
133 | ||
134 | // Calculate nominal invariant mass of events. Set current pT0 scale. | |
135 | sCM = m2( beamAPtr->p(), beamBPtr->p()); | |
136 | eCM = sqrt(sCM); | |
137 | pT0 = pT0Ref * pow(eCM / ecmRef, ecmPow); | |
138 | ||
139 | // Restrict pTmin to ensure that alpha_s(pTmin^2 + pT_0^2) does not blow up. | |
140 | pTmin = max( pTmin, sqrtpos(pow2(LAMBDA3MARGIN) * Lambda3flav2 - pT0*pT0) ); | |
141 | ||
142 | // Parameters of alphaEM generation. | |
143 | alphaEMorder = Settings::mode("SpaceShower:alphaEMorder"); | |
144 | ||
145 | // Initialize alphaEM generation. | |
146 | alphaEM.init( alphaEMorder); | |
147 | ||
148 | // Parameters of QED evolution. | |
149 | pTminChgQ = Settings::parm("SpaceShower:pTminchgQ"); | |
150 | pTminChgL = Settings::parm("SpaceShower:pTminchgL"); | |
151 | ||
152 | // Derived parameters of QCD evolution. | |
153 | pT20 = pow2(pT0); | |
154 | pT2min = pow2(pTmin); | |
155 | pT2minChgQ = pow2(pTminChgQ); | |
156 | pT2minChgL = pow2(pTminChgL); | |
157 | ||
158 | // Various other parameters. | |
159 | doMEcorrections = Settings::flag("SpaceShower:MEcorrections"); | |
160 | doPhiPolAsym = Settings::flag("SpaceShower:phiPolAsym"); | |
161 | nQuarkIn = Settings::mode("SpaceShower:nQuarkIn"); | |
162 | ||
163 | } | |
164 | ||
165 | //********* | |
166 | ||
167 | // Find whether to limit maximum scale of emissions. | |
168 | ||
169 | bool SpaceShower::limitPTmax( Event& event, double Q2Fac, double Q2Ren) { | |
170 | ||
171 | // Find whether to limit pT. Begin by user-set cases. | |
172 | bool dopTlimit = false; | |
173 | if (pTmaxMatch == 1) dopTlimit = true; | |
174 | else if (pTmaxMatch == 2) dopTlimit = false; | |
175 | ||
176 | // Look if any quark (u, d, s, c, b), gluon or photon in final state. | |
177 | else { | |
178 | for (int i = 5; i < event.size(); ++i) | |
179 | if (event[i].status() != -21) { | |
180 | int idAbs = event[i].idAbs(); | |
181 | if (idAbs <= 5 || idAbs == 21 || idAbs == 22) dopTlimit = true; | |
182 | } | |
183 | } | |
184 | ||
185 | // Dampening at factorization or renormalization scale. | |
186 | dopTdamp = false; | |
187 | pT2damp = 0.; | |
188 | if ( !dopTlimit && (pTdampMatch == 1 || pTdampMatch == 2) ) { | |
189 | dopTdamp = true; | |
190 | pT2damp = pow2(pTdampFudge) * ((pTdampMatch == 1) ? Q2Fac : Q2Ren); | |
191 | } | |
192 | ||
193 | // Done. | |
194 | return dopTlimit; | |
195 | ||
196 | } | |
197 | ||
198 | //********* | |
199 | ||
200 | // Prepare system for evolution; identify ME. | |
201 | // Routine may be called after multiple interactions, for a new subystem. | |
202 | ||
203 | void SpaceShower::prepare( int iSys, Event& event, bool limitPTmaxIn) { | |
204 | ||
205 | // Find positions of incoming colliding partons. | |
206 | int in1 = event.getInSystem( iSys, 0); | |
207 | int in2 = event.getInSystem( iSys, 1); | |
208 | ||
209 | // Reset dipole-ends list for first interaction. | |
210 | if (iSys == 0) dipEnd.resize(0); | |
211 | ||
212 | // Find matrix element corrections for system. | |
213 | int MEtype = findMEtype( iSys, event); | |
214 | ||
215 | // Maximum pT scale for dipole ends. | |
216 | double pTmax1 = (limitPTmaxIn) ? event[in1].scale() : eCM; | |
217 | double pTmax2 = (limitPTmaxIn) ? event[in2].scale() : eCM; | |
218 | if (iSys == 0 && limitPTmaxIn) { | |
219 | pTmax1 *= pTmaxFudge; | |
220 | pTmax2 *= pTmaxFudge; | |
221 | } | |
222 | ||
223 | // Find dipole ends for QCD radiation. | |
224 | if (doQCDshower) { | |
225 | int colType1 = event[in1].colType(); | |
226 | dipEnd.push_back( SpaceDipoleEnd( iSys, 1, in1, in2, pTmax1, | |
227 | colType1, 0, MEtype) ); | |
228 | int colType2 = event[in2].colType(); | |
229 | dipEnd.push_back( SpaceDipoleEnd( iSys, 2, in2, in1, pTmax2, | |
230 | colType2, 0, MEtype) ); | |
231 | } | |
232 | ||
233 | // Find dipole ends for QED radiation. | |
234 | if (doQEDshowerByQ || doQEDshowerByL) { | |
235 | int chgType1 = ( (event[in1].isQuark() && doQEDshowerByQ) | |
236 | || (event[in1].isLepton() && doQEDshowerByL) ) | |
237 | ? event[in1].chargeType() : 0; | |
238 | dipEnd.push_back( SpaceDipoleEnd( iSys, -1, in1, in2, pTmax1, | |
239 | 0, chgType1, MEtype) ); | |
240 | int chgType2 = ( (event[in2].isQuark() && doQEDshowerByQ) | |
241 | || (event[in2].isLepton() && doQEDshowerByL) ) | |
242 | ? event[in2].chargeType() : 0; | |
243 | dipEnd.push_back( SpaceDipoleEnd( iSys, -2, in2, in1, pTmax2, | |
244 | 0, chgType2, MEtype) ); | |
245 | } | |
246 | ||
247 | } | |
248 | ||
249 | //********* | |
250 | ||
251 | // Select next pT in downwards evolution of the existing dipoles. | |
252 | ||
253 | double SpaceShower::pTnext( Event& , double pTbegAll, double pTendAll, | |
254 | int nRadIn) { | |
255 | ||
256 | // Current cm energy, in case it varies between events. | |
257 | sCM = m2( beamAPtr->p(), beamBPtr->p()); | |
258 | ||
259 | // Starting values: no radiating dipole found. | |
260 | nRad = nRadIn; | |
261 | double pT2sel = pow2(pTendAll); | |
262 | iDipSel = 0; | |
263 | iSysSel = 0; | |
264 | dipEndSel = 0; | |
265 | ||
266 | // Loop over all possible dipole ends. | |
267 | for (int iDipEnd = 0; iDipEnd < int(dipEnd.size()); ++iDipEnd) { | |
268 | iDipNow = iDipEnd; | |
269 | dipEndNow = &dipEnd[iDipEnd]; | |
270 | iSysNow = dipEndNow->system; | |
271 | dipEndNow->pT2 = 0.; | |
272 | ||
273 | // Check whether dipole end should be allowed to shower. | |
274 | double pT2begDip = pow2( min( pTbegAll, dipEndNow->pTmax )); | |
275 | if (pT2begDip > pT2sel | |
276 | && ( dipEndNow->colType != 0 || dipEndNow->chgType != 0 ) ) { | |
277 | double pT2endDip = 0.; | |
278 | ||
279 | // Determine lower cut for evolution, for QCD or QED (q or l). | |
280 | if (dipEndNow->colType != 0) pT2endDip = max( pT2sel, pT2min ); | |
281 | else if (abs(dipEndNow->chgType) != 3) pT2endDip | |
282 | = max( pT2sel, pT2minChgQ ); | |
283 | else pT2endDip = max( pT2sel, pT2minChgL ); | |
284 | ||
285 | // Find properties of dipole and radiating dipole end. | |
286 | bool ordered = ( abs(dipEndNow->side) == 1 ); | |
287 | BeamParticle& beamNow = (ordered) ? *beamAPtr : *beamBPtr; | |
288 | BeamParticle& beamRec = (ordered) ? *beamBPtr : *beamAPtr; | |
289 | iNow = beamNow[iSysNow].iPos(); | |
290 | iRec = beamRec[iSysNow].iPos(); | |
291 | idDaughter = beamNow[iSysNow].id(); | |
292 | xDaughter = beamNow[iSysNow].x(); | |
293 | x1Now = (ordered) ? xDaughter : beamRec[iSysNow].x(); | |
294 | x2Now = (ordered) ? beamRec[iSysNow].x() : xDaughter; | |
295 | m2Dip = x1Now * x2Now * sCM; | |
296 | ||
297 | // Now do evolution in pT2, for QCD or QED | |
298 | if (pT2begDip > pT2endDip) { | |
299 | if (dipEndNow->colType != 0) pT2nextQCD( pT2begDip, pT2endDip); | |
300 | else pT2nextQED( pT2begDip, pT2endDip); | |
301 | } | |
302 | ||
303 | // Update if found larger pT than current maximum. | |
304 | if (dipEndNow->pT2 > pT2sel) { | |
305 | pT2sel = dipEndNow->pT2; | |
306 | iDipSel = iDipNow; | |
307 | iSysSel = iSysNow; | |
308 | dipEndSel = dipEndNow; | |
309 | } | |
310 | ||
311 | // End loop over dipole ends. | |
312 | } | |
313 | } | |
314 | ||
315 | // Return nonvanishing value if found pT is bigger than already found. | |
316 | return (dipEndSel == 0) ? 0. : sqrt(pT2sel); | |
317 | } | |
318 | ||
319 | //********* | |
320 | ||
321 | // Evolve a QCD dipole end. | |
322 | ||
323 | void SpaceShower::pT2nextQCD( double pT2begDip, double pT2endDip) { | |
324 | ||
325 | // Some properties and kinematical starting values. | |
326 | BeamParticle& beam = ( abs(dipEndNow->side) == 1 ) | |
327 | ? *beamAPtr : *beamBPtr; | |
328 | bool isGluon = (idDaughter == 21); | |
329 | bool isValence = beam[iSysNow].isValence(); | |
330 | int MEtype = dipEndNow->MEtype; | |
331 | double pT2 = pT2begDip; | |
332 | double xMaxAbs = beam.xMax(iSysNow); | |
333 | double zMinAbs = xDaughter / xMaxAbs; | |
334 | ||
335 | // Starting values for handling of massive quarks (c/b), if any. | |
336 | double idMassive = 0; | |
337 | if ( abs(idDaughter) == 4 ) idMassive = 4; | |
338 | if ( abs(idDaughter) == 5 ) idMassive = 5; | |
339 | bool isMassive = (idMassive > 0); | |
340 | double m2Massive = 0.; | |
341 | double mRatio = 0.; | |
342 | double zMaxMassive = 1.; | |
343 | double m2Threshold = pT2; | |
344 | ||
345 | // Evolution below scale of massive quark or at large x is impossible. | |
346 | if (isMassive) { | |
347 | m2Massive = (idMassive == 4) ? m2c : m2b; | |
348 | if (pT2 < HEAVYPT2EVOL * m2Massive) return; | |
349 | mRatio = sqrt( m2Massive / m2Dip ); | |
350 | zMaxMassive = (1. - mRatio) / ( 1. + mRatio * (1. - mRatio) ); | |
351 | if (xDaughter > HEAVYXEVOL * zMaxMassive * xMaxAbs) return; | |
352 | ||
353 | // Find threshold scale below which only g -> Q + Qbar will be allowed. | |
354 | m2Threshold = (idMassive == 4) ? min( pT2, CTHRESHOLD * m2c) | |
355 | : min( pT2, BTHRESHOLD * m2b); | |
356 | } | |
357 | ||
358 | // Variables used inside evolution loop. (Mainly dummy starting values.) | |
359 | int nFlavour = 3; | |
360 | double b0 = 4.5; | |
361 | double Lambda2 = Lambda3flav2; | |
362 | double pT2minNow = pT2endDip; | |
363 | int idMother = 0; | |
364 | int idSister = 0; | |
365 | double z = 0.; | |
366 | double zMaxAbs = 0.; | |
367 | double zRootMax = 0.; | |
368 | double zRootMin = 0.; | |
369 | double g2gInt = 0.; | |
370 | double q2gInt = 0.; | |
371 | double q2qInt = 0.; | |
372 | double g2qInt = 0.; | |
373 | double g2Qenhance = 0.; | |
374 | double xPDFdaughter = 0.; | |
375 | double xPDFmother[21] = {0.}; | |
376 | double xPDFgMother = 0.; | |
377 | double xPDFmotherSum = 0.; | |
378 | double kernelPDF = 0.; | |
379 | double xMother = 0.; | |
380 | double wt = 0.; | |
381 | double Q2 = 0.; | |
382 | double mSister = 0.; | |
383 | double m2Sister = 0.; | |
384 | double pT2corr = 0.; | |
385 | double phi = 0.; | |
386 | double pT2PDF = pT2; | |
387 | bool needNewPDF = true; | |
388 | ||
389 | // Begin evolution loop towards smaller pT values. | |
390 | int loopTinyPDFdau = 0; | |
391 | bool hasTinyPDFdau = false; | |
392 | do { | |
393 | wt = 0.; | |
394 | ||
395 | // Bad sign if repeated looping with small daughter PDF, so fail. | |
396 | // (Example: if all PDF's = 0 below Q_0, except for c/b companion.) | |
397 | if (hasTinyPDFdau) ++loopTinyPDFdau; | |
398 | if (loopTinyPDFdau > MAXLOOPTINYPDF) { | |
399 | infoPtr->errorMsg("Warning in SpaceShower::pT2nextQCD: " | |
400 | "small daughter PDF"); | |
401 | return; | |
402 | } | |
403 | ||
404 | // Initialize integrals of splitting kernels and evaluate parton | |
405 | // densities at the beginning. Reinitialize after long evolution | |
406 | // in pT2 or when crossing c and b flavour thresholds. | |
407 | if (needNewPDF || pT2 < EVALPDFSTEP * pT2PDF) { | |
408 | pT2PDF = pT2; | |
409 | hasTinyPDFdau = false; | |
410 | ||
411 | // Determine overestimated z range; switch at c and b masses. | |
412 | if (pT2 > m2b) { | |
413 | nFlavour = 5; | |
414 | pT2minNow = m2b; | |
415 | b0 = 23./6.; | |
416 | Lambda2 = Lambda5flav2; | |
417 | } else if (pT2 > m2c) { | |
418 | nFlavour = 4; | |
419 | pT2minNow = m2c; | |
420 | b0 = 25./6.; | |
421 | Lambda2 = Lambda4flav2; | |
422 | } else { | |
423 | nFlavour = 3; | |
424 | pT2minNow = pT2endDip; | |
425 | b0 = 27./6.; | |
426 | Lambda2 = Lambda3flav2; | |
427 | } | |
428 | zMaxAbs = 1. - 0.5 * (pT2minNow / m2Dip) * | |
429 | ( sqrt( 1. + 4. * m2Dip / pT2minNow ) - 1. ); | |
430 | if (isMassive) zMaxAbs = min( zMaxAbs, zMaxMassive); | |
431 | ||
432 | // Go to another z range with lower mass scale if current is closed. | |
433 | if (zMinAbs > zMaxAbs) { | |
434 | if (nFlavour == 3 || (idMassive == 4 && nFlavour == 4) | |
435 | || idMassive == 5) return; | |
436 | pT2 = (nFlavour == 4) ? m2c : m2b; | |
437 | continue; | |
438 | } | |
439 | ||
440 | // Parton density of daughter at current scale. | |
441 | xPDFdaughter = beam.xfISR(iSysNow, idDaughter, xDaughter, pT2); | |
442 | if (xPDFdaughter < TINYPDF) { | |
443 | xPDFdaughter = TINYPDF; | |
444 | hasTinyPDFdau = true; | |
445 | } | |
446 | ||
447 | // Integrals of splitting kernels for gluons: g -> g, q -> g. | |
448 | if (isGluon) { | |
449 | g2gInt = 6. * log(zMaxAbs * (1.-zMinAbs) | |
450 | / (zMinAbs * (1.-zMaxAbs))); | |
451 | if (doMEcorrections) g2gInt *= calcMEmax(MEtype, 21, 21); | |
452 | q2gInt = (16./3.) * (1./sqrt(zMinAbs) - 1./sqrt(zMaxAbs)); | |
453 | if (doMEcorrections) q2gInt *= calcMEmax(MEtype, 1, 21); | |
454 | ||
455 | // Parton density of potential quark mothers to a g. | |
456 | xPDFmotherSum = 0.; | |
457 | for (int i = -nQuarkIn; i <= nQuarkIn; ++i) { | |
458 | if (i == 0) { | |
459 | xPDFmother[10] = 0.; | |
460 | } else { | |
461 | xPDFmother[i+10] = beam.xfISR(iSysNow, i, xDaughter, pT2); | |
462 | xPDFmotherSum += xPDFmother[i+10]; | |
463 | } | |
464 | } | |
465 | ||
466 | // Total QCD evolution coefficient for a gluon. | |
467 | kernelPDF = g2gInt + q2gInt * xPDFmotherSum / xPDFdaughter; | |
468 | ||
469 | // For valence quark only need consider q -> q g branchings. | |
470 | // Introduce an extra factor sqrt(z) to smooth bumps. | |
471 | } else if (isValence) { | |
472 | zRootMin = (1. + sqrt(zMinAbs)) / (1. - sqrt(zMinAbs)); | |
473 | zRootMax = (1. + sqrt(zMaxAbs)) / (1. - sqrt(zMaxAbs)); | |
474 | q2qInt = (8./3.) * log( zRootMax / zRootMin ); | |
475 | if (doMEcorrections) q2qInt *= calcMEmax(MEtype, 1, 1); | |
476 | g2qInt = 0.; | |
477 | kernelPDF = q2qInt; | |
478 | ||
479 | // Integrals of splitting kernels for quarks: q -> q, g -> q. | |
480 | } else { | |
481 | q2qInt = (8./3.) * log( (1. - zMinAbs) / (1. - zMaxAbs) ); | |
482 | if (doMEcorrections) q2qInt *= calcMEmax(MEtype, 1, 1); | |
483 | g2qInt = 0.5 * (zMaxAbs - zMinAbs); | |
484 | if (doMEcorrections) g2qInt *= calcMEmax(MEtype, 21, 1); | |
485 | ||
486 | // Increase estimated upper weight for g -> Q + Qbar. | |
487 | if (isMassive) { | |
488 | double m2log = log( m2Massive / Lambda2); | |
489 | g2Qenhance = log( log(pT2/Lambda2) / m2log ) | |
490 | / log( log(m2Threshold/Lambda2) / m2log ); | |
491 | g2qInt *= g2Qenhance; | |
492 | } | |
493 | ||
494 | // Parton density of a potential gluon mother to a q. | |
495 | xPDFgMother = beam.xfISR(iSysNow, 21, xDaughter, pT2); | |
496 | ||
497 | // Total QCD evolution coefficient for a quark. | |
498 | kernelPDF = q2qInt + g2qInt * xPDFgMother / xPDFdaughter; | |
499 | } | |
500 | ||
501 | // End evaluation of splitting kernels and parton densities. | |
502 | needNewPDF = false; | |
503 | } | |
504 | if (kernelPDF < TINYKERNELPDF) return; | |
505 | ||
506 | // Pick pT2 (in overestimated z range), for one of three different cases. | |
507 | // Assume form alphas(pT0^2 + pT^2) * dpT^2/(pT0^2 + pT^2). | |
508 | double Q2alphaS; | |
509 | ||
510 | // Fixed alpha_strong. | |
511 | if (alphaSorder == 0) { | |
512 | pT2 = (pT2 + pT20) * pow( Rndm::flat(), | |
513 | 1. / (alphaS2pi * kernelPDF)) - pT20; | |
514 | ||
515 | // First-order alpha_strong. | |
516 | } else if (alphaSorder == 1) { | |
517 | pT2 = Lambda2 * pow( (pT2 + pT20) / Lambda2, | |
518 | pow(Rndm::flat(), b0 / kernelPDF) ) - pT20; | |
519 | ||
520 | // For second order reject by second term in alpha_strong expression. | |
521 | } else { | |
522 | do { | |
523 | pT2 = Lambda2 * pow( (pT2 + pT20) / Lambda2, | |
524 | pow(Rndm::flat(), b0 / kernelPDF) ) - pT20; | |
525 | Q2alphaS = max(pT2 + pT20, pow2(LAMBDA3MARGIN) * Lambda3flav2); | |
526 | } while (alphaS.alphaS2OrdCorr(Q2alphaS) < Rndm::flat() | |
527 | && pT2 > pT2minNow); | |
528 | } | |
529 | ||
530 | // Check for pT2 values that prompt special action. | |
531 | ||
532 | // If fallen into b threshold region, force g -> b + bbar. | |
533 | if (idMassive == 5 && pT2 < m2Threshold) { | |
534 | pT2nearQCDthreshold( beam, m2Massive, m2Threshold, zMinAbs, | |
535 | zMaxMassive ); | |
536 | return; | |
537 | ||
538 | // If crossed b threshold, continue evolution from this threshold. | |
539 | } else if (nFlavour == 5 && pT2 < m2b) { | |
540 | needNewPDF = true; | |
541 | pT2 = m2b; | |
542 | continue; | |
543 | ||
544 | // If fallen into c threshold region, force g -> c + cbar. | |
545 | } else if (idMassive == 4 && pT2 < m2Threshold) { | |
546 | pT2nearQCDthreshold( beam, m2Massive, m2Threshold, zMinAbs, | |
547 | zMaxMassive ); | |
548 | return; | |
549 | ||
550 | // If crossed c threshold, continue evolution from this threshold. | |
551 | } else if (nFlavour == 4 && pT2 < m2c) { | |
552 | needNewPDF = true; | |
553 | pT2 = m2c; | |
554 | continue; | |
555 | ||
556 | // Abort evolution if below cutoff scale, or below another branching. | |
557 | } else if (pT2 < pT2endDip) return; | |
558 | ||
559 | // Select z value of branching to g, and corrective weight. | |
560 | if (isGluon) { | |
561 | // g -> g (+ g). | |
562 | if (Rndm::flat() * kernelPDF < g2gInt) { | |
563 | idMother = 21; | |
564 | idSister = 21; | |
565 | z = 1. / ( 1. + ((1. - zMinAbs) / zMinAbs) * pow( (zMinAbs * | |
566 | (1. - zMaxAbs)) / (zMaxAbs * (1. - zMinAbs)), Rndm::flat() ) ); | |
567 | wt = pow2( 1. - z * (1. - z)); | |
568 | } else { | |
569 | // q -> g (+ q): also select flavour. | |
570 | double temp = xPDFmotherSum * Rndm::flat(); | |
571 | idMother = -nQuarkIn - 1; | |
572 | do { temp -= xPDFmother[(++idMother) + 10]; } | |
573 | while (temp > 0. && idMother < nQuarkIn); | |
574 | idSister = idMother; | |
575 | z = (zMinAbs * zMaxAbs) / pow2( sqrt(zMinAbs) + Rndm::flat() | |
576 | * ( sqrt(zMaxAbs)- sqrt(zMinAbs) )); | |
577 | wt = 0.5 * (1. + pow2(1. - z)) * sqrt(z) | |
578 | * xPDFdaughter / xPDFmother[idMother + 10]; | |
579 | } | |
580 | ||
581 | // Select z value of branching to q, and corrective weight. | |
582 | // Include massive kernel corrections for c and b quarks. | |
583 | } else { | |
584 | // q -> q (+ g). | |
585 | if (isValence || Rndm::flat() * kernelPDF < q2qInt) { | |
586 | idMother = idDaughter; | |
587 | idSister = 21; | |
588 | // Valence more peaked at large z. | |
589 | if (isValence) { | |
590 | double zTmp = zRootMin * pow(zRootMax / zRootMin, Rndm::flat() ); | |
591 | z = pow2( (1. - zTmp) / (1. + zTmp) ); | |
592 | } else { | |
593 | z = 1. - (1. - zMinAbs) * pow( (1. - zMaxAbs) / (1. - zMinAbs), | |
594 | Rndm::flat() ); | |
595 | } | |
596 | if (!isMassive) { | |
597 | wt = 0.5 * (1. + pow2(z)); | |
598 | } else { | |
599 | wt = 0.5 * (1. + pow2(z) - z * pow2(1.-z) * m2Massive / pT2); | |
600 | } | |
601 | if (isValence) wt *= sqrt(z); | |
602 | // g -> q (+ qbar). | |
603 | } else { | |
604 | idMother = 21; | |
605 | idSister = - idDaughter; | |
606 | z = zMinAbs + Rndm::flat() * (zMaxAbs - zMinAbs); | |
607 | if (!isMassive) { | |
608 | wt = (pow2(z) + pow2(1.-z)) * xPDFdaughter / xPDFgMother ; | |
609 | } else { | |
610 | wt = (pow2(z) + pow2(1.-z) + 2. * z * (1.-z) * m2Massive / pT2) | |
611 | * xPDFdaughter / (xPDFgMother * g2Qenhance) ; | |
612 | } | |
613 | } | |
614 | } | |
615 | ||
616 | // Derive Q2 and x of mother from pT2 and z. | |
617 | Q2 = pT2 / (1.- z); | |
618 | xMother = xDaughter / z; | |
619 | ||
620 | // Forbidden emission if outside allowed z range for given pT2. | |
621 | mSister = ParticleDataTable::m0(idSister); | |
622 | m2Sister = pow2(mSister); | |
623 | pT2corr = Q2 - z * (m2Dip + Q2) * (Q2 + m2Sister) / m2Dip; | |
624 | if(pT2corr < TINYPT2) { wt = 0.; continue; } | |
625 | ||
626 | // Optionally veto emissions not ordered in rapidity (= angle). | |
627 | if ( doRapidityOrder && dipEndNow->nBranch > 0 | |
628 | && pT2 > pow2( (1. - z) / (z * (1. - dipEndNow->zOld)) ) | |
629 | * dipEndNow->pT2Old ) { wt = 0.; continue; } | |
630 | ||
631 | // If creating heavy quark by Q -> g + Q then next need g -> Q + Qbar. | |
632 | // So minimum total mass2 is 4 * m2Sister, but use more to be safe. | |
633 | if ( isGluon && ( abs(idMother) == 4 || abs(idMother) == 5 )) { | |
634 | double m2QQsister = EXTRASPACEQ * 4. * m2Sister; | |
635 | double pT2QQcorr = Q2 - z * (m2Dip + Q2) * (Q2 + m2QQsister) / m2Dip; | |
636 | if(pT2QQcorr < TINYPT2) { wt = 0.; continue; } | |
637 | } | |
638 | ||
639 | // Select phi angle of branching at random. | |
640 | phi = 2. * M_PI * Rndm::flat(); | |
641 | ||
642 | // Evaluation of ME correction. | |
643 | if (doMEcorrections) wt *= calcMEcorr(MEtype, idMother, idDaughter, | |
644 | m2Dip, z, Q2) / calcMEmax(MEtype, idMother, idDaughter); | |
645 | ||
646 | // Optional dampening of large pT values in first radiation. | |
647 | if (dopTdamp && iSysNow == 0 && MEtype == 0 && nRad == 0) | |
648 | wt *= pT2damp / (pT2 + pT2damp); | |
649 | ||
650 | // Evaluation of new daughter and mother PDF's. | |
651 | double xPDFdaughterNew = max ( TINYPDF, | |
652 | beam.xfISR(iSysNow, idDaughter, xDaughter, pT2) ); | |
653 | double xPDFmotherNew = beam.xfISR(iSysNow, idMother, xMother, pT2); | |
654 | wt *= xPDFmotherNew / xPDFdaughterNew; | |
655 | ||
656 | // Check that valence step does not cause problem. | |
657 | if (wt > 1.) infoPtr->errorMsg("Warning in SpaceShower::" | |
658 | "pT2nextQCD: weight above unity"); | |
659 | ||
660 | // Iterate until acceptable pT (or have fallen below pTmin). | |
661 | } while (wt < Rndm::flat()) ; | |
662 | ||
663 | // Save values for (so far) acceptable branching. | |
664 | dipEndNow->store( idDaughter,idMother, idSister, x1Now, x2Now, m2Dip, | |
665 | pT2, z, Q2, mSister, m2Sister, pT2corr, phi); | |
666 | ||
667 | } | |
668 | ||
669 | //********* | |
670 | ||
671 | // Evolve a QCD dipole end near threshold, with g -> Q + Qbar enforced. | |
672 | // Note: No explicit Sudakov factor formalism here. Instead use that | |
673 | // df_Q(x, pT2) = (alpha_s/2pi) * (dT2/pT2) * ((gluon) * (splitting)). | |
674 | // This implies that effects of Q -> Q + g are neglected in this range. | |
675 | ||
676 | void SpaceShower::pT2nearQCDthreshold( BeamParticle& beam, | |
677 | double m2Massive, double m2Threshold, double zMinAbs, | |
678 | double zMaxMassive) { | |
679 | ||
680 | // Initial values, to be used in kinematics and weighting. | |
681 | double Lambda2 = (abs(idDaughter) == 4) ? Lambda4flav2 : Lambda5flav2; | |
682 | double logM2Lambda2 = log( m2Massive / Lambda2 ); | |
683 | double xPDFmotherOld = beam.xfISR(iSysNow, 21, xDaughter, m2Threshold); | |
684 | ||
685 | // Variables used inside evolution loop. (Mainly dummy start values.) | |
686 | int loop = 0; | |
687 | double wt = 0.; | |
688 | double pT2 = 0.; | |
689 | double z = 0.; | |
690 | double Q2 = 0.; | |
691 | double pT2corr = 0.; | |
692 | ||
693 | // Begin loop over tries to find acceptable g -> Q + Qbar branching. | |
694 | do { | |
695 | wt = 0.; | |
696 | ||
697 | // Check that not caught in infinite loop with impossible kinematics. | |
698 | if (++loop > 100) { | |
699 | infoPtr->errorMsg("Error in SpaceShower::pT2nearQCDthreshold: " | |
700 | "stuck in loop"); | |
701 | return; | |
702 | } | |
703 | ||
704 | // Pick dpT2/pT2 in range [m2Massive,thresholdRatio * m2Massive]. | |
705 | pT2 = m2Massive * pow( m2Threshold / m2Massive, Rndm::flat() ); | |
706 | ||
707 | // Pick z flat in allowed range. | |
708 | z = zMinAbs + Rndm::flat() * (zMaxMassive - zMinAbs); | |
709 | ||
710 | // Check that kinematically possible choice. | |
711 | Q2 = pT2 / (1.-z) - m2Massive; | |
712 | pT2corr = Q2 - z * (m2Dip + Q2) * (Q2 + m2Massive) / m2Dip; | |
713 | if(pT2corr < TINYPT2) continue; | |
714 | ||
715 | // Correction factor for running alpha_s. ?? | |
716 | wt = logM2Lambda2 / log( pT2 / Lambda2 ); | |
717 | ||
718 | // Correction factor for splitting kernel. | |
719 | wt *= pow2(z) + pow2(1.-z) + 2. * z * (1.-z) * m2Massive / pT2; | |
720 | ||
721 | // Correction factor for gluon density. | |
722 | double xPDFmotherNew = beam.xfISR(iSysNow, 21, xDaughter/z, pT2); | |
723 | wt *= xPDFmotherNew / xPDFmotherOld; | |
724 | ||
725 | // Iterate until acceptable pT and z. | |
726 | } while (wt < Rndm::flat()) ; | |
727 | ||
728 | // Select phi angle of branching at random. | |
729 | double phi = 2. * M_PI * Rndm::flat(); | |
730 | ||
731 | // Save values for (so far) acceptable branching. | |
732 | double mSister = (abs(idDaughter) == 4) ? mc : mb; | |
733 | dipEndNow->store( idDaughter, 21, -idDaughter, x1Now, x2Now, m2Dip, | |
734 | pT2, z, Q2, mSister, pow2(mSister), pT2corr, phi); | |
735 | ||
736 | } | |
737 | ||
738 | //********* | |
739 | ||
740 | // Evolve a QED dipole end. | |
741 | ||
742 | void SpaceShower::pT2nextQED( double pT2begDip, double pT2endDip) { | |
743 | ||
744 | // Type of dipole and starting values. | |
745 | BeamParticle& beam = ( abs(dipEndNow->side) == 1 ) | |
746 | ? *beamAPtr : *beamBPtr; | |
747 | bool isLeptonBeam = beam.isLepton(); | |
748 | int MEtype = dipEndNow->MEtype; | |
749 | bool isPhoton = (idDaughter == 22); | |
750 | double pT2 = pT2begDip; | |
751 | double m2Lepton = (isLeptonBeam) ? pow2(beam.m()) : 0.; | |
752 | if (isLeptonBeam && pT2begDip < m2Lepton) return; | |
753 | ||
754 | // Currently no f -> gamma branching implemented. ?? | |
755 | if (isPhoton) return; | |
756 | ||
757 | // alpha_em at maximum scale provides upper estimate. | |
758 | double alphaEMmax = alphaEM.alphaEM(pT2begDip); | |
759 | double alphaEM2pi = alphaEMmax / (2. * M_PI); | |
760 | ||
761 | // Maximum x of mother implies minimum z = xDaughter / xMother. | |
762 | double xMaxAbs = (isLeptonBeam) ? LEPTONXMAX : beam.xMax(iSysNow); | |
763 | double zMinAbs = xDaughter / xMaxAbs; | |
764 | ||
765 | // Maximum z from minimum pT and, for lepton, from minimum x_gamma. | |
766 | double zMaxAbs = 1. - 0.5 * (pT2endDip / m2Dip) * | |
767 | ( sqrt( 1. + 4. * m2Dip / pT2endDip ) - 1. ); | |
768 | if (isLeptonBeam) { | |
769 | double zMaxLepton = xDaughter / (xDaughter + LEPTONXMIN); | |
770 | if (zMaxLepton < zMaxAbs) zMaxAbs = zMaxLepton; | |
771 | } | |
772 | if (zMaxAbs < zMinAbs) return; | |
773 | ||
774 | // Integrals of splitting kernels for fermions: f -> f. Use 1 + z^2 < 2. | |
775 | // Ansatz f(z) = 2 / (1 - z), with + 2 / (z - xDaughter) for lepton. | |
776 | double f2fInt = 0.; | |
777 | double f2fIntA = 2. * log( (1. - zMinAbs) / (1. - zMaxAbs) ); | |
778 | double f2fIntB = 0.; | |
779 | if (isLeptonBeam) { | |
780 | f2fIntB = 2. * log( (zMaxAbs - xDaughter) / (zMinAbs - xDaughter) ); | |
781 | f2fInt = f2fIntA + f2fIntB; | |
782 | } else f2fInt = pow2(dipEndNow->chgType / 3.) * f2fIntA; | |
783 | ||
784 | // Upper estimate for evolution equation, including fudge factor. | |
785 | if (doMEcorrections) f2fInt *= calcMEmax(MEtype, 1, 1); | |
786 | double kernelPDF = alphaEM2pi * f2fInt; | |
787 | double fudge = (isLeptonBeam) ? LEPTONFUDGE * log(m2Dip/m2Lepton) : 1.; | |
788 | kernelPDF *= fudge; | |
789 | if (kernelPDF < TINYKERNELPDF) return; | |
790 | ||
791 | // Variables used inside evolution loop. (Mainly dummy start values.) | |
792 | int idMother = 0; | |
793 | double z = 0.; | |
794 | double xMother = 0.; | |
795 | double wt = 0.; | |
796 | double Q2 = 0.; | |
797 | double mSister = 0.; | |
798 | double m2Sister = 0.; | |
799 | double pT2corr = 0.; | |
800 | double phi = 0.; | |
801 | ||
802 | // Begin evolution loop towards smaller pT values. | |
803 | do { | |
804 | wt = 0.; | |
805 | ||
806 | // Pick pT2 (in overestimated z range). | |
807 | // For l -> l gamma include extrafactor 1 / ln(pT2 / m2l) in evolution. | |
808 | double shift = pow(Rndm::flat(), 1. / kernelPDF); | |
809 | if (isLeptonBeam) pT2 = m2Lepton * pow( pT2 / m2Lepton, shift); | |
810 | else pT2 = pT2 * shift; | |
811 | ||
812 | // Abort evolution if below cutoff scale, or below another branching. | |
813 | if (pT2 < pT2endDip) return; | |
814 | if (isLeptonBeam && pT2 < LEPTONPT2MIN * m2Lepton) return; | |
815 | ||
816 | // Select z value of branching f -> f + gamma, and corrective weight. | |
817 | idMother = idDaughter; | |
818 | wt = 0.5 * (1. + pow2(z)); | |
819 | if (isLeptonBeam) { | |
820 | if (f2fIntA > Rndm::flat() * (f2fIntA + f2fIntB)) | |
821 | z = 1. - (1. - zMinAbs) | |
822 | * pow( (1. - zMaxAbs) / (1. - zMinAbs), Rndm::flat() ); | |
823 | else z = xDaughter + (zMinAbs - xDaughter) | |
824 | * pow( (zMaxAbs - xDaughter) / (zMinAbs - xDaughter), Rndm::flat() ); | |
825 | wt *= (z - xDaughter) / (1. - xDaughter); | |
826 | } else { | |
827 | z = 1. - (1. - zMinAbs) | |
828 | * pow( (1. - zMaxAbs) / (1. - zMinAbs), Rndm::flat() ); | |
829 | } | |
830 | ||
831 | // Derive Q2 and x of mother from pT2 and z. | |
832 | Q2 = pT2 / (1. - z); | |
833 | xMother = xDaughter / z; | |
834 | ||
835 | // Forbidden emission if outside allowed z range for given pT2. | |
836 | mSister = 0.; | |
837 | m2Sister = 0.; | |
838 | pT2corr = Q2 - z * (m2Dip + Q2) * (Q2 + m2Sister) / m2Dip; | |
839 | if(pT2corr < TINYPT2) { wt = 0.; continue; } | |
840 | ||
841 | // Select phi angle of branching at random. | |
842 | phi = 2. * M_PI * Rndm::flat(); | |
843 | ||
844 | // Correct by ln(pT2 / m2l) and fudge factor. | |
845 | if (isLeptonBeam) wt *= log(pT2 / m2Lepton) / fudge; | |
846 | ||
847 | // Evaluation of ME correction. | |
848 | if (doMEcorrections) wt *= calcMEcorr(MEtype, idMother, idDaughter, | |
849 | m2Dip, z, Q2) / calcMEmax(MEtype, idMother, idDaughter); | |
850 | ||
851 | // Optional dampening of large pT values in first radiation. | |
852 | if (dopTdamp && iSysNow == 0 && MEtype == 0 && nRad == 0) | |
853 | wt *= pT2damp / (pT2 + pT2damp); | |
854 | ||
855 | // Correct to current value of alpha_EM. | |
856 | double alphaEMnow = alphaEM.alphaEM(pT2); | |
857 | wt *= (alphaEMnow / alphaEMmax); | |
858 | ||
859 | // Evaluation of new daughter and mother PDF's. | |
860 | double xPDFdaughterNew = max ( TINYPDF, | |
861 | beam.xfISR(iSysNow, idDaughter, xDaughter, pT2) ); | |
862 | double xPDFmotherNew = beam.xfISR(iSysNow, idMother, xMother, pT2); | |
863 | wt *= xPDFmotherNew / xPDFdaughterNew; | |
864 | ||
865 | // Iterate until acceptable pT (or have fallen below pTmin). | |
866 | } while (wt < Rndm::flat()) ; | |
867 | ||
868 | // Save values for (so far) acceptable branching. | |
869 | dipEndNow->store( idDaughter,idMother, 22, x1Now, x2Now, m2Dip, | |
870 | pT2, z, Q2, mSister, m2Sister, pT2corr, phi); | |
871 | ||
872 | } | |
873 | ||
874 | //********* | |
875 | ||
876 | // Kinematics of branching. | |
877 | // Construct mother -> daughter + sister, with recoiler on other side. | |
878 | ||
879 | bool SpaceShower::branch( Event& event) { | |
880 | ||
881 | // Side on which branching occured. | |
882 | int side = abs(dipEndSel->side); | |
883 | double sideSign = (side == 1) ? 1. : -1.; | |
884 | ||
885 | // Read in flavour and colour variables. | |
886 | int iDaughter = event.getInSystem( iSysSel, side - 1); | |
887 | int iRecoiler = event.getInSystem( iSysSel, 2 - side); | |
888 | int idDaughterNow = dipEndSel->idDaughter; | |
889 | int idMother = dipEndSel->idMother; | |
890 | int idSister = dipEndSel->idSister; | |
891 | int colDaughter = event[iDaughter].col(); | |
892 | int acolDaughter = event[iDaughter].acol(); | |
893 | ||
894 | // Read in kinematical variables. | |
895 | double x1 = dipEndSel->x1; | |
896 | double x2 = dipEndSel->x2; | |
897 | double m2 = dipEndSel->m2Dip; | |
898 | double m = sqrt(m2); | |
899 | double pT2 = dipEndSel->pT2; | |
900 | double z = dipEndSel->z; | |
901 | double Q2 = dipEndSel->Q2; | |
902 | double mSister = dipEndSel->mSister; | |
903 | double m2Sister = dipEndSel->m2Sister; | |
904 | double pT2corr = dipEndSel->pT2corr; | |
905 | double phi = dipEndSel->phi; | |
906 | ||
907 | // Take copy of existing system, to be given modified kinematics. | |
908 | int eventSizeOld = event.size(); | |
909 | int systemSizeOld = event.sizeSystem(iSysSel); | |
910 | for ( int iCopy = 0; iCopy < systemSizeOld; ++iCopy) { | |
911 | int iOldCopy = event.getInSystem( iSysSel, iCopy); | |
912 | int statusNew = (iOldCopy == iDaughter | |
913 | || iOldCopy == iRecoiler) ? event[iOldCopy].status() : 44; | |
914 | event.copy(iOldCopy, statusNew); | |
915 | } | |
916 | ||
917 | // Define colour flow in branching. | |
918 | // Default corresponds to f -> f + gamma. | |
919 | int colMother = colDaughter; | |
920 | int acolMother = acolDaughter; | |
921 | int colSister = 0; | |
922 | int acolSister = 0; | |
923 | if (idSister == 22) ; | |
924 | // q -> q + g and 50% of g -> g + g; need new colour. | |
925 | else if (idSister == 21 && ( (idMother > 0 && idMother < 9) | |
926 | || (idMother == 21 && Rndm::flat() < 0.5) ) ) { | |
927 | colMother = event.nextColTag(); | |
928 | colSister = colMother; | |
929 | acolSister = colDaughter; | |
930 | // qbar -> qbar + g and other 50% of g -> g + g; need new colour. | |
931 | } else if (idSister == 21) { | |
932 | acolMother = event.nextColTag(); | |
933 | acolSister = acolMother; | |
934 | colSister = acolDaughter; | |
935 | // q -> g + q. | |
936 | } else if (idDaughterNow == 21 && idMother > 0) { | |
937 | colMother = colDaughter; | |
938 | acolMother = 0; | |
939 | colSister = acolDaughter; | |
940 | // qbar -> g + qbar | |
941 | } else if (idDaughterNow == 21) { | |
942 | acolMother = acolDaughter; | |
943 | colMother = 0; | |
944 | acolSister = colDaughter; | |
945 | // g -> q + qbar. | |
946 | } else if (idDaughterNow > 0 && idDaughterNow < 9) { | |
947 | acolMother = event.nextColTag(); | |
948 | acolSister = acolMother; | |
949 | // g -> qbar + q. | |
950 | } else if (idDaughterNow < 0 && idDaughterNow > -9) { | |
951 | colMother = event.nextColTag(); | |
952 | colSister = colMother; | |
953 | // q -> gamma + q. | |
954 | } else if (idDaughterNow == 22 && idMother > 0) { | |
955 | colMother = event.nextColTag(); | |
956 | colSister = colMother; | |
957 | // qbar -> gamma + qbar. | |
958 | } else if (idDaughterNow == 22) { | |
959 | acolMother = event.nextColTag(); | |
960 | acolSister = acolMother; | |
961 | } | |
962 | ||
963 | // Construct kinematics of mother, sister and recoiler in old rest frame. | |
964 | double pTbranch = sqrt(pT2corr) * m2 / ( z * (m2 + Q2) ); | |
965 | double pzMother = sideSign * 0.5 * m * ( (m2 - Q2) / ( z * (m2 + Q2) ) | |
966 | + (Q2 + m2Sister) / m2 ); | |
967 | double eMother = sqrt( pow2(pTbranch) + pow2(pzMother) ); | |
968 | double pzSister = pzMother - sideSign * 0.5 * (m2 + Q2) / m; | |
969 | double eSister = sqrt( pow2(pTbranch) + pow2(pzSister) + m2Sister ); | |
970 | double eNewRecoiler = 0.5 * (m2 + Q2) / m; | |
971 | Vec4 pMother( pTbranch, 0., pzMother, eMother ); | |
972 | Vec4 pSister( pTbranch, 0., pzSister, eSister ); | |
973 | Vec4 pNewRecoiler( 0., 0., -sideSign * eNewRecoiler, eNewRecoiler); | |
974 | ||
975 | // Indices of partons involved. Add new sister. | |
976 | int iMother = eventSizeOld + side - 1; | |
977 | int iNewRecoiler = eventSizeOld + 2 - side; | |
978 | int iSister = event.append( idSister, 43, iMother, 0, 0, 0, | |
979 | colSister, acolSister, pSister, mSister, sqrt(pT2) ); | |
980 | ||
981 | // References to the partons involved. | |
982 | Particle& daughter = event[iDaughter]; | |
983 | Particle& mother = event[iMother]; | |
984 | Particle& newRecoiler = event[iNewRecoiler]; | |
985 | Particle& sister = event.back(); | |
986 | ||
987 | // Replace old by new mother; update new recoiler. | |
988 | mother.id( idMother ); | |
989 | mother.status( -41); | |
990 | mother.cols( colMother, acolMother); | |
991 | mother.p( pMother); | |
992 | newRecoiler.status( -42); | |
993 | newRecoiler.p( pNewRecoiler); | |
994 | ||
995 | // Update mother and daughter pointers; also for beams. | |
996 | daughter.mothers( iMother, 0); | |
997 | mother.daughters( iSister, iDaughter); | |
998 | if (iSysSel == 0) { | |
999 | event[1].daughter1( (side == 1) ? iMother : iNewRecoiler ); | |
1000 | event[2].daughter1( (side == 2) ? iMother : iNewRecoiler ); | |
1001 | } | |
1002 | ||
1003 | // Find boost to old rest frame, and rotation -phi. | |
1004 | RotBstMatrix Mtot; | |
1005 | Mtot.bst(0., 0., (x2 - x1) / (x1 + x2) ); | |
1006 | Mtot.rot(0., -phi); | |
1007 | ||
1008 | // Find boost from old rest frame to event cm frame. | |
1009 | RotBstMatrix MfromRest; | |
1010 | // The boost to the new rest frame. | |
1011 | Vec4 sumNew = pMother + pNewRecoiler; | |
1012 | double betaX = sumNew.px() / sumNew.e(); | |
1013 | double betaZ = sumNew.pz() / sumNew.e(); | |
1014 | MfromRest.bst( -betaX, 0., -betaZ); | |
1015 | // Alignment of radiator + recoiler to +- z axis, and rotation +phi. | |
1016 | pMother.rotbst(MfromRest); | |
1017 | double theta = pMother.theta(); | |
1018 | if (side == 2) theta += M_PI; | |
1019 | MfromRest.rot(-theta, phi); | |
1020 | // Longitudinal boost to radiator + recoiler in event cm frame. | |
1021 | double x1New = (side == 1) ? x1 / z : x1; | |
1022 | double x2New = (side == 2) ? x2 / z : x2; | |
1023 | MfromRest.bst(0., 0., (x1New - x2New) / (x1New + x2New) ); | |
1024 | Mtot.rotbst(MfromRest); | |
1025 | ||
1026 | // Perform cumulative rotation/boost operation. | |
1027 | // Mother, recoiler and sister from old rest frame to event cm frame. | |
1028 | mother.rotbst(MfromRest); | |
1029 | newRecoiler.rotbst(MfromRest); | |
1030 | sister.rotbst(MfromRest); | |
1031 | // The rest from (and to) event cm frame. | |
1032 | for ( int i = eventSizeOld + 2; i < eventSizeOld + systemSizeOld; ++i) | |
1033 | event[i].rotbst(Mtot); | |
1034 | ||
1035 | // Update list of partons in system; adding newly produced one. | |
1036 | for ( int iCopy = 0; iCopy < systemSizeOld; ++iCopy) | |
1037 | event.setInSystem( iSysSel, iCopy, eventSizeOld + iCopy); | |
1038 | event.addToSystem( iSysSel, eventSizeOld + systemSizeOld); | |
1039 | ||
1040 | // Update info on dipole ends (QCD or QED). | |
1041 | for (int iDip = 0; iDip < int(dipEnd.size()); ++iDip) | |
1042 | if ( dipEnd[iDip].system == iSysSel && abs(dipEnd[iDip].side) == side ) { | |
1043 | dipEnd[iDip].iRadiator = iMother; | |
1044 | dipEnd[iDip].iRecoiler = iNewRecoiler; | |
1045 | if (dipEnd[iDip].side > 0) | |
1046 | dipEnd[iDip].colType = mother.colType(); | |
1047 | else { | |
1048 | dipEnd[iDip].chgType = 0; | |
1049 | if ( (mother.isQuark() && doQEDshowerByQ) | |
1050 | || (mother.isLepton() && doQEDshowerByL) ) | |
1051 | dipEnd[iDip].chgType = mother.chargeType(); | |
1052 | } | |
1053 | // Kill ME corrections after first emission. | |
1054 | dipEnd[iDip].MEtype = 0; | |
1055 | } | |
1056 | ||
1057 | // Update info on beam remnants. | |
1058 | BeamParticle& beamNow = (side == 1) ? *beamAPtr : *beamBPtr; | |
1059 | double xNew = (side == 1) ? x1New : x2New; | |
1060 | beamNow[iSysSel].update( iMother, idMother, xNew); | |
1061 | // Redo choice of companion kind whenever new flavour. | |
1062 | if (idMother != idDaughterNow) { | |
1063 | beamNow.xfISR( iSysSel, idMother, xNew, pT2); | |
1064 | beamNow.pickValSeaComp(); | |
1065 | } | |
1066 | BeamParticle& beamRec = (side == 1) ? *beamBPtr : *beamAPtr; | |
1067 | beamRec[iSysSel].iPos( iNewRecoiler); | |
1068 | ||
1069 | // Store branching values of current dipole. (For rapidity ordering.) | |
1070 | ++dipEndSel->nBranch; | |
1071 | dipEndSel->pT2Old = pT2; | |
1072 | dipEndSel->zOld = z; | |
1073 | ||
1074 | ||
1075 | // Done without any errors. | |
1076 | return true; | |
1077 | ||
1078 | } | |
1079 | ||
1080 | //********* | |
1081 | ||
1082 | // Find class of ME correction. | |
1083 | ||
1084 | int SpaceShower::findMEtype( int iSys, Event& event) { | |
1085 | ||
1086 | // Default values and no action. | |
1087 | int MEtype = 0; | |
1088 | if (!doMEcorrections) ; | |
1089 | ||
1090 | // Identify systems producing a single resonance. | |
1091 | else if (event.sizeSystem( iSys) == 3) { | |
1092 | int idIn1 = event[event.getInSystem( iSys, 0)].id(); | |
1093 | int idIn2 = event[event.getInSystem( iSys, 1)].id(); | |
1094 | int idRes = event[event.getInSystem( iSys, 2)].id(); | |
1095 | ||
1096 | // f + fbar -> vector boson. | |
1097 | if ( (idRes == 23 || abs(idRes) == 24 || idRes == 32 | |
1098 | || idRes == 33 || abs(idRes) == 34 || abs(idRes) == 41) | |
1099 | && abs(idIn1) < 20 && abs(idIn2) < 20 ) MEtype = 1; | |
1100 | ||
1101 | // g + g, gamma + gamma -> Higgs boson. | |
1102 | if ( (idRes == 25 || idRes == 35 || idRes == 36) | |
1103 | && ( ( idIn1 == 21 && idIn2 == 21 ) | |
1104 | || ( idIn1 == 22 && idIn2 == 22 ) ) ) MEtype = 2; | |
1105 | ||
1106 | // f + fbar -> Higgs boson. | |
1107 | if ( (idRes == 25 || idRes == 35 || idRes == 36) | |
1108 | && abs(idIn1) < 20 && abs(idIn2) < 20 ) MEtype = 3; | |
1109 | } | |
1110 | ||
1111 | // Done. | |
1112 | return MEtype; | |
1113 | ||
1114 | } | |
1115 | ||
1116 | //********* | |
1117 | ||
1118 | // Provide maximum of expected ME weight; for preweighting of evolution. | |
1119 | ||
1120 | double SpaceShower::calcMEmax( int MEtype, int idMother, int idDaughterIn) { | |
1121 | ||
1122 | // Currently only one non-unity case: g(gamma) f -> V f'. | |
1123 | if (MEtype == 1 && idMother > 20 && idDaughterIn < 20) return 3.; | |
1124 | return 1.; | |
1125 | ||
1126 | } | |
1127 | ||
1128 | //********* | |
1129 | ||
1130 | // Provide actual ME weight for current branching. | |
1131 | // Note: currently ME corrections are only allowed for first branching | |
1132 | // on each side, so idDaughter is essentially known and checks overkill. | |
1133 | ||
1134 | double SpaceShower::calcMEcorr(int MEtype, int idMother, int idDaughterIn, | |
1135 | double M2, double z, double Q2) { | |
1136 | ||
1137 | // Convert to Mandelstam variables. Sometimes may need to swap later. | |
1138 | double sH = M2 / z; | |
1139 | double tH = -Q2; | |
1140 | double uH = Q2 - M2 * (1. - z) / z; | |
1141 | int idMabs = abs(idMother); | |
1142 | int idDabs = abs(idDaughterIn); | |
1143 | ||
1144 | // Corrections for f + fbar -> s-channel vector boson. | |
1145 | if (MEtype == 1) { | |
1146 | if (idMabs < 20 && idDabs < 20) { | |
1147 | return (tH*tH + uH*uH + 2. * M2 * sH) / (sH*sH + M2*M2); | |
1148 | } else if (idDabs < 20) { | |
1149 | // g(gamma) f -> V f': -Q2 = (p_g - p_f')^2 in PS while | |
1150 | // tHat = (p_f - p_f')^2 in ME so need to swap tHat <-> uHat. | |
1151 | swap( tH, uH); | |
1152 | return (sH*sH + uH*uH + 2. * M2 * tH) / (pow2(sH - M2) + M2*M2); | |
1153 | } | |
1154 | ||
1155 | // Corrections for g + g -> Higgs boson. | |
1156 | } else if (MEtype == 2) { | |
1157 | if (idMabs < 20 && idDabs > 20) { | |
1158 | return (sH*sH + uH*uH) / (sH*sH + pow2(sH - M2)); | |
1159 | } else if (idDabs > 20) { | |
1160 | return 0.5 * (pow4(sH) + pow4(tH) + pow4(uH) + pow4(M2)) | |
1161 | / pow2(sH*sH - M2 * (sH - M2)); | |
1162 | } | |
1163 | ||
1164 | // Corrections for f + fbar -> Higgs boson (f = b mainly). | |
1165 | } else if (MEtype == 3) { | |
1166 | if (idMabs < 20 && idDabs < 20) { | |
1167 | // The PS and ME answers agree for f fbar -> H g/gamma. | |
1168 | return 1.; | |
1169 | } else if (idDabs < 20) { | |
1170 | // Need to swap tHat <-> uHat, cf. vector-boson production above. | |
1171 | swap( tH, uH); | |
1172 | return (sH*sH + uH*uH + 2. * (M2 - uH) * (M2 - sH)) | |
1173 | / (pow2(sH - M2) + M2*M2); | |
1174 | } | |
1175 | } | |
1176 | ||
1177 | return 1.; | |
1178 | ||
1179 | } | |
1180 | ||
1181 | //********* | |
1182 | ||
1183 | // Print the list of dipoles. | |
1184 | ||
1185 | void SpaceShower::list(ostream& os) { | |
1186 | ||
1187 | // Header. | |
1188 | os << "\n -------- PYTHIA SpaceShower Dipole Listing ---------- \n" | |
1189 | << "\n i syst side rad rec pTmax col chg type \n" | |
1190 | << fixed << setprecision(3); | |
1191 | ||
1192 | // Loop over dipole list and print it. | |
1193 | for (int i = 0; i < int(dipEnd.size()); ++i) | |
1194 | os << setw(5) << i << setw(6) << dipEnd[i].system | |
1195 | << setw(6) << dipEnd[i].side << setw(6) << dipEnd[i].iRadiator | |
1196 | << setw(6) << dipEnd[i].iRecoiler << setw(12) << dipEnd[i].pTmax | |
1197 | << setw(5) << dipEnd[i].colType << setw(5) << dipEnd[i].chgType | |
1198 | << setw(5) << dipEnd[i].MEtype << "\n"; | |
1199 | ||
1200 | // Done. | |
1201 | os << "\n -------- End PYTHIA SpaceShower Dipole Listing ------" | |
1202 | << endl; | |
1203 | ||
1204 | ||
1205 | } | |
1206 | ||
1207 | //************************************************************************** | |
1208 | ||
1209 | } // end namespace Pythia8 |