Line data Source code
1 : // PartonLevel.cc is a part of the PYTHIA event generator.
2 : // Copyright (C) 2015 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 : // Hard diffraction added by Christine Rasmussen.
6 :
7 : // Function definitions (not found in the header) for the PartonLevel class.
8 :
9 : #include "Pythia8/PartonLevel.h"
10 :
11 : namespace Pythia8 {
12 :
13 : //==========================================================================
14 :
15 : // The PartonLevel 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 : // Maximum number of tries to produce parton level from given input.
23 : const int PartonLevel::NTRY = 10;
24 :
25 : //--------------------------------------------------------------------------
26 :
27 : // Main routine to initialize the parton-level generation process.
28 :
29 : bool PartonLevel::init( Info* infoPtrIn, Settings& settings,
30 : ParticleData* particleDataPtrIn, Rndm* rndmPtrIn,
31 : BeamParticle* beamAPtrIn, BeamParticle* beamBPtrIn,
32 : BeamParticle* beamPomAPtrIn, BeamParticle* beamPomBPtrIn,
33 : Couplings* couplingsPtrIn, PartonSystems* partonSystemsPtrIn,
34 : SigmaTotal* sigmaTotPtr, TimeShower* timesDecPtrIn, TimeShower* timesPtrIn,
35 : SpaceShower* spacePtrIn, RHadrons* rHadronsPtrIn, UserHooks* userHooksPtrIn,
36 : MergingHooks* mergingHooksPtrIn, bool useAsTrial ) {
37 :
38 : // Store input pointers and modes for future use.
39 0 : infoPtr = infoPtrIn;
40 0 : particleDataPtr = particleDataPtrIn;
41 0 : rndmPtr = rndmPtrIn;
42 0 : beamAPtr = beamAPtrIn;
43 0 : beamBPtr = beamBPtrIn;
44 0 : beamHadAPtr = beamAPtr;
45 0 : beamHadBPtr = beamBPtr;
46 0 : beamPomAPtr = beamPomAPtrIn;
47 0 : beamPomBPtr = beamPomBPtrIn;
48 0 : couplingsPtr = couplingsPtrIn;
49 0 : partonSystemsPtr = partonSystemsPtrIn;
50 0 : timesDecPtr = timesDecPtrIn;
51 0 : timesPtr = timesPtrIn;
52 0 : spacePtr = spacePtrIn;
53 0 : rHadronsPtr = rHadronsPtrIn;
54 0 : userHooksPtr = userHooksPtrIn;
55 0 : mergingHooksPtr = mergingHooksPtrIn;
56 :
57 : // Min bias and diffraction processes need special treatment.
58 0 : bool doSQ = settings.flag("SoftQCD:all")
59 0 : || settings.flag("SoftQCD:inelastic");
60 0 : bool doND = settings.flag("SoftQCD:nonDiffractive");
61 0 : bool doSD = settings.flag("SoftQCD:singleDiffractive");
62 0 : bool doDD = settings.flag("SoftQCD:doubleDiffractive");
63 0 : bool doCD = settings.flag("SoftQCD:centralDiffractive");
64 0 : doNonDiff = doSQ || doND;
65 0 : doDiffraction = doSQ || doSD || doDD || doCD;
66 0 : doHardDiff = settings.flag("Diffraction:doHard");
67 0 : sampleTypeDiff = (doHardDiff) ? settings.mode("Diffraction:sampleType")
68 : : 0;
69 :
70 : // Separate low-mass (unresolved) and high-mass (perturbative) diffraction.
71 0 : mMinDiff = settings.parm("Diffraction:mMinPert");
72 0 : mWidthDiff = settings.parm("Diffraction:mWidthPert");
73 0 : pMaxDiff = settings.parm("Diffraction:probMaxPert");
74 0 : if (mMinDiff > infoPtr->eCM()) doDiffraction = false;
75 :
76 : // Need MPI initialization for soft QCD processes, even if only first MPI.
77 : // But no need to initialize MPI if never going to use it.
78 0 : doMPI = settings.flag("PartonLevel:MPI");
79 0 : doMPIMB = doMPI;
80 0 : doMPISDA = doMPI;
81 0 : doMPISDB = doMPI;
82 0 : doMPICD = doMPI;
83 0 : doMPIinit = doMPI;
84 0 : if (doNonDiff || doDiffraction) doMPIinit = true;
85 0 : if (!settings.flag("PartonLevel:all")) doMPIinit = false;
86 :
87 : // Initialise trial shower switch.
88 0 : doTrial = useAsTrial;
89 : // Merging initialization.
90 0 : bool hasMergingHooks = (mergingHooksPtr != 0);
91 0 : canRemoveEvent = !doTrial && hasMergingHooks
92 0 : && ( mergingHooksPtr->doCKKWLMerging() || mergingHooksPtr->doNL3Merging());
93 0 : canRemoveEmission = !doTrial && hasMergingHooks
94 0 : && ( mergingHooksPtr->doUMEPSMerging() || mergingHooksPtr->doNL3Merging()
95 0 : || mergingHooksPtr->doUNLOPSMerging() );
96 0 : nTrialEmissions = 1;
97 0 : pTLastBranch = 0.0;
98 0 : typeLastBranch = 0;
99 :
100 : // Flags for showers: ISR and FSR.
101 0 : doISR = settings.flag("PartonLevel:ISR");
102 0 : bool FSR = settings.flag("PartonLevel:FSR");
103 0 : bool FSRinProcess = settings.flag("PartonLevel:FSRinProcess");
104 0 : bool interleaveFSR = settings.flag("TimeShower:interleave");
105 0 : doFSRduringProcess = FSR && FSRinProcess && interleaveFSR;
106 0 : doFSRafterProcess = FSR && FSRinProcess && !interleaveFSR;
107 0 : doFSRinResonances = FSR && settings.flag("PartonLevel:FSRinResonances");
108 :
109 : // Flags for colour reconnection.
110 0 : doReconnect = settings.flag("ColourReconnection:reconnect");
111 0 : reconnectMode = settings.mode("ColourReconnection:mode");
112 0 : forceResonanceCR = settings.flag("ColourReconnection:forceResonance");
113 :
114 : // Some other flags.
115 0 : doRemnants = settings.flag("PartonLevel:Remnants");
116 0 : doSecondHard = settings.flag("SecondHard:generate");
117 0 : earlyResDec = settings.flag("PartonLevel:earlyResDec");
118 :
119 : // Allow R-hadron formation.
120 0 : allowRH = settings.flag("RHadrons:allow");
121 :
122 : // Possibility to allow user veto during evolution.
123 0 : canVetoPT = (userHooksPtr != 0)
124 0 : ? userHooksPtr->canVetoPT() : false;
125 0 : pTvetoPT = (canVetoPT)
126 0 : ? userHooksPtr->scaleVetoPT() : -1.;
127 0 : canVetoStep = (userHooksPtr != 0)
128 0 : ? userHooksPtr->canVetoStep() : false;
129 0 : nVetoStep = (canVetoStep)
130 0 : ? userHooksPtr->numberVetoStep() : -1;
131 0 : canVetoMPIStep = (userHooksPtr != 0)
132 0 : ? userHooksPtr->canVetoMPIStep() : false;
133 0 : nVetoMPIStep = (canVetoMPIStep)
134 0 : ? userHooksPtr->numberVetoMPIStep() : -1;
135 0 : canVetoEarly = (userHooksPtr != 0)
136 0 : ? userHooksPtr->canVetoPartonLevelEarly() : false;
137 :
138 : // Settings for vetoing of QCD emission for Drell-Yan weak boson production.
139 0 : vetoWeakJets = settings.flag("WeakShower:vetoQCDjets");
140 0 : vetoWeakDeltaR2 = pow2(settings.parm("WeakShower:vetoWeakDeltaR"));
141 :
142 : // Possibility to set maximal shower scale in resonance decays.
143 0 : canSetScale = (userHooksPtr != 0)
144 0 : ? userHooksPtr->canSetResonanceScale() : false;
145 :
146 : // Possibility to reconnect specifically for resonance decays.
147 0 : canReconResSys = (userHooksPtr != 0)
148 0 : ? userHooksPtr->canReconnectResonanceSystems() : false;
149 :
150 : // Done with initialization only for FSR in resonance decays.
151 0 : if (beamAPtr == 0 || beamBPtr == 0) return true;
152 :
153 : // Flag if lepton beams, and if non-resolved ones. May change main flags.
154 0 : hasTwoLeptonBeams = beamAPtr->isLepton() && beamBPtr->isLepton();
155 0 : hasOneLeptonBeam = (beamAPtr->isLepton() || beamBPtr->isLepton())
156 0 : && !hasTwoLeptonBeams;
157 0 : hasPointLeptons = (hasOneLeptonBeam || hasTwoLeptonBeams)
158 0 : && (beamAPtr->isUnresolved() || beamBPtr->isUnresolved());
159 0 : if (hasOneLeptonBeam || hasTwoLeptonBeams) {
160 0 : doMPIMB = false;
161 0 : doMPISDA = false;
162 0 : doMPISDB = false;
163 0 : doMPICD = false;
164 0 : doMPIinit = false;
165 0 : }
166 0 : if (hasTwoLeptonBeams && hasPointLeptons) {
167 0 : doISR = false;
168 0 : doRemnants = false;
169 0 : }
170 :
171 : // Set info and initialize the respective program elements.
172 0 : timesPtr->init( beamAPtr, beamBPtr);
173 0 : if (doISR) spacePtr->init( beamAPtr, beamBPtr);
174 0 : doMPIMB = multiMB.init( doMPIinit, 0, infoPtr, settings, particleDataPtr,
175 0 : rndmPtr, beamAPtr, beamBPtr, couplingsPtr, partonSystemsPtr, sigmaTotPtr,
176 0 : userHooksPtr);
177 0 : if (doSD || doDD || doSQ || doHardDiff) doMPISDA = multiSDA.init( doMPIinit,
178 0 : 1, infoPtr, settings, particleDataPtr, rndmPtr, beamAPtr, beamPomBPtr,
179 0 : couplingsPtr, partonSystemsPtr, sigmaTotPtr, userHooksPtr);
180 0 : if (doSD || doDD || doSQ || doHardDiff) doMPISDB = multiSDB.init( doMPIinit,
181 0 : 2, infoPtr, settings, particleDataPtr, rndmPtr, beamPomAPtr, beamBPtr,
182 0 : couplingsPtr, partonSystemsPtr, sigmaTotPtr, userHooksPtr);
183 0 : if (doCD || doSQ) doMPICD = multiCD.init( doMPIinit, 3, infoPtr, settings,
184 0 : particleDataPtr, rndmPtr, beamPomAPtr, beamPomBPtr, couplingsPtr,
185 0 : partonSystemsPtr, sigmaTotPtr, userHooksPtr);
186 0 : if (!remnants.init( infoPtr, settings, rndmPtr, beamAPtr, beamBPtr,
187 0 : partonSystemsPtr, particleDataPtr, &colourReconnection)) return false;
188 0 : resonanceDecays.init( infoPtr, particleDataPtr, rndmPtr);
189 0 : colourReconnection.init( infoPtr, settings, rndmPtr, particleDataPtr,
190 0 : beamAPtr, beamBPtr, partonSystemsPtr);
191 0 : junctionSplitting.init(infoPtr, settings, rndmPtr, particleDataPtr);
192 0 : if (doHardDiff) hardDiffraction.init(infoPtr, settings, rndmPtr, beamAPtr,
193 0 : beamBPtr, beamPomAPtr, beamPomBPtr);
194 :
195 : // Succeeded, or not.
196 0 : multiPtr = &multiMB;
197 0 : if (doMPIinit && !doMPIMB) return false;
198 0 : if (doMPIinit && (doSD || doDD || doSQ) && (!doMPISDA || !doMPISDB))
199 0 : return false;
200 0 : if (doMPIinit && (doCD || doSQ) && !doMPICD) return false;
201 0 : if (!doMPIMB || !doMPISDA || !doMPISDB || !doMPICD) doMPI = false;
202 0 : return true;
203 :
204 0 : }
205 :
206 : //--------------------------------------------------------------------------
207 :
208 : // Function to reset PartonLevel object for trial shower usage.
209 :
210 : void PartonLevel::resetTrial() {
211 :
212 : // Clear input pointers.
213 0 : partonSystemsPtr->clear();
214 0 : beamAPtr->clear();
215 0 : beamBPtr->clear();
216 0 : beamHadAPtr->clear();
217 0 : beamHadBPtr->clear();
218 0 : beamPomAPtr->clear();
219 0 : beamPomBPtr->clear();
220 :
221 : // Clear last branching return values.
222 0 : pTLastBranch = 0.0;
223 0 : typeLastBranch = 0;
224 :
225 0 : }
226 :
227 : //--------------------------------------------------------------------------
228 :
229 : // Main routine to do the parton-level evolution.
230 :
231 : bool PartonLevel::next( Event& process, Event& event) {
232 :
233 : // Current event classification.
234 0 : isResolved = infoPtr->isResolved();
235 0 : isResolvedA = isResolved;
236 0 : isResolvedB = isResolved;
237 0 : isResolvedC = isResolved;
238 0 : isDiffA = infoPtr->isDiffractiveA();
239 0 : isDiffB = infoPtr->isDiffractiveB();
240 0 : isDiffC = infoPtr->isDiffractiveC();
241 0 : isDiff = isDiffA || isDiffB || isDiffC;
242 0 : isCentralDiff = isDiffC;
243 0 : isDoubleDiff = isDiffA && isDiffB;
244 0 : isSingleDiff = isDiff && !isDoubleDiff && !isCentralDiff;
245 0 : isNonDiff = infoPtr->isNonDiffractive();
246 :
247 : // Default values for what is to come.
248 0 : isHardDiffA = false;
249 0 : isHardDiffB = false;
250 0 : isHardDiff = false;
251 0 : doDiffVeto = false;
252 0 : isSetupDiff = false;
253 :
254 : // The setup of the diffractive events can come after the first evolution.
255 0 : doVeto = false;
256 : int nHardDiffLoop = 1;
257 0 : infoPtr->setAbortPartonLevel(false);
258 :
259 : // Mark hard diffractive events to handle CR correctly.
260 : bool doDiffCR = false;
261 :
262 : // Prepare for a potential hard diffractive event.
263 0 : if (doHardDiff) {
264 :
265 : // Preliminary decision based on diffractive-to-inclusive PDF ratio.
266 : // If Pomeron taken from side A(=1), then B is the diffractive system
267 : // If Pomeron taken from side B(=2), then A is the diffractive system
268 0 : isHardDiffA = hardDiffraction.isDiffractive(2, infoPtr->id2pdf(),
269 0 : infoPtr->x2pdf(), infoPtr->Q2Fac(), infoPtr->pdf2());
270 0 : isHardDiffB = hardDiffraction.isDiffractive(1, infoPtr->id1pdf(),
271 0 : infoPtr->x1pdf(), infoPtr->Q2Fac(), infoPtr->pdf1());
272 :
273 : // No hard double diffraction yet, so randomly choose one of the sides.
274 0 : if (isHardDiffA && isHardDiffB) {
275 0 : if (rndmPtr-> flat() < 0.5) isHardDiffA = false;
276 0 : else isHardDiffB = false;
277 : }
278 0 : isHardDiff = isHardDiffA || isHardDiffB;
279 :
280 : // Save diffractive values.
281 0 : double xPomA = (isHardDiffB) ? hardDiffraction.getXPomeronA() : 0.;
282 0 : double xPomB = (isHardDiffA) ? hardDiffraction.getXPomeronB() : 0.;
283 0 : double tPomA = (isHardDiffB) ? hardDiffraction.getTPomeronA() : 0.;
284 0 : double tPomB = (isHardDiffA) ? hardDiffraction.getTPomeronB() : 0.;
285 0 : infoPtr->setHardDiff( false, isHardDiffA, isHardDiffB,
286 : xPomA, xPomB, tPomA, tPomB);
287 :
288 : // Discard all nondiffractive events if only diffractive sample is wanted.
289 0 : if (!isHardDiff && (sampleTypeDiff == 3 || sampleTypeDiff == 4)) {
290 0 : doDiffVeto = true;
291 0 : return false;
292 : }
293 :
294 0 : if (isHardDiff) {
295 : // Discard all diffractive events if only want nondiffractive sample.
296 0 : if (sampleTypeDiff == 5) {
297 0 : infoPtr->setHardDiff( false, false, false, 0., 0., 0., 0.);
298 0 : doDiffVeto = true;
299 0 : return false;
300 : }
301 :
302 : // Set up the diffractive system if run without MPI veto.
303 0 : else if (sampleTypeDiff == 1 || sampleTypeDiff == 3)
304 0 : setupHardDiff( process);
305 :
306 : // Allow for second loop if run with MPI veto.
307 : else nHardDiffLoop = 2;
308 : }
309 0 : }
310 :
311 : // nHardLoop counts how many hard-scattering subsystems are to be processed.
312 : // Almost always 1, but elastic and low-mass diffraction gives 0, while
313 : // double diffraction can give up to 2. Not to be confused with SecondHard.
314 : int nHardLoop = 1;
315 0 : if (!isResolved) nHardLoop = (isDiff) ? decideResolvedDiff( process) : 0;
316 :
317 : // Handle unresolved subsystems. Done if no resolved ones.
318 0 : sizeProcess = 0;
319 0 : sizeEvent = 0;
320 0 : if (!isResolvedA || !isResolvedB || !isResolvedC) {
321 0 : bool physical = setupUnresolvedSys( process, event);
322 0 : if (!physical || nHardLoop == 0) return physical;
323 0 : sizeProcess = process.size();
324 0 : sizeEvent = event.size();
325 0 : }
326 :
327 : // Number of actual branchings.
328 : int nBranch = 0;
329 : // Number of desired branchings, negative value means no restriction.
330 0 : int nBranchMax = (doTrial) ? nTrialEmissions : -1;
331 :
332 : // Store merging weight.
333 0 : bool hasMergingHooks = (mergingHooksPtr != 0);
334 0 : if ( hasMergingHooks && canRemoveEvent )
335 0 : mergingHooksPtr->storeWeights(infoPtr->getWeightCKKWL());
336 :
337 : // Loop to set up diffractive system if run with MPI veto.
338 0 : for (int iHardDiffLoop = 1; iHardDiffLoop <= nHardDiffLoop;
339 0 : ++iHardDiffLoop) {
340 :
341 : // Big outer loop to handle up to two systems (in double diffraction),
342 : // but normally one. (Not indented in following, but end clearly marked.)
343 0 : for (int iHardLoop = 1; iHardLoop <= nHardLoop; ++iHardLoop) {
344 0 : infoPtr->setCounter(20, iHardLoop);
345 0 : infoPtr->setCounter(21);
346 :
347 : // Classification of diffractive system: 1 = A, 2 = B, 3 = central.
348 0 : iDS = 0;
349 0 : if (isDiffA || isDiffB) iDS = (iHardLoop == 2 || !isResolvedA) ? 2 : 1;
350 0 : if (isDiffC) iDS = 3;
351 :
352 : // Process and event records can be out of step for diffraction.
353 0 : if (iHardLoop == 2) {
354 0 : sizeProcess = process.size();
355 0 : sizeEvent = event.size();
356 0 : partonSystemsPtr->clear();
357 0 : if (event.lastColTag() > process.lastColTag())
358 0 : process.initColTag(event.lastColTag());
359 : }
360 :
361 : // If you need to restore then do not throw existing diffractive system.
362 0 : if (isDiff) {
363 0 : event.saveSize();
364 0 : event.saveJunctionSize();
365 :
366 : // Allow special treatment of diffractive systems.
367 0 : setupResolvedDiff( process);
368 0 : }
369 :
370 : // Prepare to do multiparton interactions; at new mass for diffraction.
371 0 : if (doMPIinit) multiPtr->reset();
372 :
373 : // Special case if nondiffractive: do hardest interaction.
374 0 : if (isNonDiff || isDiff) {
375 0 : multiPtr->pTfirst();
376 0 : multiPtr->setupFirstSys( process);
377 0 : }
378 :
379 : // Allow up to ten tries; failure possible for beam remnants.
380 : // Main cause: inconsistent colour flow at the end of the day.
381 : bool physical = true;
382 : int nRad = 0;
383 0 : for (int iTry = 0; iTry < NTRY; ++ iTry) {
384 0 : infoPtr->addCounter(21);
385 0 : for (int i = 22; i < 32; ++i) infoPtr->setCounter(i);
386 :
387 : // Reset flag, counters and max scales.
388 : physical = true;
389 0 : nMPI = (doSecondHard) ? 2 : 1;
390 0 : nISR = 0;
391 0 : nFSRinProc = 0;
392 0 : nFSRinRes = 0;
393 0 : nISRhard = 0;
394 0 : nFSRhard = 0;
395 0 : pTsaveMPI = 0.;
396 0 : pTsaveISR = 0.;
397 0 : pTsaveFSR = 0.;
398 :
399 : // Identify hard interaction system for showers.
400 0 : setupHardSys( process, event);
401 :
402 : // Optionally check for a veto after the hardest interaction.
403 0 : if (canVetoMPIStep) {
404 0 : doVeto = userHooksPtr->doVetoMPIStep( 1, event);
405 : // Abort event if vetoed.
406 0 : if (doVeto) {
407 0 : if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
408 0 : return false;
409 : }
410 : }
411 :
412 : // Check matching of process scale to maximum ISR/FSR/MPI scales.
413 0 : double Q2Fac = infoPtr->Q2Fac();
414 0 : double Q2Ren = infoPtr->Q2Ren();
415 0 : bool limitPTmaxISR = (doISR)
416 0 : ? spacePtr->limitPTmax( event, Q2Fac, Q2Ren) : false;
417 0 : bool limitPTmaxFSR = (doFSRduringProcess)
418 0 : ? timesPtr->limitPTmax( event, Q2Fac, Q2Ren) : false;
419 0 : bool limitPTmaxMPI = (doMPI) ? multiPtr->limitPTmax( event) : false;
420 :
421 : // Global recoil: reset counters and store locations of outgoing partons.
422 0 : timesPtr->prepareGlobal( event);
423 : bool isFirstTrial = true;
424 :
425 : // Set hard scale, maximum for showers and multiparton interactions.
426 0 : double pTscaleRad = process.scale();
427 0 : double pTscaleMPI = pTscaleRad;
428 0 : if (doSecondHard) {
429 0 : pTscaleRad = max( pTscaleRad, process.scaleSecond() );
430 0 : pTscaleMPI = min( pTscaleMPI, process.scaleSecond() );
431 0 : }
432 0 : double pTmaxMPI = (limitPTmaxMPI) ? pTscaleMPI : infoPtr->eCM();
433 0 : double pTmaxISR = (limitPTmaxISR) ? spacePtr->enhancePTmax() * pTscaleRad
434 0 : : infoPtr->eCM();
435 0 : double pTmaxFSR = (limitPTmaxFSR) ? timesPtr->enhancePTmax() * pTscaleRad
436 0 : : infoPtr->eCM();
437 :
438 : // Potentially reset up starting scales for matrix element merging.
439 0 : if ( hasMergingHooks && (doTrial || canRemoveEvent || canRemoveEmission) )
440 0 : mergingHooksPtr->setShowerStartingScales( doTrial,
441 0 : (canRemoveEvent || canRemoveEmission), pTscaleRad, process, pTmaxFSR,
442 : limitPTmaxFSR, pTmaxISR, limitPTmaxISR, pTmaxMPI, limitPTmaxMPI );
443 0 : double pTmax = max( pTmaxMPI, max( pTmaxISR, pTmaxFSR) );
444 0 : pTsaveMPI = pTmaxMPI;
445 0 : pTsaveISR = pTmaxISR;
446 0 : pTsaveFSR = pTmaxFSR;
447 :
448 : // Prepare the classes to begin the generation.
449 0 : if (doMPI) multiPtr->prepare( event, pTmaxMPI);
450 0 : if (doISR) spacePtr->prepare( 0, event, limitPTmaxISR);
451 0 : if (doFSRduringProcess) timesPtr->prepare( 0, event, limitPTmaxFSR);
452 0 : if (doSecondHard && doISR) spacePtr->prepare( 1, event, limitPTmaxISR);
453 0 : if (doSecondHard && doFSRduringProcess) timesPtr->prepare( 1, event,
454 0 : limitPTmaxFSR);
455 :
456 : // Impact parameter has now been chosen, except for diffraction.
457 0 : if (!isDiff) infoPtr->setImpact( multiPtr->bMPI(),
458 0 : multiPtr->enhanceMPI(), true);
459 : // Set up initial veto scale.
460 0 : doVeto = false;
461 0 : double pTveto = pTvetoPT;
462 0 : typeLatest = 0;
463 :
464 : // Begin evolution down in pT from hard pT scale.
465 0 : do {
466 0 : infoPtr->addCounter(22);
467 0 : typeVetoStep = 0;
468 0 : nRad = nISR + nFSRinProc;
469 :
470 : // Find next pT value for FSR, MPI and ISR.
471 : // Order calls to minimize time expenditure.
472 0 : double pTgen = 0.;
473 0 : double pTtimes = (doFSRduringProcess)
474 0 : ? timesPtr->pTnext( event, pTmaxFSR, pTgen, isFirstTrial) : -1.;
475 0 : pTgen = max( pTgen, pTtimes);
476 0 : double pTmulti = (doMPI)
477 0 : ? multiPtr->pTnext( pTmaxMPI, pTgen, event) : -1.;
478 0 : pTgen = max( pTgen, pTmulti);
479 0 : double pTspace = (doISR)
480 0 : ? spacePtr->pTnext( event, pTmaxISR, pTgen, nRad) : -1.;
481 0 : double pTnow = max( pTtimes, max( pTmulti, pTspace));
482 :
483 : // Update information.
484 0 : infoPtr->setPTnow( pTnow);
485 : isFirstTrial = false;
486 :
487 : // Allow a user veto. Only do it once, so remember to change pTveto.
488 0 : if (pTveto > 0. && pTveto > pTnow) {
489 : pTveto = -1.;
490 0 : doVeto = userHooksPtr->doVetoPT( typeLatest, event);
491 : // Abort event if vetoed.
492 0 : if (doVeto) {
493 0 : if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
494 0 : return false;
495 : }
496 : }
497 :
498 : // Do a multiparton interaction (if allowed).
499 0 : if (pTmulti > 0. && pTmulti > pTspace && pTmulti > pTtimes) {
500 0 : infoPtr->addCounter(23);
501 0 : if (multiPtr->scatter( event)) {
502 0 : typeLatest = 1;
503 0 : ++nMPI;
504 0 : if (canVetoMPIStep && nMPI <= nVetoMPIStep) typeVetoStep = 1;
505 :
506 : // Break for exclusive hard diffraction with MPI veto.
507 0 : if (isHardDiff && sampleTypeDiff == 4 && iHardDiffLoop == 1) {
508 0 : infoPtr->setHardDiff( false, false, false, 0., 0., 0., 0.);
509 0 : doDiffVeto = true;
510 0 : return false;
511 : }
512 :
513 : // Update ISR and FSR dipoles.
514 0 : if (doISR) spacePtr->prepare( nMPI - 1, event);
515 0 : if (doFSRduringProcess) timesPtr->prepare( nMPI - 1, event);
516 : }
517 :
518 : // Set maximal scales for next pT to pick.
519 0 : pTmaxMPI = pTmulti;
520 0 : pTmaxISR = min(pTmulti, pTmaxISR);
521 0 : pTmaxFSR = min(pTmulti, pTmaxFSR);
522 0 : pTmax = pTmulti;
523 0 : nBranch++;
524 0 : pTLastBranch = pTmulti;
525 0 : typeLastBranch = 1;
526 0 : }
527 :
528 : // Do an initial-state emission (if allowed).
529 0 : else if (pTspace > 0. && pTspace > pTtimes) {
530 0 : infoPtr->addCounter(24);
531 0 : if (spacePtr->branch( event)) {
532 0 : typeLatest = 2;
533 0 : iSysNow = spacePtr->system();
534 0 : ++nISR;
535 0 : if (iSysNow == 0) ++nISRhard;
536 0 : if (canVetoStep && iSysNow == 0 && nISRhard <= nVetoStep)
537 0 : typeVetoStep = 2;
538 :
539 : // Update FSR dipoles.
540 0 : if (doFSRduringProcess) timesPtr->update( iSysNow, event,
541 0 : spacePtr->getHasWeaklyRadiated());
542 0 : nBranch++;
543 0 : pTLastBranch = pTspace;
544 0 : typeLastBranch = 2;
545 :
546 : // Rescatter: it is possible for kinematics to fail, in which
547 : // case we need to restart the parton level processing.
548 0 : } else if (spacePtr->doRestart()) {
549 : physical = false;
550 0 : break;
551 : }
552 :
553 : // Set maximal scales for next pT to pick.
554 0 : pTmaxMPI = min(pTspace, pTmaxMPI);
555 0 : pTmaxISR = pTspace;
556 0 : pTmaxFSR = min(pTspace, pTmaxFSR);
557 0 : pTmax = pTspace;
558 0 : }
559 :
560 : // Do a final-state emission (if allowed).
561 0 : else if (pTtimes > 0.) {
562 0 : infoPtr->addCounter(25);
563 0 : if (timesPtr->branch( event, true)) {
564 0 : typeLatest = 3;
565 0 : iSysNow = timesPtr->system();
566 0 : ++nFSRinProc;
567 0 : if (iSysNow == 0) ++nFSRhard;
568 0 : if (canVetoStep && iSysNow == 0 && nFSRhard <= nVetoStep)
569 0 : typeVetoStep = 3;
570 :
571 : // Update ISR dipoles.
572 0 : if (doISR) spacePtr->update( iSysNow, event,
573 0 : timesPtr->getHasWeaklyRadiated());
574 0 : nBranch++;
575 0 : pTLastBranch = pTtimes;
576 0 : typeLastBranch = 3;
577 :
578 0 : }
579 :
580 : // Set maximal scales for next pT to pick.
581 0 : pTmaxMPI = min(pTtimes, pTmaxMPI);
582 0 : pTmaxISR = min(pTtimes, pTmaxISR);
583 0 : pTmaxFSR = pTtimes;
584 0 : pTmax = pTtimes;
585 0 : }
586 :
587 : // If no pT scales above zero then nothing to be done.
588 : else pTmax = 0.;
589 :
590 : // Check for double counting for Drell-Yan weak production.
591 : // Only look at the second emission.
592 0 : if ( (infoPtr->code() == 221 || infoPtr->code() == 222) &&
593 0 : nISRhard + nFSRhard == 2 && vetoWeakJets) {
594 0 : int id1 = event[partonSystemsPtr->getOut(0,0)].id();
595 0 : int id2 = event[partonSystemsPtr->getOut(0,1)].id();
596 0 : int id3 = event[partonSystemsPtr->getOut(0,2)].id();
597 0 : Vec4 p1 = event[partonSystemsPtr->getOut(0,0)].p();
598 0 : Vec4 p2 = event[partonSystemsPtr->getOut(0,1)].p();
599 0 : Vec4 p3 = event[partonSystemsPtr->getOut(0,2)].p();
600 :
601 : // Make sure id1 is weak boson, and check that there
602 : // only is a single weak boson and no photons.
603 : bool doubleCountEvent = true;
604 0 : if (abs(id1) == 24 || abs(id1) == 23) {
605 0 : if (abs(id2) > 21 || abs(id3) > 21)
606 0 : doubleCountEvent = false;
607 0 : } else if (abs(id2) == 24 || abs(id2) == 23) {
608 0 : swap(id1,id2);
609 0 : swap(p1,p2);
610 0 : if (abs(id3) > 21)
611 0 : doubleCountEvent = false;
612 0 : } else if ( abs(id3) == 24 || abs(id3) == 23) {
613 0 : swap(id1,id3);
614 0 : swap(p1,p3);
615 0 : }
616 :
617 0 : if (doubleCountEvent) {
618 0 : double d = p1.pT2();
619 : bool cut = true;
620 0 : if (p2.pT2() < d) {d = p2.pT2(); cut = false;}
621 0 : if (p3.pT2() < d) {d = p3.pT2(); cut = false;}
622 :
623 : // Check for angle between weak boson and quarks.
624 : // (require final state particle to be a fermion)
625 0 : if (abs(id2) < 20) {
626 0 : double dij = min(p1.pT2(),p2.pT2())
627 0 : * pow2(RRapPhi(p1,p2)) / vetoWeakDeltaR2;
628 0 : if (dij < d) {
629 : d = dij;
630 : cut = true;
631 0 : }
632 0 : }
633 :
634 0 : if (abs(id3) < 20) {
635 0 : double dij = min(p1.pT2(),p3.pT2())
636 0 : * pow2(RRapPhi(p1,p3)) / vetoWeakDeltaR2;
637 0 : if (dij < d) {
638 : d = dij;
639 : cut = true;
640 0 : }
641 0 : }
642 :
643 : // Check for angle between recoiler and radiator,
644 : // if it is a quark anti-quark pair
645 : // or if the recoiler is a gluon.
646 0 : if (abs(id2) == 21 || abs(id3) == 21 || id2 == - id3) {
647 0 : double dij = min(p2.pT2(),p3.pT2())
648 0 : * pow2(RRapPhi(p2,p3)) / vetoWeakDeltaR2;
649 0 : if (dij < d) {
650 : d = dij;
651 : cut = false;
652 0 : }
653 0 : }
654 :
655 : // Veto event if it does not belong to Drell-Yan production.
656 0 : if (cut) return false;
657 0 : }
658 0 : }
659 :
660 : // Optionally check for a veto after the first few interactions,
661 : // or after the first few emissions, ISR or FSR, in the hardest system.
662 0 : if (typeVetoStep == 1) {
663 0 : doVeto = userHooksPtr->doVetoMPIStep( nMPI, event);
664 0 : } else if (typeVetoStep > 1) {
665 0 : doVeto = userHooksPtr->doVetoStep( typeVetoStep, nISRhard,
666 0 : nFSRhard, event);
667 0 : }
668 :
669 : // Abort event if vetoed.
670 0 : if (doVeto) {
671 0 : if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
672 0 : return false;
673 : }
674 :
675 : // Keep on evolving until nothing is left to be done.
676 0 : if (typeLatest > 0 && typeLatest < 4)
677 0 : infoPtr->addCounter(25 + typeLatest);
678 0 : if (!isDiff) infoPtr->setPartEvolved( nMPI, nISR);
679 :
680 : // Handle potential merging veto.
681 0 : if ( canRemoveEvent && nISRhard + nFSRhard == 1 ){
682 : // Simply check, and possibly reset weights.
683 0 : mergingHooksPtr->doVetoStep( process, event );
684 0 : }
685 :
686 : // End loop evolution down in pT from hard pT scale.
687 0 : } while (pTmax > 0. && (nBranchMax <= 0 || nBranch < nBranchMax) );
688 :
689 : // Do all final-state emissions if not already considered above.
690 0 : if (doFSRafterProcess && (nBranchMax <= 0 || nBranch < nBranchMax) ) {
691 :
692 : // Find largest scale for final partons.
693 : pTmax = 0.;
694 0 : for (int i = 0; i < event.size(); ++i)
695 0 : if (event[i].isFinal() && event[i].scale() > pTmax)
696 0 : pTmax = event[i].scale();
697 0 : pTsaveFSR = pTmax;
698 :
699 : // Prepare all subsystems for evolution.
700 0 : for (int iSys = 0; iSys < partonSystemsPtr->sizeSys(); ++iSys)
701 0 : timesPtr->prepare( iSys, event);
702 :
703 : // Set up initial veto scale.
704 0 : doVeto = false;
705 0 : pTveto = pTvetoPT;
706 :
707 : // Begin evolution down in pT from hard pT scale.
708 0 : do {
709 0 : infoPtr->addCounter(29);
710 0 : typeVetoStep = 0;
711 0 : double pTtimes = timesPtr->pTnext( event, pTmax, 0.);
712 0 : infoPtr->setPTnow( pTtimes);
713 :
714 : // Allow a user veto. Only do it once, so remember to change pTveto.
715 0 : if (pTveto > 0. && pTveto > pTtimes) {
716 : pTveto = -1.;
717 0 : doVeto = userHooksPtr->doVetoPT( 4, event);
718 : // Abort event if vetoed.
719 0 : if (doVeto) {
720 0 : if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
721 0 : return false;
722 : }
723 : }
724 :
725 : // Do a final-state emission (if allowed).
726 0 : if (pTtimes > 0.) {
727 0 : infoPtr->addCounter(30);
728 0 : if (timesPtr->branch( event, true)) {
729 0 : iSysNow = timesPtr->system();
730 0 : ++nFSRinProc;
731 0 : if (iSysNow == 0) ++nFSRhard;
732 0 : if (canVetoStep && iSysNow == 0 && nFSRhard <= nVetoStep)
733 0 : typeVetoStep = 4;
734 :
735 0 : nBranch++;
736 0 : pTLastBranch = pTtimes;
737 0 : typeLastBranch = 4;
738 :
739 0 : }
740 : pTmax = pTtimes;
741 0 : }
742 :
743 : // If no pT scales above zero then nothing to be done.
744 : else pTmax = 0.;
745 :
746 : // Optionally check for a veto after the first few emissions.
747 0 : if (typeVetoStep > 0) {
748 0 : doVeto = userHooksPtr->doVetoStep( typeVetoStep, nISRhard,
749 0 : nFSRhard, event);
750 : // Abort event if vetoed.
751 0 : if (doVeto) {
752 0 : if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
753 0 : return false;
754 : }
755 : }
756 :
757 : // Handle potential merging veto.
758 0 : if ( canRemoveEvent && nISRhard + nFSRhard == 1 ){
759 : // Simply check, and possibly reset weights.
760 0 : mergingHooksPtr->doVetoStep( process, event );
761 0 : }
762 :
763 : // Keep on evolving until nothing is left to be done.
764 0 : infoPtr->addCounter(31);
765 :
766 0 : } while (pTmax > 0. && (nBranchMax <= 0 || nBranch < nBranchMax) );
767 : }
768 :
769 : // Handle veto after ISR + FSR + MPI, but before beam remnants
770 : // and resonance decays, e.g. for MLM matching.
771 0 : if (canVetoEarly && userHooksPtr->doVetoPartonLevelEarly( event)) {
772 0 : doVeto = true;
773 0 : if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
774 0 : return false;
775 : }
776 :
777 : // Perform showers in resonance decay chains before beams & reconnection.
778 0 : if (earlyResDec) {
779 0 : int oldSizeEvt = event.size();
780 0 : int oldSizeSys = partonSystemsPtr->sizeSys();
781 0 : if (nBranchMax <= 0 || nBranch < nBranchMax)
782 0 : doVeto = !resonanceShowers( process, event, true);
783 : // Abort event if vetoed.
784 0 : if (doVeto) return false;
785 :
786 : // Reassign new decay products to original system.
787 0 : for (int iSys = oldSizeSys; iSys < partonSystemsPtr->sizeSys(); ++iSys)
788 0 : for (int iOut = 0; iOut < partonSystemsPtr->sizeOut(iSys); ++iOut)
789 0 : partonSystemsPtr->addOut(0, partonSystemsPtr->getOut( iSys, iOut) );
790 0 : partonSystemsPtr->setSizeSys( oldSizeSys);
791 :
792 : // Perform decays and showers of W and Z emitted in shower.
793 : // To do:check if W/Z emission is on in ISR or FSR??
794 0 : if (!wzDecayShowers( event)) return false;
795 :
796 : // User hook to reconnect colours specifically in resonance decays.
797 0 : if (canReconResSys && !userHooksPtr->doReconnectResonanceSystems(
798 0 : oldSizeEvt, event)) return false;
799 0 : }
800 :
801 : // Find the first particle in the current diffractive system.
802 : int iFirst = 0;
803 0 : if (isDiff) {
804 : doDiffCR = isDiff;
805 0 : iFirst = (iHardLoop == 1) ? 5 + sizeEvent - sizeProcess : sizeEvent;
806 0 : if (isDiffC) iFirst = 6 + sizeEvent - sizeProcess;
807 : }
808 :
809 : // Change the first particle for hard diffraction.
810 0 : if (sampleTypeDiff == 1 || sampleTypeDiff == 3 || iHardDiffLoop == 2) {
811 : doDiffCR = true;
812 : iFirst = 5;
813 0 : }
814 :
815 : // Add beam remnants, including primordial kT kick and colour tracing.
816 0 : if (!doTrial && physical && doRemnants
817 0 : && !remnants.add( event, iFirst, doDiffCR)) physical = false;
818 :
819 : // If no problems then done.
820 0 : if (physical) break;
821 :
822 : // Else restore and loop, but do not throw existing diffractive system.
823 0 : if (!isDiff) event.clear();
824 : else {
825 0 : event.restoreSize();
826 0 : event.restoreJunctionSize();
827 : }
828 0 : beamAPtr->clear();
829 0 : beamBPtr->clear();
830 0 : partonSystemsPtr->clear();
831 :
832 : // End loop over ten tries. Restore from diffraction. Hopefully it worked.
833 0 : }
834 0 : if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
835 0 : if (!physical) {
836 : // Leave hard diffractive system properly if beam remnant failed.
837 0 : if (isHardDiff) leaveHardDiff( process, event);
838 0 : return false;
839 : }
840 :
841 : // End big outer loop to handle two systems in double diffraction.
842 0 : }
843 :
844 : // If no additional MPI has been found then set up the diffractive
845 : // system the first time around.
846 0 : if (isHardDiff && (sampleTypeDiff == 2 || sampleTypeDiff == 4) &&
847 0 : iHardDiffLoop == 1 && nMPI == 1) {
848 0 : event.clear();
849 0 : beamAPtr->clear();
850 0 : beamBPtr->clear();
851 0 : partonSystemsPtr->clear();
852 0 : setupHardDiff( process);
853 0 : continue;
854 : }
855 :
856 : // Do colour reconnection for non-diffractive events before resonance decays.
857 0 : if (doReconnect && !doDiffCR && reconnectMode > 0) {
858 0 : Event eventSave = event;
859 : bool colCorrect = false;
860 0 : for (int i = 0; i < 10; ++i) {
861 0 : colourReconnection.next(event, 0);
862 0 : if (junctionSplitting.checkColours(event)) {
863 : colCorrect = true;
864 0 : break;
865 : }
866 0 : else event = eventSave;
867 : }
868 0 : if (!colCorrect) {
869 0 : infoPtr->errorMsg("Error in PartonLevel::next: "
870 : "Colour reconnection failed.");
871 0 : return false;
872 : }
873 0 : }
874 :
875 : // Perform showers in resonance decay chains after beams & reconnection.
876 0 : int oldSizeEvt = event.size();
877 0 : if (!earlyResDec) {
878 0 : if (nBranchMax <= 0 || nBranch < nBranchMax)
879 0 : doVeto = !resonanceShowers( process, event, true);
880 : // Abort event if vetoed.
881 0 : if (doVeto) return false;
882 :
883 : // Perform decays and showers of W and Z emitted in shower.
884 : // To do:check if W/Z emission is on in ISR or FSR??
885 0 : if (!wzDecayShowers( event)) return false;
886 :
887 : // User hook to reconnect colours specifically in resonance decays.
888 0 : if (canReconResSys && !userHooksPtr->doReconnectResonanceSystems(
889 0 : oldSizeEvt, event)) return false;
890 : }
891 :
892 : // Store event properties. Not available for diffraction.
893 0 : if (!isDiff) infoPtr->setEvolution( pTsaveMPI, pTsaveISR, pTsaveFSR,
894 0 : nMPI, nISR, nFSRinProc, nFSRinRes);
895 0 : if (isDiff) {
896 0 : multiPtr->setEmpty();
897 0 : infoPtr->setImpact( multiPtr->bMPI(), multiPtr->enhanceMPI(), false);
898 0 : }
899 :
900 :
901 : // Do colour reconnection for resonance decays.
902 0 : if (!earlyResDec && forceResonanceCR && doReconnect &&
903 0 : !doDiffCR && reconnectMode != 0) {
904 0 : Event eventSave = event;
905 : bool colCorrect = false;
906 0 : for (int i = 0; i < 10; ++i) {
907 0 : colourReconnection.next(event, oldSizeEvt);
908 0 : if (junctionSplitting.checkColours(event)) {
909 : colCorrect = true;
910 0 : break;
911 : }
912 0 : else event = eventSave;
913 : }
914 0 : if (!colCorrect) {
915 0 : infoPtr->errorMsg("Error in PartonLevel::next: "
916 : "Colour reconnection failed.");
917 0 : return false;
918 : }
919 0 : }
920 :
921 : // Leave diffractive events.
922 0 : if (isHardDiff) {
923 :
924 : // If inclusive sample wanted for MPI veto and nMPI > 1
925 : // then event is non-diffractive and we can break the loop.
926 0 : if (sampleTypeDiff == 2 && iHardDiffLoop == 1 && nMPI > 1) {
927 0 : infoPtr->setHardDiff( false, false, false, 0., 0., 0., 0.);
928 0 : break;
929 : }
930 :
931 : // Leave diffractive system properly.
932 0 : if (sampleTypeDiff == 1 || sampleTypeDiff == 3 || iHardDiffLoop == 2)
933 0 : leaveHardDiff( process, event);
934 : }
935 :
936 : // End big outer loop to handle the setup of the diffractive system.
937 0 : }
938 :
939 : // Done.
940 0 : return true;
941 :
942 0 : }
943 :
944 : //--------------------------------------------------------------------------
945 :
946 : // Decide which diffractive subsystems are resolved (= perturbative).
947 :
948 : int PartonLevel::decideResolvedDiff( Event& process) {
949 :
950 : // Loop over two systems.
951 : int nHighMass = 0;
952 0 : int iDSmin = (isDiffC) ? 3 : 1;
953 0 : int iDSmax = (isDiffC) ? 3 : 2;
954 0 : for (int iDSnow = iDSmin; iDSnow <= iDSmax; ++iDSnow) {
955 0 : int iDiffMot = iDSnow + 2;
956 :
957 : // Only high-mass diffractive systems should be resolved.
958 0 : double mDiff = process[iDiffMot].m();
959 0 : bool isHighMass = ( mDiff > mMinDiff && rndmPtr->flat()
960 0 : < pMaxDiff * ( 1. - exp( -(mDiff - mMinDiff) / mWidthDiff ) ) );
961 :
962 : // Set outcome and done.
963 0 : if (isHighMass) ++nHighMass;
964 0 : if (iDSnow == 1) isResolvedA = isHighMass;
965 0 : if (iDSnow == 2) isResolvedB = isHighMass;
966 0 : if (iDSnow == 3) isResolvedC = isHighMass;
967 : }
968 0 : return nHighMass;
969 :
970 : }
971 :
972 : //--------------------------------------------------------------------------
973 :
974 : // Set up an unresolved process, i.e. elastic or diffractive.
975 :
976 : bool PartonLevel::setupUnresolvedSys( Event& process, Event& event) {
977 :
978 : // No hard scale in event.
979 0 : process.scale( 0.);
980 :
981 : // Copy particles from process to event.
982 0 : for (int i = 0; i < process.size(); ++ i) event.append( process[i]);
983 :
984 : // Loop to find diffractively excited beams.
985 0 : for (iDS = 1; iDS < 4; ++iDS)
986 0 : if ( (iDS == 1 && isDiffA && !isResolvedA)
987 0 : || (iDS == 2 && isDiffB && !isResolvedB)
988 0 : || (iDS == 3 && isDiffC && !isResolvedC) ) {
989 0 : int iBeam = iDS + 2;
990 :
991 : // Diffractive mass. Boost and rotation from diffractive system
992 : // rest frame, aligned along z axis, to event cm frame.
993 0 : double mDiff = process[iBeam].m();
994 0 : double m2Diff = mDiff * mDiff;
995 0 : Vec4 pDiffA = (iDS == 1) ? process[1].p()
996 0 : : process[1].p() - process[3].p();
997 0 : Vec4 pDiffB = (iDS == 2) ? process[2].p()
998 0 : : process[2].p() - process[4].p();
999 0 : RotBstMatrix MtoCM;
1000 0 : MtoCM.fromCMframe( pDiffA, pDiffB);
1001 :
1002 : // Beam Particle used for flavour content kicked out by Pomeron.
1003 : // Randomize for central diffraction; misses closed gluon loop case.
1004 0 : bool beamSideA = (iDS == 1 || (iDS == 3 && rndmPtr->flat() < 0.5));
1005 0 : BeamParticle* beamPtr = (beamSideA) ? beamAPtr : beamBPtr;
1006 0 : if (iDS == 3) beamPtr = (beamSideA) ? beamPomAPtr : beamPomBPtr;
1007 :
1008 : // Pick quark or gluon kicked out and flavour subdivision.
1009 0 : beamPtr->newValenceContent();
1010 0 : bool gluonIsKicked = beamPtr->pickGluon(mDiff);
1011 0 : int id1 = beamPtr->pickValence();
1012 0 : int id2 = beamPtr->pickRemnant();
1013 :
1014 : // Find flavour masses. Scale them down if too big.
1015 0 : double m1 = particleDataPtr->constituentMass(id1);
1016 0 : double m2 = particleDataPtr->constituentMass(id2);
1017 0 : if (m1 + m2 > 0.5 * mDiff) {
1018 0 : double reduce = 0.5 * mDiff / (m1 + m2);
1019 0 : m1 *= reduce;
1020 0 : m2 *= reduce;
1021 0 : }
1022 :
1023 : // If quark is kicked out, then trivial kinematics in rest frame.
1024 0 : if (!gluonIsKicked) {
1025 0 : double pAbs = sqrt( pow2(m2Diff - m1*m1 - m2*m2)
1026 0 : - pow2(2. * m1 * m2) ) / (2. * mDiff);
1027 0 : if (!beamSideA) pAbs = -pAbs;
1028 0 : double e1 = (m2Diff + m1*m1 - m2*m2) / (2. * mDiff);
1029 0 : double e2 = (m2Diff + m2*m2 - m1*m1) / (2. * mDiff);
1030 0 : Vec4 p1( 0., 0., -pAbs, e1);
1031 0 : Vec4 p2( 0., 0., pAbs, e2);
1032 :
1033 : // Boost and rotate to event cm frame.
1034 0 : p1.rotbst( MtoCM);
1035 0 : p2.rotbst( MtoCM);
1036 :
1037 : // Set colours.
1038 : int col1, acol1, col2, acol2;
1039 0 : if (particleDataPtr->colType(id1) == 1) {
1040 0 : col1 = event.nextColTag();
1041 : acol1 = 0;
1042 : col2 = 0;
1043 : acol2 = col1;
1044 0 : } else {
1045 : col1 = 0;
1046 0 : acol1 = event.nextColTag();
1047 : col2 = acol1;
1048 : acol2 = 0;
1049 : }
1050 : // Update process colours to stay in step.
1051 0 : process.nextColTag();
1052 :
1053 : // Store partons of diffractive system and mark system decayed.
1054 0 : int iDauBeg = event.append( id1, 24, iBeam, 0, 0, 0, col1, acol1,
1055 0 : p1, m1);
1056 0 : int iDauEnd = event.append( id2, 63, iBeam, 0, 0, 0, col2, acol2,
1057 0 : p2, m2);
1058 0 : event[iBeam].statusNeg();
1059 0 : event[iBeam].daughters(iDauBeg, iDauEnd);
1060 :
1061 : // If gluon is kicked out: share momentum between two remnants.
1062 0 : } else {
1063 : double m2Sys, zSys, pxSys, pySys, mTS1, mTS2;
1064 0 : zSys = beamPtr->zShare(mDiff, m1, m2);
1065 :
1066 : // Provide relative pT kick in remnant. Construct (transverse) masses.
1067 0 : pxSys = beamPtr->pxShare();
1068 0 : pySys = beamPtr->pyShare();
1069 0 : mTS1 = m1*m1 + pxSys*pxSys + pySys*pySys;
1070 0 : mTS2 = m2*m2 + pxSys*pxSys + pySys*pySys;
1071 0 : m2Sys = mTS1 / zSys + mTS2 / (1. - zSys);
1072 :
1073 : // Momentum of kicked-out massless gluon in diffractive rest frame.
1074 0 : double pAbs = (m2Diff - m2Sys) / (2. * mDiff);
1075 0 : double pLRem = (beamSideA) ? pAbs : -pAbs;
1076 0 : Vec4 pG( 0., 0., -pLRem, pAbs);
1077 0 : Vec4 pRem(0., 0., pLRem, mDiff - pAbs);
1078 :
1079 : // Momenta of the two beam remnant flavours. (Lightcone p+ = m_diff!)
1080 0 : double e1 = 0.5 * (zSys * mDiff + mTS1 / (zSys * mDiff));
1081 0 : double pL1 = 0.5 * (zSys * mDiff - mTS1 / (zSys * mDiff));
1082 0 : if (!beamSideA) pL1 = -pL1;
1083 0 : Vec4 p1(pxSys, pySys, pL1, e1);
1084 0 : Vec4 p2 = pRem - p1;
1085 :
1086 : // Boost and rotate to event cm frame. Improve precision.
1087 0 : pG.rotbst( MtoCM);
1088 0 : p1.rotbst( MtoCM);
1089 0 : p2.rotbst( MtoCM);
1090 0 : pG.e( pG.pAbs());
1091 :
1092 : // Set colours.
1093 : int colG, acolG, col1, acol1, col2, acol2;
1094 0 : if (particleDataPtr->colType(id1) == 1) {
1095 0 : col1 = event.nextColTag();
1096 : acol1 = 0;
1097 0 : colG = event.nextColTag();
1098 : acolG = col1;
1099 : col2 = 0;
1100 : acol2 = colG;
1101 0 : } else {
1102 : col1 = 0;
1103 0 : acol1 = event.nextColTag();
1104 : colG = acol1;
1105 0 : acolG = event.nextColTag();
1106 : col2 = acolG;
1107 : acol2 = 0;
1108 : }
1109 : // Update process colours to stay in step.
1110 0 : process.nextColTag();
1111 0 : process.nextColTag();
1112 :
1113 : // Store partons of diffractive system and mark system decayed.
1114 0 : int iDauBeg = event.append( 21, 24, iBeam, 0, 0, 0, colG, acolG, pG, 0.);
1115 0 : event.append( id1, 63, iBeam, 0, 0, 0, col1, acol1, p1, m1);
1116 0 : int iDauEnd = event.append( id2, 63, iBeam, 0, 0, 0, col2, acol2,
1117 0 : p2, m2);
1118 0 : event[iBeam].statusNeg();
1119 0 : event[iBeam].daughters(iDauBeg, iDauEnd);
1120 0 : }
1121 :
1122 : // End loop over beams. Done.
1123 0 : }
1124 0 : return true;
1125 :
1126 : }
1127 :
1128 : //--------------------------------------------------------------------------
1129 :
1130 : // Set up the hard process(es), excluding subsequent resonance decays.
1131 :
1132 : void PartonLevel::setupHardSys( Event& process, Event& event) {
1133 :
1134 : // Incoming partons to hard process are stored in slots 3 and 4.
1135 : int inS = 0;
1136 : int inP = 3;
1137 : int inM = 4;
1138 :
1139 : // Mother and last entry of diffractive system. Offset.
1140 0 : int iDiffMot = iDS + 2;
1141 0 : int iDiffDau = process.size() - 1;
1142 0 : int nOffset = sizeEvent - sizeProcess;
1143 :
1144 : // Corrected information for hard diffraction.
1145 0 : if (isSetupDiff) {
1146 0 : iDiffMot = (isHardDiffB) ? 4 : 3;
1147 : inS = iDiffMot;
1148 : inP = 7;
1149 : inM = 8;
1150 0 : }
1151 :
1152 : // Resolved diffraction means more entries.
1153 0 : if (isDiff) {
1154 : inS = iDiffMot;
1155 0 : inP = iDiffDau - 3;
1156 0 : inM = iDiffDau - 2;
1157 :
1158 : // Diffractively excited particle described as Pomeron-hadron beams.
1159 0 : event[inS].statusNeg();
1160 0 : event[inS].daughters( inP - 2 + nOffset, inM - 2 + nOffset);
1161 0 : }
1162 :
1163 : // If two hard interactions then find where second begins.
1164 0 : int iBeginSecond = process.size();
1165 0 : if (doSecondHard) {
1166 : iBeginSecond = 5;
1167 0 : while (process[iBeginSecond].status() != -21) ++iBeginSecond;
1168 : }
1169 :
1170 : // If incoming partons are massive then recalculate to put them massless.
1171 0 : if (process[inP].m() != 0. || process[inM].m() != 0.) {
1172 0 : double pPos = process[inP].pPos() + process[inM].pPos();
1173 0 : double pNeg = process[inP].pNeg() + process[inM].pNeg();
1174 0 : process[inP].pz( 0.5 * pPos);
1175 0 : process[inP].e( 0.5 * pPos);
1176 0 : process[inP].m( 0.);
1177 0 : process[inM].pz(-0.5 * pNeg);
1178 0 : process[inM].e( 0.5 * pNeg);
1179 0 : process[inM].m( 0.);
1180 0 : }
1181 :
1182 : // Add incoming hard-scattering partons to list in beam remnants.
1183 0 : double x1 = process[inP].pPos() / process[inS].m();
1184 0 : beamAPtr->append( inP + nOffset, process[inP].id(), x1);
1185 0 : double x2 = process[inM].pNeg() / process[inS].m();
1186 0 : beamBPtr->append( inM + nOffset, process[inM].id(), x2);
1187 :
1188 : // Scale. Find whether incoming partons are valence or sea. Store.
1189 : // When an x-dependent matter profile is used with nonDiffractive,
1190 : // trial interactions mean that the valence/sea choice has already
1191 : // been made and should be restored here.
1192 0 : double scale = process.scale();
1193 : int vsc1, vsc2;
1194 0 : beamAPtr->xfISR( 0, process[inP].id(), x1, scale*scale);
1195 0 : if (isNonDiff && (vsc1 = multiPtr->getVSC1()) != 0)
1196 0 : (*beamAPtr)[0].companion(vsc1);
1197 0 : else vsc1 = beamAPtr->pickValSeaComp();
1198 0 : beamBPtr->xfISR( 0, process[inM].id(), x2, scale*scale);
1199 0 : if (isNonDiff && (vsc2 = multiPtr->getVSC2()) != 0)
1200 0 : (*beamBPtr)[0].companion(vsc2);
1201 0 : else vsc2 = beamBPtr->pickValSeaComp();
1202 0 : bool isVal1 = (vsc1 == -3);
1203 0 : bool isVal2 = (vsc2 == -3);
1204 0 : infoPtr->setValence( isVal1, isVal2);
1205 :
1206 : // Initialize info needed for subsequent sequential decays + showers.
1207 0 : nHardDone = sizeProcess;
1208 0 : iPosBefShow.resize( process.size() );
1209 0 : fill( iPosBefShow.begin(), iPosBefShow.end(), 0);
1210 :
1211 : // Add the beam and hard subprocess partons to the event record.
1212 0 : for (int i = sizeProcess; i < iBeginSecond; ++i) {
1213 0 : if (process[i].mother1() > inM) break;
1214 0 : int j = event.append(process[i]);
1215 0 : iPosBefShow[i] = i;
1216 :
1217 : // Offset history if process and event not in step.
1218 0 : if (nOffset != 0) {
1219 0 : int iOrd = i - iBeginSecond + 7;
1220 0 : if (iOrd == 1 || iOrd == 2)
1221 0 : event[j].offsetHistory( 0, 0, 0, nOffset);
1222 0 : else if (iOrd == 3 || iOrd == 4)
1223 0 : event[j].offsetHistory( 0, nOffset, 0, nOffset);
1224 0 : else if (iOrd == 5 || iOrd == 6)
1225 0 : event[j].offsetHistory( 0, nOffset, 0, 0);
1226 0 : }
1227 :
1228 : // Currently outgoing ones should not count as decayed.
1229 0 : if (event[j].status() == -22) {
1230 0 : event[j].statusPos();
1231 0 : event[j].daughters(0, 0);
1232 0 : }
1233 :
1234 : // Complete task of copying hard subsystem into event record.
1235 0 : ++nHardDone;
1236 : }
1237 :
1238 : // Store participating partons as first set in list of all systems.
1239 0 : partonSystemsPtr->addSys();
1240 0 : partonSystemsPtr->setInA(0, inP + nOffset);
1241 0 : partonSystemsPtr->setInB(0, inM + nOffset);
1242 0 : for (int i = inM + 1; i < nHardDone; ++i)
1243 0 : partonSystemsPtr->addOut(0, i + nOffset);
1244 0 : partonSystemsPtr->setSHat( 0,
1245 0 : (event[inP + nOffset].p() + event[inM + nOffset].p()).m2Calc() );
1246 0 : partonSystemsPtr->setPTHat( 0, scale);
1247 :
1248 : // Identify second hard process where applicable.
1249 : // Since internally generated incoming partons are guaranteed massless.
1250 0 : if (doSecondHard) {
1251 : int inP2 = iBeginSecond;
1252 0 : int inM2 = iBeginSecond + 1;
1253 :
1254 : // Add incoming hard-scattering partons to list in beam remnants.
1255 : // Not valid if not in rest frame??
1256 0 : x1 = process[inP2].pPos() / process[0].e();
1257 0 : beamAPtr->append( inP2, process[inP2].id(), x1);
1258 0 : x2 = process[inM2].pNeg() / process[0].e();
1259 0 : beamBPtr->append( inM2, process[inM2].id(), x2);
1260 :
1261 : // Find whether incoming partons are valence or sea.
1262 0 : scale = process.scaleSecond();
1263 0 : beamAPtr->xfISR( 1, process[inP2].id(), x1, scale*scale);
1264 0 : beamAPtr->pickValSeaComp();
1265 0 : beamBPtr->xfISR( 1, process[inM2].id(), x2, scale*scale);
1266 0 : beamBPtr->pickValSeaComp();
1267 :
1268 : // Add the beam and hard subprocess partons to the event record.
1269 0 : for (int i = inP2; i < process.size(); ++ i) {
1270 0 : int mother = process[i].mother1();
1271 0 : if ( (mother > 2 && mother < inP2) || mother > inM2 ) break;
1272 0 : event.append(process[i]);
1273 0 : iPosBefShow[i] = i;
1274 :
1275 : // Currently outgoing ones should not count as decayed.
1276 0 : if (event[i].status() == -22) {
1277 0 : event[i].statusPos();
1278 0 : event[i].daughters(0, 0);
1279 0 : }
1280 :
1281 : // Complete task of copying hard subsystem into event record.
1282 0 : ++nHardDone;
1283 0 : }
1284 :
1285 : // Store participating partons as second set in list of all systems.
1286 0 : partonSystemsPtr->addSys();
1287 0 : partonSystemsPtr->setInA(1, inP2);
1288 0 : partonSystemsPtr->setInB(1, inM2);
1289 0 : for (int i = inM2 + 1; i < nHardDone; ++i)
1290 0 : partonSystemsPtr->addOut(1, i);
1291 0 : partonSystemsPtr->setSHat( 1,
1292 0 : (event[inP2].p() + event[inM2].p()).m2Calc() );
1293 0 : partonSystemsPtr->setPTHat( 1, scale);
1294 :
1295 : // End code for second hard process.
1296 0 : }
1297 :
1298 : // Update event colour tag to maximum in whole process.
1299 : int maxColTag = 0;
1300 0 : for (int i = 0; i < process.size(); ++ i) {
1301 0 : if (process[i].col() > maxColTag) maxColTag = process[i].col();
1302 0 : if (process[i].acol() > maxColTag) maxColTag = process[i].acol();
1303 : }
1304 0 : event.initColTag(maxColTag);
1305 :
1306 : // Copy junctions from process to event.
1307 0 : for (int iJun = 0; iJun < process.sizeJunction(); ++iJun) {
1308 : // Resonance decay products may not have been copied from process to
1309 : // event yet. If so, do not add junctions associated with decays yet.
1310 0 : int kindJunction = process.kindJunction(iJun);
1311 : bool doCopy = true;
1312 : // For junction types <= 4, check if final-state legs were copied.
1313 0 : if (kindJunction <= 4) {
1314 0 : int iLegF1 = (kindJunction - 1) / 2;
1315 0 : for (int iLeg = iLegF1; iLeg <= 2; ++iLeg) {
1316 : bool colFound = false;
1317 0 : for (int i = inM + 1; i < event.size(); ++i) {
1318 0 : int col = (kindJunction % 2 == 1) ? event[i].col() : event[i].acol();
1319 0 : if (col == process.colJunction(iJun,iLeg)) colFound = true;
1320 : }
1321 0 : if (!colFound) doCopy = false;
1322 : }
1323 0 : }
1324 0 : if (doCopy) event.appendJunction( process.getJunction(iJun));
1325 : }
1326 :
1327 : // Done.
1328 0 : }
1329 :
1330 : //--------------------------------------------------------------------------
1331 :
1332 : // Set up the event for subsequent resonance decays and showers.
1333 :
1334 : void PartonLevel::setupShowerSys( Event& process, Event& event) {
1335 :
1336 : // Reset event record to only contain line 0.
1337 0 : event.clear();
1338 0 : event.append( process[0]);
1339 :
1340 : // Initialize info needed for subsequent sequential decays + showers.
1341 0 : nHardDone = 1;
1342 0 : iPosBefShow.resize( process.size());
1343 0 : fill( iPosBefShow.begin(), iPosBefShow.end(), 0);
1344 :
1345 : // Add the hard subprocess partons to the event record.
1346 0 : for (int i = 1; i < process.size(); ++i) {
1347 0 : if (process[i].mother1() > 0) break;
1348 0 : int j = event.append(process[i]);
1349 0 : iPosBefShow[i] = i;
1350 :
1351 : // Currently outgoing ones should not count as decayed.
1352 0 : if (event[j].status() == -22) {
1353 0 : event[j].statusPos();
1354 0 : event[j].daughters(0, 0);
1355 0 : }
1356 :
1357 : // Complete task of copying hard subsystem into event record.
1358 0 : ++nHardDone;
1359 : }
1360 :
1361 : // Store participating partons as first set in list of all systems.
1362 0 : partonSystemsPtr->clear();
1363 0 : partonSystemsPtr->addSys();
1364 0 : for (int i = 1; i < nHardDone; ++i) partonSystemsPtr->addOut(0, i);
1365 0 : partonSystemsPtr->setSHat( 0, pow2(process[0].m()) );
1366 0 : partonSystemsPtr->setPTHat( 0, 0.5 * process[0].m() );
1367 :
1368 : // Copy junctions from process to event.
1369 0 : for (int iJun = 0; iJun < process.sizeJunction(); ++iJun) {
1370 : // Resonance decay products may not have been copied from process to
1371 : // event yet. If so, do not add junctions associated with decays yet.
1372 0 : int kindJunction = process.kindJunction(iJun);
1373 : bool doCopy = true;
1374 : // For junction types <= 4, check if final-state legs were copied.
1375 0 : if (kindJunction <= 4) {
1376 0 : int iLegF1 = (kindJunction - 1) / 2;
1377 0 : for (int iLeg = iLegF1; iLeg <= 2; ++iLeg) {
1378 : bool colFound = false;
1379 0 : for (int i = 1; i < event.size(); ++i) {
1380 0 : int col = (kindJunction % 2 == 1) ? event[i].col() : event[i].acol();
1381 0 : if (col == process.colJunction(iJun,iLeg)) colFound = true;
1382 : }
1383 0 : if (!colFound) doCopy = false;
1384 : }
1385 0 : }
1386 0 : if (doCopy) event.appendJunction( process.getJunction(iJun));
1387 : }
1388 :
1389 : // Done.
1390 0 : }
1391 :
1392 : //--------------------------------------------------------------------------
1393 :
1394 : // Resolved diffraction: replace full event with diffractive subsystem.
1395 :
1396 : void PartonLevel::setupResolvedDiff( Event& process) {
1397 :
1398 : // Mother and last entry of diffractive system.
1399 0 : int iDiffMot = iDS + 2;
1400 0 : int iDiffDau = process.size() - 1;
1401 :
1402 : // Diffractively excited particle to be replaced by Pomeron-hadron beams
1403 : // (or Pomeron-Pomeron beams for central diffraction).
1404 0 : process[iDiffMot].statusNeg();
1405 0 : process[iDiffMot].daughters( iDiffDau + 1, iDiffDau + 2);
1406 :
1407 : // Diffractive system mass.
1408 0 : double mDiff = process[iDiffMot].m();
1409 0 : double m2Diff = mDiff * mDiff;
1410 :
1411 : // Set up Pomeron-proton or Pomeron-Pomeron system as if it were
1412 : // the complete collision. Set Pomeron "beam particle" massless.
1413 0 : int idDiffA = (iDS == 1) ? process[1].id() : 990;
1414 0 : int idDiffB = (iDS == 2) ? process[2].id() : 990;
1415 0 : double mDiffA = (iDS == 1) ? process[1].m() : 0.;
1416 0 : double mDiffB = (iDS == 2) ? process[2].m() : 0.;
1417 0 : double m2DiffA = mDiffA * mDiffA;
1418 0 : double m2DiffB = mDiffB * mDiffB;
1419 0 : double eDiffA = 0.5 * (m2Diff + m2DiffA - m2DiffB) / mDiff;
1420 0 : double eDiffB = 0.5 * (m2Diff + m2DiffB - m2DiffA) / mDiff;
1421 0 : double pzDiff = 0.5 * sqrtpos( pow2(m2Diff - m2DiffA - m2DiffB)
1422 0 : - 4. * m2DiffA * m2DiffB ) / mDiff;
1423 0 : process.append( idDiffA, 13, iDiffMot, 0, 0, 0, 0, 0,
1424 : 0., 0., pzDiff, eDiffA, mDiffA);
1425 0 : process.append( idDiffB, 13, iDiffMot, 0, 0, 0, 0, 0,
1426 0 : 0., 0., -pzDiff, eDiffB, mDiffB);
1427 :
1428 : // Reassign beam pointers to refer to subsystem effective beams.
1429 0 : beamAPtr = (iDS == 1) ? beamHadAPtr : beamPomAPtr;
1430 0 : beamBPtr = (iDS == 2) ? beamHadBPtr : beamPomBPtr;
1431 :
1432 : // Pretend that the diffractive system is the whole collision.
1433 0 : eCMsave = infoPtr->eCM();
1434 0 : infoPtr->setECM( mDiff);
1435 0 : beamAPtr->newPzE( pzDiff, eDiffA);
1436 0 : beamBPtr->newPzE( -pzDiff, eDiffB);
1437 :
1438 : // Beams not found in normal slots 1 and 2.
1439 0 : int beamOffset = (sizeEvent > 0) ? sizeEvent - 1 : 4;
1440 :
1441 : // Reassign beam pointers in other classes.
1442 0 : timesPtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
1443 0 : spacePtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
1444 0 : remnants.reassignBeamPtrs( beamAPtr, beamBPtr, iDS);
1445 0 : colourReconnection.reassignBeamPtrs( beamAPtr, beamBPtr);
1446 :
1447 : // Reassign multiparton interactions pointer to right object.
1448 0 : if (iDS == 1) multiPtr = &multiSDA;
1449 0 : else if (iDS == 2) multiPtr = &multiSDB;
1450 0 : else multiPtr = &multiCD;
1451 :
1452 0 : }
1453 :
1454 : //--------------------------------------------------------------------------
1455 :
1456 : // Resolved diffraction: restore to original behaviour.
1457 :
1458 : void PartonLevel::leaveResolvedDiff( int iHardLoop, Event& process,
1459 : Event& event) {
1460 :
1461 : // Reconstruct boost and rotation to event cm frame.
1462 0 : Vec4 pDiffA = (iDS == 1) ? process[1].p()
1463 0 : : process[1].p() - process[3].p();
1464 0 : Vec4 pDiffB = (iDS == 2) ? process[2].p()
1465 0 : : process[2].p() - process[4].p();
1466 0 : RotBstMatrix MtoCM;
1467 0 : MtoCM.fromCMframe( pDiffA, pDiffB);
1468 :
1469 : // Perform rotation and boost on diffractive system.
1470 0 : for (int i = sizeProcess; i < process.size(); ++i)
1471 0 : process[i].rotbst( MtoCM);
1472 0 : int iFirst = (iHardLoop == 1) ? 5 + sizeEvent - sizeProcess : sizeEvent;
1473 0 : if(isDiffC) iFirst = 6 + sizeEvent - sizeProcess;
1474 0 : for (int i = iFirst; i < event.size(); ++i)
1475 0 : event[i].rotbst( MtoCM);
1476 :
1477 : // Restore cm energy.
1478 0 : infoPtr->setECM( eCMsave);
1479 0 : beamAPtr->newPzE( event[1].pz(), event[1].e());
1480 0 : beamBPtr->newPzE( event[2].pz(), event[2].e());
1481 :
1482 : // Restore beam pointers to incoming hadrons.
1483 0 : beamAPtr = beamHadAPtr;
1484 0 : beamBPtr = beamHadBPtr;
1485 :
1486 : // Reassign beam pointers in other classes.
1487 0 : timesPtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
1488 0 : spacePtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
1489 0 : remnants.reassignBeamPtrs( beamAPtr, beamBPtr, 0);
1490 0 : colourReconnection.reassignBeamPtrs( beamAPtr, beamBPtr);
1491 :
1492 : // Restore multiparton interactions pointer to default object.
1493 0 : multiPtr = &multiMB;
1494 :
1495 0 : }
1496 :
1497 : //--------------------------------------------------------------------------
1498 :
1499 : // Set up special handling of hard diffraction.
1500 :
1501 : void PartonLevel::setupHardDiff( Event& process) {
1502 :
1503 : // Create a temporary event record holding the info of the hard process.
1504 0 : Event tmpProcess = process;
1505 0 : process.clear();
1506 0 : process.scale(tmpProcess.scale());
1507 :
1508 : // Add the first three entries: system + incoming beams.
1509 0 : for (int iEntry = 0; iEntry < 3; ++iEntry)
1510 0 : process.append( tmpProcess[iEntry]);
1511 :
1512 : // Get system info and calculate diffractive system mass.
1513 0 : double eCM = infoPtr->eCM();
1514 0 : double sNow = eCM * eCM;
1515 0 : double xPom = (isHardDiffB) ? infoPtr->xPomeronA()
1516 0 : : infoPtr->xPomeronB();
1517 0 : double m2Diff = xPom * sNow;
1518 0 : double mDiff = sqrt(m2Diff);
1519 :
1520 : // Particle masses. If isHardDiffB then m3 is a proton and m4 the
1521 : // diffractive system.
1522 0 : double m1 = process[1].m();
1523 0 : double m2 = process[2].m();
1524 0 : double m3 = (isHardDiffB) ? m1 : mDiff;
1525 0 : double m4 = (isHardDiffA) ? m2 : mDiff;
1526 :
1527 : // Evaluate momenta of outgoing p and p_diff, initially along beam axis.
1528 0 : double s3 = pow2(m3);
1529 0 : double s4 = pow2(m4);
1530 0 : double lambda34 = sqrtpos( pow2( sNow - s3 - s4) - 4. * s3 * s4 );
1531 0 : double pAbs = 0.5 * lambda34 / eCM;
1532 0 : Vec4 p3 = Vec4( 0., 0., pAbs, 0.5 * (sNow + s3 - s4) / eCM);
1533 0 : Vec4 p4 = Vec4( 0., 0., -pAbs, 0.5 * (sNow + s4 - s3) / eCM);
1534 :
1535 : // Take copies for later longitudinal boost; then rotate outgoing beams.
1536 0 : Vec4 pD3 = p3;
1537 0 : Vec4 pD4 = p4;
1538 0 : double phi = 2. * M_PI * rndmPtr->flat();
1539 0 : double theta = (isHardDiffB) ? hardDiffraction.getThetaPomeronA() :
1540 0 : hardDiffraction.getThetaPomeronB();
1541 0 : p3.rot( theta, phi);
1542 0 : p4.rot( theta, phi);
1543 :
1544 : // Append intermediate states to the event record.
1545 0 : int status3 = (isHardDiffB) ? 14 : 15;
1546 0 : int status4 = (isHardDiffA) ? 14 : 15;
1547 : int sign = 0;
1548 0 : if (isHardDiffB) sign = (process[2].id() > 0) ? 1 : -1;
1549 0 : else if (isHardDiffA) sign = (process[1].id() > 0) ? 1 : -1;
1550 0 : int id3 = (isHardDiffB) ? process[1].id() : sign * 9902210;
1551 0 : int id4 = (isHardDiffA) ? process[2].id() : sign * 9902210;
1552 0 : process.append( id3, status3, 1, 0, 0, 0, 0, 0, p3, m3);
1553 0 : process.append( id4, status4, 2, 0, 0, 0, 0, 0, p4, m4);
1554 :
1555 : // Correct event record history accordingly.
1556 0 : process[1].daughters(3, 0);
1557 0 : process[2].daughters(4, 0);
1558 0 : int iDiffMot = (isHardDiffB) ? 4 : 3;
1559 0 : int iDiffRad = process.size() - 1;
1560 0 : process[iDiffMot].statusNeg();
1561 0 : process[iDiffMot].daughters( iDiffRad + 1, iDiffRad + 2);
1562 :
1563 : // Set up Pomeron-proton system as if it were the complete collision.
1564 : // Set Pomeron "beam particle" massless.
1565 0 : int idDiffA = (isHardDiffB) ? 990 : process[1].id();
1566 0 : int idDiffB = (isHardDiffA) ? 990 : process[2].id();
1567 0 : double mDiffA = (isHardDiffB) ? 0. : process[1].m();
1568 0 : double mDiffB = (isHardDiffA) ? 0. : process[2].m();
1569 0 : double m2DiffA = mDiffA * mDiffA;
1570 0 : double m2DiffB = mDiffB * mDiffB;
1571 0 : double eDiffA = 0.5 * (m2Diff + m2DiffA - m2DiffB) / mDiff;
1572 0 : double eDiffB = 0.5 * (m2Diff + m2DiffB - m2DiffA) / mDiff;
1573 0 : double pzDiff = 0.5 * sqrtpos( pow2(m2Diff - m2DiffA - m2DiffB)
1574 0 : - 4. * m2DiffA * m2DiffB ) / mDiff;
1575 0 : process.append( idDiffA, 13, iDiffMot, 0, 0, 0, 0, 0,
1576 : 0., 0., pzDiff, eDiffA, mDiffA);
1577 0 : process.append( idDiffB, 13, iDiffMot, 0, 0, 0, 0, 0,
1578 0 : 0., 0., -pzDiff, eDiffB, mDiffB);
1579 :
1580 : // Append hard process.
1581 0 : vector<int> hardParton;
1582 0 : for (int iHard = 3; iHard < tmpProcess.size(); ++iHard)
1583 0 : hardParton.push_back( process.append(tmpProcess[iHard]) );
1584 :
1585 : // Boost the hard partons in z-direction (from pp to Pp system).
1586 0 : Vec4 pDiffA = (isHardDiffA) ? process[1].p() : process[1].p() - pD3;
1587 0 : Vec4 pDiffB = (isHardDiffB) ? process[2].p() : process[2].p() - pD4;
1588 0 : RotBstMatrix MtoCM;
1589 0 : MtoCM.toCMframe( pDiffA, pDiffB);
1590 0 : for (unsigned int i = 0; i < hardParton.size(); ++i)
1591 0 : process[hardParton[i]].rotbst(MtoCM);
1592 :
1593 : // Change mothers and daughters after appending hard process.
1594 0 : for (unsigned int j = 0; j < hardParton.size(); ++j){
1595 0 : int mother1 = (tmpProcess[j+3].mother1() == 0)
1596 0 : ? 0 : tmpProcess[j+3].mother1() + 4;
1597 0 : int mother2 = (tmpProcess[j+3].mother2() == 0)
1598 0 : ? 0 : tmpProcess[j+3].mother2() + 4;
1599 0 : int daughter1 = (tmpProcess[j+3].daughter1() == 0)
1600 0 : ? 0 : tmpProcess[j+3].daughter1() + 4;
1601 0 : int daughter2 = (tmpProcess[j+3].daughter2() == 0)
1602 0 : ? 0 : tmpProcess[j+3].daughter2() + 4;
1603 0 : process[hardParton[j]].mothers( mother1,mother2);
1604 0 : process[hardParton[j]].daughters( daughter1, daughter2);
1605 : }
1606 :
1607 : // Search for pomeron and proton with status codes 13 (beam-inside-beam)
1608 : int iPomeron = 0;
1609 : int iProton = 0;
1610 0 : for (int i = 0; i < process.size(); ++i) {
1611 0 : if (process[i].id() == 990 && process[i].status() == 13) iPomeron = i;
1612 0 : if (abs(process[i].id()) == 2212 && process[i].status() == 13) iProton = i;
1613 : }
1614 :
1615 0 : if (isHardDiffB){
1616 0 : process[iPomeron].daughters(hardParton[0], 0);
1617 0 : process[iProton].daughters(hardParton[1],0);
1618 0 : process[hardParton[0]].mothers(iPomeron,0);
1619 0 : process[hardParton[1]].mothers(iProton, 0);
1620 0 : } else {
1621 0 : process[iPomeron].daughters(hardParton[1], 0);
1622 0 : process[iProton].daughters(hardParton[0],0);
1623 0 : process[hardParton[1]].mothers(iPomeron,0);
1624 0 : process[hardParton[0]].mothers(iProton, 0);
1625 : }
1626 :
1627 : // Negate status of Pomeron and proton
1628 0 : process[iPomeron].statusNeg();
1629 0 : process[iProton].statusNeg();
1630 :
1631 : // Change state of system to unresolved to avoid aborting from Pythia.
1632 0 : infoPtr->setHasUnresolvedBeams( true);
1633 :
1634 : // Reassign beam pointers to refer to subsystem effective beams.
1635 0 : beamAPtr = (isHardDiffB) ? beamPomAPtr : beamHadAPtr;
1636 0 : beamBPtr = (isHardDiffA) ? beamPomBPtr : beamHadBPtr;
1637 :
1638 : // Pretend that the diffractive system is the whole collision.
1639 0 : eCMsave = infoPtr->eCM();
1640 0 : infoPtr->setECM( mDiff);
1641 0 : beamAPtr->newPzE( pzDiff, eDiffA);
1642 0 : beamBPtr->newPzE( -pzDiff, eDiffB);
1643 :
1644 : // Beams not found in normal slots 1 and 2.
1645 : int beamOffset = 4;
1646 :
1647 : // Reassign beam pointers in other classes.
1648 0 : timesPtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
1649 0 : spacePtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
1650 0 : remnants.reassignBeamPtrs( beamAPtr, beamBPtr, (isHardDiffB) ? 2 : 1);
1651 0 : colourReconnection.reassignBeamPtrs( beamAPtr, beamBPtr);
1652 :
1653 : // Reassign multiparton interactions pointer to right object.
1654 0 : if (isHardDiffA) multiPtr = &multiSDA;
1655 0 : else if (isHardDiffB) multiPtr = &multiSDB;
1656 :
1657 : // Done.
1658 0 : isSetupDiff = true;
1659 :
1660 0 : }
1661 :
1662 : //--------------------------------------------------------------------------
1663 :
1664 : // Leave special handling of hard diffraction.
1665 :
1666 : void PartonLevel::leaveHardDiff( Event& process, Event& event) {
1667 :
1668 : // Reconstruct boost and rotation to event cm frame.
1669 0 : Vec4 pDiffA = (isHardDiffA) ? process[1].p()
1670 0 : : process[1].p() - process[3].p();
1671 0 : Vec4 pDiffB = (isHardDiffB) ? process[2].p()
1672 0 : : process[2].p() - process[4].p();
1673 0 : RotBstMatrix MtoCM;
1674 0 : MtoCM.fromCMframe( pDiffA, pDiffB);
1675 :
1676 : // Perform rotation and boost on diffractive system.
1677 0 : for (int i = 5; i < process.size(); ++i) process[i].rotbst( MtoCM);
1678 0 : for (int i = 5; i < event.size(); ++i) event[i].rotbst( MtoCM);
1679 :
1680 : // Clear diffractive info.
1681 0 : isHardDiffA = isHardDiffB = isHardDiff = false;
1682 :
1683 : // Restore cm energy.
1684 0 : infoPtr->setECM( eCMsave);
1685 0 : beamAPtr->newPzE( event[1].pz(), event[1].e());
1686 0 : beamBPtr->newPzE( event[2].pz(), event[2].e());
1687 :
1688 : // Restore beam pointers to incoming hadrons.
1689 0 : beamAPtr = beamHadAPtr;
1690 0 : beamBPtr = beamHadBPtr;
1691 :
1692 : // Reassign beam pointers in other classes.
1693 0 : timesPtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
1694 0 : spacePtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
1695 0 : remnants.reassignBeamPtrs( beamAPtr, beamBPtr, 0);
1696 0 : colourReconnection.reassignBeamPtrs( beamAPtr, beamBPtr);
1697 :
1698 : // Restore multiparton interactions pointer to default object.
1699 0 : multiPtr = &multiMB;
1700 :
1701 0 : }
1702 :
1703 : //--------------------------------------------------------------------------
1704 :
1705 : // Handle showers in successive resonance decays.
1706 :
1707 : bool PartonLevel::resonanceShowers( Event& process, Event& event,
1708 : bool skipForR) {
1709 :
1710 : // Prepare to start over from beginning for R-hadron decays.
1711 0 : if (allowRH) {
1712 0 : if (skipForR) {
1713 0 : nHardDoneRHad = nHardDone;
1714 0 : inRHadDecay.resize(0);
1715 0 : for (int i = 0; i < process.size(); ++i)
1716 0 : inRHadDecay.push_back( false);
1717 0 : } else nHardDone = nHardDoneRHad;
1718 : }
1719 :
1720 : // Isolate next system to be processed, if anything remains.
1721 : int nRes = 0;
1722 : int nFSRres = 0;
1723 : // Number of desired branchings, negative value means no restriction.
1724 0 : int nBranchMax = (doTrial) ? nTrialEmissions : -1;
1725 : // Vector to tell which junctions have already been copied
1726 0 : vector<int> iJunCopied;
1727 :
1728 0 : while (nHardDone < process.size()) {
1729 0 : ++nRes;
1730 0 : int iBegin = nHardDone;
1731 :
1732 : // In first call (skipForR = true) skip over resonances
1733 : // that should form R-hadrons, and their daughters.
1734 0 : if (allowRH) {
1735 0 : if (skipForR) {
1736 : bool comesFromR = false;
1737 : int iTraceUp = iBegin;
1738 0 : do {
1739 0 : if ( rHadronsPtr->givesRHadron(process[iTraceUp].id()) )
1740 0 : comesFromR = true;
1741 0 : iTraceUp = process[iTraceUp].mother1();
1742 0 : } while (iTraceUp > 0 && !comesFromR);
1743 0 : if (comesFromR) {
1744 0 : inRHadDecay[iBegin] = true;
1745 0 : ++nHardDone;
1746 0 : continue;
1747 : }
1748 :
1749 : // In optional second call (skipForR = false) process decay chains
1750 : // inside R-hadrons.
1751 0 : } else if (!inRHadDecay[iBegin]) {
1752 0 : ++nHardDone;
1753 0 : continue;
1754 : }
1755 : }
1756 :
1757 : // Mother in hard process and in complete event (after shower).
1758 0 : int iHardMother = process[iBegin].mother1();
1759 0 : Particle& hardMother = process[iHardMother];
1760 0 : int iBefMother = iPosBefShow[iHardMother];
1761 0 : int iAftMother = event[iBefMother].iBotCopyId();
1762 : // Possibly trace across intermediate R-hadron state.
1763 0 : if (allowRH) {
1764 0 : int iTraceRHadron = rHadronsPtr->trace( iAftMother);
1765 0 : if (iTraceRHadron > 0) iAftMother = iTraceRHadron;
1766 0 : }
1767 0 : Particle& aftMother = event[iAftMother];
1768 :
1769 : // From now on mother counts as decayed.
1770 0 : aftMother.statusNeg();
1771 :
1772 : // Mother can have been moved by showering (in any of previous steps),
1773 : // so prepare to update colour and momentum information for system.
1774 0 : int colBef = hardMother.col();
1775 0 : int acolBef = hardMother.acol();
1776 0 : int colAft = aftMother.col();
1777 0 : int acolAft = aftMother.acol();
1778 0 : RotBstMatrix M;
1779 0 : M.bst( hardMother.p(), aftMother.p());
1780 :
1781 : // New colour reconnection can not handle late resonance decay
1782 : // of coloured particles so abort event.
1783 0 : if ( (colBef != 0 || acolBef != 0) && doReconnect && reconnectMode == 1
1784 0 : && forceResonanceCR && !earlyResDec) {
1785 0 : infoPtr->errorMsg("Abort in PartonLevel::resonanceShower: "
1786 : "new CR can't handle separate CR for coloured resonance decays");
1787 0 : infoPtr->setAbortPartonLevel(true);
1788 0 : return false;
1789 : }
1790 :
1791 : // Extract next partons from hard event into normal event record.
1792 0 : vector<bool> doCopyJun;
1793 0 : for (int i = iBegin; i < process.size(); ++i) {
1794 0 : if (process[i].mother1() != iHardMother) break;
1795 0 : int iNow = event.append( process[i] );
1796 0 : iPosBefShow[i] = iNow;
1797 0 : Particle& now = event.back();
1798 :
1799 : // Currently outgoing ones should not count as decayed.
1800 0 : if (now.status() == -22) {
1801 0 : now.statusPos();
1802 0 : now.daughters(0, 0);
1803 0 : }
1804 :
1805 : // Update daughter and mother information.
1806 0 : if (i == iBegin) event[iAftMother].daughter1( iNow);
1807 0 : else event[iAftMother].daughter2( iNow);
1808 0 : now.mother1(iAftMother);
1809 :
1810 : // Check if this parton carries a junction color in hard event.
1811 0 : for (int iJun = 0; iJun < process.sizeJunction(); ++iJun) {
1812 0 : if (iJun >= int(doCopyJun.size())) doCopyJun.push_back(false);
1813 : // Only consider junctions that can appear in decays.
1814 0 : int kindJunction = process.kindJunction(iJun);
1815 0 : if (kindJunction >= 5) continue;
1816 0 : int col = (kindJunction % 2 == 1) ? now.col() : now.acol();
1817 0 : int iLegF1 = (kindJunction - 1) / 2;
1818 0 : for (int iLeg = iLegF1; iLeg <= 2; ++iLeg)
1819 0 : if (col == process.colJunction(iJun,iLeg)) doCopyJun[iJun] = true;
1820 0 : }
1821 :
1822 : // Update colour and momentum information.
1823 0 : if (now.col() == colBef) now.col( colAft);
1824 0 : if (now.acol() == acolBef) now.acol( acolAft);
1825 : // Sextet mothers have additional (negative) tag
1826 0 : if (now.col() == -acolBef) now.col( -acolAft);
1827 0 : if (now.acol() == -colBef) now.acol( -colAft);
1828 0 : now.rotbst( M);
1829 :
1830 : // Update vertex information.
1831 0 : if (now.hasVertex()) now.vProd( event[iAftMother].vDec() );
1832 :
1833 : // Complete task of copying next subsystem into event record.
1834 0 : ++nHardDone;
1835 : }
1836 0 : int iEnd = nHardDone - 1;
1837 :
1838 : // Copy down junctions from hard event into normal event record.
1839 0 : for (int iJun = 0; iJun < int(doCopyJun.size()); ++iJun) {
1840 : // Check if this junction was already copied
1841 0 : for (int jJun = 0; jJun < int(iJunCopied.size()); ++jJun)
1842 0 : if (iJunCopied[jJun] == iJun) doCopyJun[iJun] = false;
1843 : // Skip if not doing anything
1844 0 : if (!doCopyJun[iJun]) continue;
1845 : // Check for changed colors and update as necessary.
1846 0 : Junction junCopy = process.getJunction(iJun);
1847 0 : for (int iLeg = 0; iLeg <= 2; ++iLeg) {
1848 0 : int colLeg = junCopy.col(iLeg);
1849 0 : if (colLeg == colBef) junCopy.col(iLeg, colAft);
1850 0 : if (colLeg == acolBef) junCopy.col(iLeg, acolAft);
1851 : }
1852 0 : event.appendJunction(junCopy);
1853 : // Mark junction as copied (to avoid later recopying)
1854 0 : iJunCopied.push_back(iJun);
1855 0 : }
1856 :
1857 : // Reset pT of last branching
1858 0 : pTLastBranch = 0.0;
1859 :
1860 : // Add new system, automatically with two empty beam slots.
1861 0 : int iSys = partonSystemsPtr->addSys();
1862 0 : partonSystemsPtr->setSHat(iSys, pow2(hardMother.m()) );
1863 0 : partonSystemsPtr->setPTHat(iSys, 0.5 * hardMother.m() );
1864 :
1865 : // Loop over allowed range to find all final-state particles.
1866 0 : for (int i = iPosBefShow[iBegin]; i <= iPosBefShow[iEnd]; ++i)
1867 0 : if (event[i].isFinal()) partonSystemsPtr->addOut( iSys, i);
1868 :
1869 : // Do parton showers inside subsystem: maximum scale by mother mass.
1870 0 : if (doFSRinResonances) {
1871 0 : double pTmax = 0.5 * hardMother.m();
1872 0 : if (canSetScale) pTmax
1873 0 : = userHooksPtr->scaleResonance( iAftMother, event);
1874 0 : nFSRhard = 0;
1875 :
1876 : // Set correct scale for trial showers.
1877 0 : if (doTrial) pTmax = process.scale();
1878 :
1879 : // Let prepare routine do the setup.
1880 0 : timesDecPtr->prepare( iSys, event);
1881 :
1882 : // Number of actual branchings
1883 : int nBranch = 0;
1884 :
1885 : // Set up initial veto scale.
1886 0 : doVeto = false;
1887 0 : double pTveto = pTvetoPT;
1888 :
1889 : // Begin evolution down in pT from hard pT scale.
1890 0 : do {
1891 0 : typeVetoStep = 0;
1892 0 : double pTtimes = timesDecPtr->pTnext( event, pTmax, 0.);
1893 :
1894 : // Allow a user veto. Only do it once, so remember to change pTveto.
1895 0 : if (pTveto > 0. && pTveto > pTtimes) {
1896 : pTveto = -1.;
1897 0 : doVeto = userHooksPtr->doVetoPT( 5, event);
1898 : // Abort event if vetoed.
1899 0 : if (doVeto) return false;
1900 : }
1901 :
1902 : // Do a final-state emission (if allowed).
1903 0 : if (pTtimes > 0.) {
1904 0 : if (timesDecPtr->branch( event)) {
1905 0 : ++nFSRres;
1906 0 : ++nFSRhard;
1907 0 : if (canVetoStep && nFSRhard <= nVetoStep) typeVetoStep = 5;
1908 :
1909 0 : nBranch++;
1910 0 : pTLastBranch = pTtimes;
1911 0 : typeLastBranch = 5;
1912 :
1913 0 : }
1914 : pTmax = pTtimes;
1915 0 : }
1916 :
1917 : // If no pT scales above zero then nothing to be done.
1918 : else pTmax = 0.;
1919 :
1920 : // Optionally check for a veto after the first few emissions.
1921 0 : if (typeVetoStep > 0) {
1922 0 : doVeto = userHooksPtr->doVetoStep( typeVetoStep, 0, nFSRhard,
1923 : event);
1924 : // Abort event if vetoed.
1925 0 : if (doVeto) return false;
1926 : }
1927 :
1928 : // Handle potential merging veto.
1929 0 : if ( canRemoveEvent && nFSRhard == 1 ) {
1930 : // Simply check, and possibly reset weights.
1931 0 : mergingHooksPtr->doVetoStep( process, event, true );
1932 : }
1933 :
1934 : // Keep on evolving until nothing is left to be done.
1935 0 : } while (pTmax > 0. && (nBranchMax <= 0 || nBranch < nBranchMax) );
1936 :
1937 0 : }
1938 :
1939 : // No more systems to be processed. Set total number of emissions.
1940 0 : }
1941 0 : if (skipForR) nFSRinRes = nFSRres;
1942 0 : return true;
1943 :
1944 0 : }
1945 :
1946 : //--------------------------------------------------------------------------
1947 :
1948 : // Perform decays and showers of W and Z emitted in shower.
1949 :
1950 : bool PartonLevel::wzDecayShowers( Event& event) {
1951 :
1952 : // Identify W/Z produced by a parton shower.
1953 0 : for (int iWZ = 0; iWZ < event.size(); ++iWZ)
1954 0 : if (event[iWZ].isFinal()
1955 0 : && (event[iWZ].id() == 23 || event[iWZ].idAbs() == 24) ) {
1956 0 : int iWZtop = event[iWZ].iTopCopy();
1957 : int typeWZ = 0;
1958 0 : if (event[iWZtop].statusAbs() == 56) typeWZ = 1;
1959 0 : if (event[iWZtop].statusAbs() == 47) typeWZ = 2;
1960 0 : int sizeSave = event.size();
1961 :
1962 : // Map id_Z = 23 -> 93 and id_W = 24 -> 94, for separate decay settings.
1963 : // Let W/Z resonance decay. Restore correct identity and status codes.
1964 0 : if (typeWZ > 0) {
1965 0 : int idSave = event[iWZ].id();
1966 0 : event[iWZ].id( (idSave > 0) ? idSave + 70 : idSave - 70);
1967 0 : int statusSave = event[iWZ].status();
1968 0 : resonanceDecays.next( event, iWZ);
1969 0 : event[iWZ].id( idSave);
1970 0 : if (event.size() - sizeSave != 2) return true;
1971 0 : event[iWZ].status( -statusSave);
1972 0 : }
1973 :
1974 : // FSR decays.
1975 0 : if (typeWZ == 1) {
1976 :
1977 : // Identify fermion after W/Z emission.
1978 0 : vector<int> iSisters = event[iWZtop].sisterList();
1979 0 : if (iSisters.size() != 1) {
1980 0 : infoPtr->errorMsg("Error in PartonLevel::wzDecayShowers: "
1981 : "Not able to find a single sister particle");
1982 0 : return false;
1983 : }
1984 0 : int iEmitter = iSisters[0];
1985 :
1986 : // Boosts to study decay in W/Z rest frame.
1987 0 : RotBstMatrix MtoNew, MtoRest, MtoCM;
1988 0 : MtoNew.bst( event[iWZtop].p(), event[iWZ].p());
1989 0 : MtoRest.bstback( event[iWZ].p());
1990 0 : MtoCM.bst( event[iWZ].p());
1991 :
1992 : // Emitter and recoiler in W/Z rest frame.
1993 0 : Vec4 pEmitter = event[iEmitter].p();
1994 0 : pEmitter.rotbst( MtoNew);
1995 0 : pEmitter.rotbst( MtoRest);
1996 0 : if (event[iWZtop + 1].statusAbs() != 52) {
1997 0 : infoPtr->errorMsg("Error in PartonLevel::wzDecayShowers: "
1998 : "Found wrong recoiler");
1999 0 : return false;
2000 : }
2001 0 : Vec4 pRecoiler = event[iWZtop + 1].p();
2002 0 : pRecoiler.rotbst( MtoNew);
2003 0 : pRecoiler.rotbst( MtoRest);
2004 0 : Vec4 pWZRest = event[iWZ].p();
2005 0 : pWZRest.rotbst( MtoRest);
2006 :
2007 : // Always choose p4 as the particle and p5 as the anti-particle.
2008 0 : Vec4 p4 = pEmitter;
2009 0 : Vec4 p5 = pRecoiler;
2010 0 : if (event[iEmitter].id() < 0) swap( p4, p5);
2011 :
2012 : // Decay daughters in W/Z rest frame.
2013 : // Always choose pDec1 as the particle and p2Dec as the anti-particle.
2014 0 : Vec4 pDec1 = event[sizeSave].p();
2015 0 : Vec4 pDec2 = event[sizeSave + 1].p();
2016 0 : if (event[sizeSave].id() < 0) swap( pDec1, pDec2);
2017 0 : pDec1.rotbst( MtoRest);
2018 0 : pDec2.rotbst( MtoRest);
2019 :
2020 : // Couplings.
2021 : double li2, ri2, lf2, rf2;
2022 : // Z couplings: make use of initial fermion polarization if set.
2023 0 : if (event[iWZ].id() == 23) {
2024 0 : li2 = pow2(couplingsPtr->lf( event[iEmitter].idAbs() ));
2025 0 : ri2 = pow2(couplingsPtr->rf( event[iEmitter].idAbs() ));
2026 0 : lf2 = pow2(couplingsPtr->lf( event[sizeSave].idAbs() ));
2027 0 : rf2 = pow2(couplingsPtr->rf( event[sizeSave].idAbs() ));
2028 0 : if ( abs( event[iEmitter].pol() + 1.) < 0.1) ri2 = 0.;
2029 0 : if ( abs( event[iEmitter].pol() - 1.) < 0.1) li2 = 0.;
2030 : // W couplings.
2031 : } else {
2032 : li2 = 1.;
2033 : ri2 = 0.;
2034 : lf2 = 1.;
2035 : rf2 = 0.;
2036 : }
2037 :
2038 : // Different needed kinematic variables.
2039 0 : double sWZER = (p4 + pWZRest + p5).m2Calc();
2040 0 : double x1 = 2. * p4 * (p4 + pWZRest + p5) / sWZER;
2041 0 : double x2 = 2. * p5 * (p4 + pWZRest + p5) / sWZER;
2042 0 : double x1s = x1 * x1;
2043 0 : double x2s = x2 * x2;
2044 0 : double m2Sel = pWZRest.m2Calc();
2045 0 : double rWZER = m2Sel / sWZER;
2046 :
2047 : // Calculate constants needed in correction.
2048 0 : double con[9];
2049 0 : con[0] = 2. * m2Sel * (1.-x1) * ((x2s+1.-x1-x2) - rWZER * (1.-x2))
2050 0 : * (li2 * lf2 + ri2 * rf2);
2051 0 : con[1] = 2. * m2Sel * (1.-x2) * ((x1s+1.-x1-x2) - rWZER * (1.-x1))
2052 0 : * (li2 * rf2 + ri2 * lf2);
2053 0 : con[2] = 2. * m2Sel * (1.-x1) * ((x2s+1.-x1-x2) - rWZER * (1.-x2))
2054 0 : * (li2 * rf2 + ri2 * lf2);
2055 0 : con[3] = 2. * m2Sel * (1.-x2) * ((x1s+1.-x1-x2) - rWZER * (1.-x1))
2056 0 : * (li2 * lf2 + ri2 * rf2);
2057 0 : con[4] = m2Sel * sWZER * (1.-x1) * (1.-x2) * ((x1+x2-1.) + rWZER)
2058 0 : * (li2 + ri2) * (lf2 + rf2);
2059 0 : con[5] = -4. * (1.-x1) * (1.-x2) * (li2 + ri2) * (lf2 + rf2);
2060 0 : con[6] = -4. * (1.-x1) * (1.-x2) * (li2 + ri2) * (lf2 + rf2);
2061 0 : con[7] = 4. * (1.-x1) * ((1.-x1) - rWZER * (1.-x2))
2062 0 : * (li2 + ri2) * (lf2 + rf2);
2063 0 : con[8] = 4. * (1.-x2) * ((1.-x2) - rWZER * (1.-x1))
2064 0 : * (li2 + ri2) * (lf2 + rf2);
2065 :
2066 : // Find maximum value: try pDec1 and pDec2 = -pDec1 along +-x, +-y, +-z.
2067 : double wtMax = 0.;
2068 0 : double pAbs12 = pDec1.pAbs();
2069 0 : for (int j = 0; j < 6; ++j) {
2070 0 : Vec4 pDec1Test( 0., 0., 0., pDec1.e());
2071 0 : Vec4 pDec2Test( 0., 0., 0., pDec2.e());
2072 0 : if (j == 0) { pDec1Test.px( pAbs12); pDec1Test.px( -pAbs12);}
2073 0 : else if (j == 1) { pDec1Test.px( -pAbs12); pDec1Test.px( pAbs12);}
2074 0 : else if (j == 2) { pDec1Test.py( pAbs12); pDec1Test.py( -pAbs12);}
2075 0 : else if (j == 3) { pDec1Test.py( -pAbs12); pDec1Test.py( pAbs12);}
2076 0 : else if (j == 4) { pDec1Test.pz( pAbs12); pDec1Test.pz( -pAbs12);}
2077 0 : else if (j == 5) { pDec1Test.pz( -pAbs12); pDec1Test.pz( pAbs12);}
2078 :
2079 : // Evaluate matrix element and compare with current maximum.
2080 0 : double p2p4Test = p4 * pDec1Test;
2081 0 : double p3p4Test = p4 * pDec2Test;
2082 0 : double p2p5Test = p5 * pDec1Test;
2083 0 : double p3p5Test = p5 * pDec2Test;
2084 0 : double testValues[9] = { p2p4Test, p2p5Test, p3p4Test, p3p5Test, 1.,
2085 0 : p2p5Test * p3p4Test, p2p4Test * p3p5Test, p2p4Test * p3p4Test,
2086 0 : p2p5Test * p3p5Test};
2087 : double wtTest = 0.;
2088 0 : for (int i = 0; i < 9; ++i) wtTest += con[i] * testValues[i];
2089 0 : if (wtTest > wtMax) wtMax = wtTest;
2090 0 : }
2091 :
2092 : // Multiply by four to ensure maximum is an overestimate.
2093 0 : wtMax *= 4.;
2094 :
2095 : // Iterate with new angles until weighting succeeds.
2096 : int nRot = -1;
2097 : double wt = 0.;
2098 0 : do {
2099 0 : ++nRot;
2100 0 : if (nRot > 0) {
2101 0 : RotBstMatrix MrndmRot;
2102 0 : MrndmRot.rot( acos(2. * rndmPtr->flat() - 1.),
2103 0 : 2. * M_PI * rndmPtr->flat());
2104 0 : pDec1.rotbst(MrndmRot);
2105 0 : pDec2.rotbst(MrndmRot);
2106 0 : }
2107 :
2108 : // p2 is decay product, p3 is anti decay product,
2109 : // p4 is dipole particle, p5 is dipole anti particle.
2110 : // So far assumed that we always have qQ-dipole.
2111 0 : double p2p4 = p4 * pDec1;
2112 0 : double p3p4 = p4 * pDec2;
2113 0 : double p2p5 = p5 * pDec1;
2114 0 : double p3p5 = p5 * pDec2;
2115 :
2116 : // Calculate weight and compare with maximum weight.
2117 0 : double wtValues[9] = { p2p4, p2p5, p3p4, p3p5, 1., p2p5 * p3p4,
2118 0 : p2p4 * p3p5, p2p4 * p3p4, p2p5 * p3p5};
2119 : wt = 0.;
2120 0 : for (int i = 0; i < 9; ++i) wt += con[i] * wtValues[i];
2121 0 : if (wt > wtMax || wt < 0.) {
2122 0 : infoPtr->errorMsg("Error in PartonLevel::wzDecayShowers: "
2123 : "wt bigger than wtMax or less than zero");
2124 0 : return false;
2125 : }
2126 0 : } while (wt < wtMax * rndmPtr->flat());
2127 :
2128 : // If momenta rotated then store new ones.
2129 0 : if (nRot > 0) {
2130 0 : pDec1.rotbst( MtoCM);
2131 0 : pDec2.rotbst( MtoCM);
2132 0 : if (event[sizeSave].id() > 0) {
2133 0 : event[sizeSave].p( pDec1);
2134 0 : event[sizeSave + 1].p( pDec2);
2135 0 : }
2136 : else {
2137 0 : event[sizeSave].p( pDec2);
2138 0 : event[sizeSave + 1].p( pDec1);
2139 : }
2140 : }
2141 0 : }
2142 :
2143 : // ISR decays.
2144 0 : if (typeWZ == 2) {
2145 :
2146 : // Identify mother of W/Z emission.
2147 0 : double iMother = event[iWZtop].mother1();
2148 :
2149 : // Boosts to study decay in W/Z rest frame.
2150 0 : RotBstMatrix MtoNew, MtoRest, MtoCM;
2151 0 : MtoNew.bst( event[iWZtop].p(), event[iWZ].p());
2152 0 : MtoRest.bstback( event[iWZ].p());
2153 0 : MtoCM.bst( event[iWZ].p());
2154 :
2155 : // Find recoiler.
2156 : int iRecoiler;
2157 0 : if (event[iMother + 1].statusAbs() == 42) iRecoiler = iMother + 1;
2158 0 : else if (event[iMother - 1].statusAbs() == 42) iRecoiler = iMother - 1;
2159 : else {
2160 0 : infoPtr->errorMsg("Error in PartonLevel::wzDecayShowers: "
2161 : "Found wrong recoiler");
2162 0 : return false;
2163 : }
2164 :
2165 : // Emitter and recoiler in W/Z rest frame.
2166 0 : Vec4 pMother = event[iMother].p();
2167 0 : pMother.rotbst( MtoNew);
2168 0 : pMother.rotbst( MtoRest);
2169 0 : Vec4 pRecoiler = event[iRecoiler].p();
2170 0 : pRecoiler.rotbst( MtoNew);
2171 0 : pRecoiler.rotbst( MtoRest);
2172 0 : Vec4 pWZRest = event[iWZ].p();
2173 0 : pWZRest.rotbst( MtoRest);
2174 :
2175 : // Always choose p1 as the particle and p2 as the anti-particle.
2176 : // If no anti-particles just continue.
2177 0 : Vec4 p1 = pMother;
2178 0 : Vec4 p2 = pRecoiler;
2179 0 : if (event[iMother].id() < 0) swap( p1, p2);
2180 :
2181 : // Decay daughters in W/Z rest frame.
2182 : // Always choose pDec1 as the particle and p2Dec as the anti-particle.
2183 0 : Vec4 pDec1 = event[sizeSave].p();
2184 0 : Vec4 pDec2 = event[sizeSave + 1].p();
2185 0 : if (event[sizeSave].id() < 0) swap( pDec1, pDec2);
2186 0 : pDec1.rotbst( MtoRest);
2187 0 : pDec2.rotbst( MtoRest);
2188 :
2189 : // Couplings.
2190 : double li2, ri2, lf2, rf2;
2191 : // Z couplings: make use of initial fermion polarization if set.
2192 0 : if (event[iWZ].id() == 23) {
2193 0 : li2 = pow2(couplingsPtr->lf( event[iMother].idAbs() ));
2194 0 : ri2 = pow2(couplingsPtr->rf( event[iMother].idAbs() ));
2195 0 : lf2 = pow2(couplingsPtr->lf( event[sizeSave].idAbs() ));
2196 0 : rf2 = pow2(couplingsPtr->rf( event[sizeSave].idAbs() ));
2197 0 : if ( abs( event[iMother].pol() + 1.) < 0.1) ri2 = 0.;
2198 0 : if ( abs( event[iMother].pol() - 1.) < 0.1) li2 = 0.;
2199 : // W couplings.
2200 : } else {
2201 : li2 = 1.;
2202 : ri2 = 0.;
2203 : lf2 = 1.;
2204 : rf2 = 0.;
2205 : }
2206 :
2207 : // Different needed kinematic variables.
2208 0 : double s = (p1 + p2).m2Calc();
2209 0 : double t = (p1-pWZRest).m2Calc();
2210 0 : double u = (p2-pWZRest).m2Calc();
2211 0 : double m2Sel = pWZRest.m2Calc();
2212 0 : double m2Final = t + u + s - m2Sel;
2213 :
2214 : // Calculate constants needed in correction.
2215 0 : double con[9];
2216 0 : con[0] = 2. * m2Sel * (u * (1. - m2Final / t) + s)
2217 0 : * (li2 * rf2 + ri2 * lf2);
2218 0 : con[1] = 2. * m2Sel * (u * (1. - m2Final / t) + s)
2219 0 : * (li2 * lf2 + ri2 * rf2);
2220 0 : con[2] = 2. * m2Sel * (t * (1. - m2Final / u) + s)
2221 0 : * (li2 * lf2 + ri2 * rf2);
2222 0 : con[3] = 2. * m2Sel * (t * (1. - m2Final / u) + s)
2223 0 : * (li2 * rf2 + ri2 * lf2);
2224 0 : con[4] = m2Sel * m2Final * s * (li2 + ri2) * (lf2 + rf2);
2225 0 : con[5] = -4. * m2Final * (li2 + ri2) * (lf2 + rf2);
2226 0 : con[6] = -4. * m2Final * (li2 + ri2) * (lf2 + rf2);
2227 0 : con[7] = 4. * (m2Final * u / t - m2Sel) * (li2 + ri2) * (lf2 + rf2);
2228 0 : con[8] = 4. * (m2Final * t / u - m2Sel) * (li2 + ri2) * (lf2 + rf2);
2229 :
2230 : // Find maximum value: try pDec1 and pDec2 = -pDec1 along +-x, +-y, +-z.
2231 : double wtMax = 0.;
2232 0 : double pAbs12 = pDec1.pAbs();
2233 0 : for (int j = 0; j < 6; ++j) {
2234 0 : Vec4 pDec1Test( 0., 0., 0., pDec1.e());
2235 0 : Vec4 pDec2Test( 0., 0., 0., pDec2.e());
2236 0 : if (j == 0) { pDec1Test.px( pAbs12); pDec1Test.px( -pAbs12);}
2237 0 : else if (j == 1) { pDec1Test.px( -pAbs12); pDec1Test.px( pAbs12);}
2238 0 : else if (j == 2) { pDec1Test.py( pAbs12); pDec1Test.py( -pAbs12);}
2239 0 : else if (j == 3) { pDec1Test.py( -pAbs12); pDec1Test.py( pAbs12);}
2240 0 : else if (j == 4) { pDec1Test.pz( pAbs12); pDec1Test.pz( -pAbs12);}
2241 0 : else if (j == 5) { pDec1Test.pz( -pAbs12); pDec1Test.pz( pAbs12);}
2242 :
2243 : // Evaluate matrix element and compare with current maximum.
2244 0 : double p1p4Test = p1 * pDec1Test;
2245 0 : double p1p5Test = p1 * pDec2Test;
2246 0 : double p2p4Test = p2 * pDec1Test;
2247 0 : double p2p5Test = p2 * pDec2Test;
2248 0 : double testValues[9] = { p1p4Test, p1p5Test, p2p4Test, p2p5Test, 1.,
2249 0 : p1p4Test * p2p5Test, p1p5Test * p2p4Test, p1p4Test * p1p5Test,
2250 0 : p2p4Test * p2p5Test};
2251 : double wtTest = 0.;
2252 0 : for (int i = 0; i < 9; ++i) wtTest += con[i] * testValues[i];
2253 0 : if (wtTest > wtMax) wtMax = wtTest;
2254 0 : }
2255 :
2256 : // Multiply by four to ensure maximum is an overestimate.
2257 0 : wtMax *= 4.;
2258 :
2259 : // Iterate with new angles until weighting succeeds.
2260 : int nRot = -1;
2261 : double wt = 0.;
2262 0 : do {
2263 0 : ++nRot;
2264 0 : if (nRot > 0) {
2265 0 : RotBstMatrix MrndmRot;
2266 0 : MrndmRot.rot( acos(2. * rndmPtr->flat() - 1.),
2267 0 : 2. * M_PI * rndmPtr->flat());
2268 0 : pDec1.rotbst(MrndmRot);
2269 0 : pDec2.rotbst(MrndmRot);
2270 0 : }
2271 :
2272 : // p2 is decay product, p3 is anti decay product,
2273 : // p4 is dipole particle, p5 is dipole anti particle.
2274 : // So far assumed that we always have qQ-dipole.
2275 0 : double p1p4 = p1 * pDec1;
2276 0 : double p1p5 = p1 * pDec2;
2277 0 : double p2p4 = p2 * pDec1;
2278 0 : double p2p5 = p2 * pDec2;
2279 :
2280 : // Calculate weight and compare with maximum weight.
2281 0 : double wtValues[9] = { p1p4, p1p5, p2p4, p2p5, 1., p1p4 * p2p5,
2282 0 : p1p5 * p2p4, p1p4 * p1p5, p2p4 * p2p5};
2283 : wt = 0.;
2284 0 : for (int i = 0; i < 9; ++i) wt += con[i] * wtValues[i];
2285 0 : if (wt > wtMax || wt < 0.) {
2286 0 : infoPtr->errorMsg("Error in PartonLevel::wzDecayShowers: "
2287 : "wt bigger than wtMax or less than zero");
2288 0 : return false;
2289 : }
2290 0 : } while (wt < wtMax * rndmPtr->flat());
2291 :
2292 : // If momenta rotated then store new ones.
2293 0 : if (nRot > 0) {
2294 0 : pDec1.rotbst( MtoCM);
2295 0 : pDec2.rotbst( MtoCM);
2296 0 : if (event[sizeSave].id() > 0) {
2297 0 : event[sizeSave].p( pDec1);
2298 0 : event[sizeSave + 1].p( pDec2);
2299 0 : }
2300 : else {
2301 0 : event[sizeSave].p( pDec2);
2302 0 : event[sizeSave + 1].p( pDec1);
2303 : }
2304 : }
2305 0 : }
2306 :
2307 : // Add new system, automatically with two empty beam slots.
2308 0 : if (typeWZ > 0) {
2309 : // Maximum shower scale set by mother mass.
2310 0 : double pTmax = 0.5 * event[iWZ].m();
2311 0 : int iSys = partonSystemsPtr->addSys();
2312 0 : partonSystemsPtr->setSHat(iSys, pow2(event[iWZ].m()) );
2313 0 : partonSystemsPtr->setPTHat(iSys, pTmax );
2314 0 : for (int i = sizeSave; i < event.size(); ++i)
2315 0 : partonSystemsPtr->addOut( iSys, i);
2316 :
2317 : // Do parton showers inside subsystem.
2318 0 : if (doFSRinResonances) {
2319 :
2320 : // Let prepare routine do the setup.
2321 0 : timesDecPtr->prepare( iSys, event);
2322 :
2323 : // Begin evolution down in pT from hard pT scale.
2324 0 : do {
2325 0 : double pTtimes = timesDecPtr->pTnext( event, pTmax, 0.);
2326 :
2327 : // Do a final-state emission (if allowed).
2328 0 : if (pTtimes > 0.) {
2329 0 : timesDecPtr->branch( event);
2330 : pTmax = pTtimes;
2331 0 : }
2332 :
2333 : // If no pT scales above zero then nothing to be done.
2334 : else pTmax = 0.;
2335 :
2336 : // Keep on evolving until nothing is left to be done.
2337 0 : } while (pTmax > 0.);
2338 : }
2339 0 : }
2340 :
2341 : // End loop over event to find W/Z gauge bosons.
2342 0 : }
2343 :
2344 : // Done.
2345 0 : return true;
2346 :
2347 0 : }
2348 :
2349 : //==========================================================================
2350 :
2351 : } // end namespace Pythia8
|