StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
PartonLevel.cc
1 // PartonLevel.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2020 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL v2 or later, 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 #include "Pythia8/ColourReconnection.h"
11 
12 namespace Pythia8 {
13 
14 //==========================================================================
15 
16 // The PartonLevel class.
17 
18 //--------------------------------------------------------------------------
19 
20 // Constants: could be changed here if desired, but normally should not.
21 // These are of technical nature, as described for each.
22 
23 // Maximum number of tries to produce parton level from given input.
24 const int PartonLevel::NTRY = 10;
25 
26 //--------------------------------------------------------------------------
27 
28 // Main routine to initialize the parton-level generation process.
29 
30 bool PartonLevel::init( TimeShowerPtr timesDecPtrIn,
31  TimeShowerPtr timesPtrIn, SpaceShowerPtr spacePtrIn, RHadrons* rHadronsPtrIn,
32  MergingHooksPtr mergingHooksPtrIn, PartonVertexPtr partonVertexPtrIn,
33  StringIntPtr stringInteractionsPtrIn, bool useAsTrial ) {
34 
35  // Store other input pointers.
36  beamHadAPtr = beamAPtr;
37  beamHadBPtr = beamBPtr;
38  timesDecPtr = timesDecPtrIn;
39  timesPtr = timesPtrIn;
40  spacePtr = spacePtrIn;
41  rHadronsPtr = rHadronsPtrIn;
42  mergingHooksPtr = mergingHooksPtrIn;
43  partonVertexPtr = partonVertexPtrIn;
44  colourReconnectionPtr = stringInteractionsPtrIn->getColourReconnections();
45 
46  // Reference to Settings.
47  Settings& settings = *settingsPtr;
48 
49  // Min bias and diffraction processes need special treatment.
50  bool doSQ = settings.flag("SoftQCD:all")
51  || settings.flag("SoftQCD:inelastic");
52  bool doND = settings.flag("SoftQCD:nonDiffractive");
53  bool doSD = settings.flag("SoftQCD:singleDiffractive");
54  bool doDD = settings.flag("SoftQCD:doubleDiffractive");
55  bool doCD = settings.flag("SoftQCD:centralDiffractive");
56  doNonDiff = doSQ || doND;
57  doDiffraction = doSQ || doSD || doDD || doCD;
58  doHardDiff = settings.flag("Diffraction:doHard");
59  hardDiffSide = (doHardDiff) ? settings.mode("Diffraction:hardDiffSide")
60  : 0;
61  sampleTypeDiff = (doHardDiff) ? settings.mode("Diffraction:sampleType")
62  : 0;
63 
64  // Separate low-mass (unresolved) and high-mass (perturbative) diffraction.
65  mMinDiff = settings.parm("Diffraction:mMinPert");
66  mWidthDiff = settings.parm("Diffraction:mWidthPert");
67  pMaxDiff = settings.parm("Diffraction:probMaxPert");
68  if (mMinDiff > infoPtr->eCM()) doDiffraction = false;
69 
70  // Set whether photon inside lepton. Mode updated event-by-event.
71  gammaMode = settings.mode("Photon:ProcessType");
72  gammaModeEvent = 0;
73  beamAhasGamma = settings.flag("PDF:beamA2gamma");
74  beamBhasGamma = settings.flag("PDF:beamB2gamma");
75  sampleQ2gamma = settings.flag("Photon:sampleQ2");
76  beamHasGamma = (beamAhasGamma || beamBhasGamma)
77  && (beamAPtr != 0) && (beamBPtr != 0);
78  hasGammaA = false;
79  hasGammaB = false;
80  beamAisGamma = (beamAPtr != 0) ? beamAPtr->isGamma() : false;
81  beamBisGamma = (beamBPtr != 0) ? beamBPtr->isGamma() : false;
82  beamAhasResGamma = (beamAPtr != 0) ? beamAPtr->hasResGamma() : false;
83  beamBhasResGamma = (beamBPtr != 0) ? beamBPtr->hasResGamma() : false;
84  beamHasResGamma = (gammaMode < 4) && beamHasGamma;
85  isGammaHadronDir = false;
86 
87  // Simplify initialization when only unresolved photons.
88  bool isAgamBhad = (beamAisGamma || beamAhasGamma) && beamBPtr->isHadron();
89  bool isBgamAhad = (beamBisGamma || beamBhasGamma) && beamAPtr->isHadron();
90  bool isAgamBgam = (beamAisGamma || beamAhasGamma)
91  && (beamBisGamma || beamBhasGamma);
92  bool onlyDirGamma = ( gammaMode == 4 || ( gammaMode == 3 && isAgamBhad )
93  || ( gammaMode == 2 && isBgamAhad ) || ( gammaMode > 1 && isAgamBgam) );
94 
95  // Show the copies of beam photon if found in ISR.
96  showUnresGamma = settings.flag("Photon:showUnres");
97 
98  // Need MPI initialization for soft QCD processes, even if only first MPI.
99  // But no need to initialize MPI if never going to use it.
100  doMPI = settings.flag("PartonLevel:MPI");
101  doMPIMB = doMPI;
102  doMPISDA = doMPI;
103  doMPISDB = doMPI;
104  doMPICD = doMPI;
105  doMPIinit = doMPI;
106  doMPIgmgm = doMPI;
107  if (doNonDiff || doDiffraction) doMPIinit = true;
108  if (!settings.flag("PartonLevel:all")) doMPIinit = false;
109 
110  // Nature of MPI matching also used here for one case.
111  pTmaxMatchMPI = settings.mode("MultipartonInteractions:pTmaxMatch");
112 
113  // Initialise trial shower switch.
114  doTrial = useAsTrial;
115  // Merging initialization.
116  bool hasMergingHooks = (mergingHooksPtr != 0);
117  canRemoveEvent = !doTrial && hasMergingHooks
118  && ( mergingHooksPtr->doCKKWLMerging() || mergingHooksPtr->doNL3Merging());
119  canRemoveEmission = !doTrial && hasMergingHooks
120  && ( mergingHooksPtr->doUMEPSMerging() || mergingHooksPtr->doNL3Merging()
121  || mergingHooksPtr->doUNLOPSMerging() );
122  nTrialEmissions = 1;
123  pTLastBranch = 0.0;
124  typeLastBranch = 0;
125 
126  // Flags for showers: ISR and FSR.
127  doISR = settings.flag("PartonLevel:ISR");
128  bool FSR = settings.flag("PartonLevel:FSR");
129  bool FSRinProcess = settings.flag("PartonLevel:FSRinProcess");
130  bool interleaveFSR = settings.flag("TimeShower:interleave");
131  doFSRduringProcess = FSR && FSRinProcess && interleaveFSR;
132  doFSRafterProcess = FSR && FSRinProcess && !interleaveFSR;
133  doFSRinResonances = FSR && settings.flag("PartonLevel:FSRinResonances");
134 
135  // Flags for colour reconnection.
136  doReconnect = settings.flag("ColourReconnection:reconnect");
137  reconnectMode = settings.mode("ColourReconnection:mode");
138  forceResonanceCR = settings.flag("ColourReconnection:forceResonance");
139 
140  // Some other flags.
141  doRemnants = settings.flag("PartonLevel:Remnants");
142  doSecondHard = settings.flag("SecondHard:generate");
143  twoHard = doSecondHard;
144  earlyResDec = settings.flag("PartonLevel:earlyResDec");
145 
146  // Allow R-hadron formation.
147  allowRH = settings.flag("RHadrons:allow");
148 
149  // Possibility to allow user veto during evolution.
150  canVetoPT = (userHooksPtr != 0)
151  ? userHooksPtr->canVetoPT() : false;
152  pTvetoPT = (canVetoPT)
153  ? userHooksPtr->scaleVetoPT() : -1.;
154  canVetoStep = (userHooksPtr != 0)
155  ? userHooksPtr->canVetoStep() : false;
156  nVetoStep = (canVetoStep)
157  ? userHooksPtr->numberVetoStep() : -1;
158  canVetoMPIStep = (userHooksPtr != 0)
159  ? userHooksPtr->canVetoMPIStep() : false;
160  nVetoMPIStep = (canVetoMPIStep)
161  ? userHooksPtr->numberVetoMPIStep() : -1;
162  canVetoEarly = (userHooksPtr != 0)
163  ? userHooksPtr->canVetoPartonLevelEarly() : false;
164 
165  // Settings for vetoing of QCD emission for Drell-Yan weak boson production.
166  vetoWeakJets = settings.flag("WeakShower:vetoQCDjets");
167  vetoWeakDeltaR2 = pow2(settings.parm("WeakShower:vetoWeakDeltaR"));
168 
169  // Possibility to set maximal shower scale in resonance decays.
170  canSetScale = (userHooksPtr != 0)
171  ? userHooksPtr->canSetResonanceScale() : false;
172 
173  // Possibility to reconnect specifically for resonance decays.
174  canReconResSys = (userHooksPtr != 0)
175  ? userHooksPtr->canReconnectResonanceSystems() : false;
176 
177  // Done with initialization only for FSR in resonance decays.
178  if (beamAPtr == 0 || beamBPtr == 0) return true;
179 
180  // Make sure that photons are in resolved mode when mixing with unresolved
181  // before initializing MPIs.
182  if ( (beamAisGamma || beamAhasGamma) && gammaMode == 0) {
183  beamAPtr->setGammaMode(1);
184  if (beamAhasGamma) beamGamAPtr->setGammaMode(1);
185  }
186  if ( (beamBisGamma || beamBhasGamma) && gammaMode == 0) {
187  beamBPtr->setGammaMode(1);
188  if (beamBhasGamma) beamGamBPtr->setGammaMode(1);
189  }
190 
191  // Flag if lepton beams, and if non-resolved ones. May change main flags.
192  hasTwoLeptonBeams = beamAPtr->isLepton() && beamBPtr->isLepton();
193  hasOneLeptonBeam = (beamAPtr->isLepton() || beamBPtr->isLepton())
194  && !hasTwoLeptonBeams;
195  hasPointLeptons = (hasOneLeptonBeam || hasTwoLeptonBeams)
196  && (beamAPtr->isUnresolved() || beamBPtr->isUnresolved());
197  if ( (hasOneLeptonBeam || hasTwoLeptonBeams) && !beamHasResGamma ) {
198  doMPIMB = false;
199  doMPISDA = false;
200  doMPISDB = false;
201  doMPICD = false;
202  doMPIinit = false;
203  doMPIgmgm = false;
204  }
205  if (hasTwoLeptonBeams && hasPointLeptons) {
206  doISR = false;
207  doRemnants = false;
208  }
209 
210  // For ND events in lepton->gamma events no need to initialize MPIs for l+l-.
211  doNDgamma = false;
212  if (beamHasResGamma) doMPIinit = false;
213  if (beamHasResGamma && doND) doNDgamma = true;
214 
215  // Set info and initialize the respective program elements.
216  if (timesPtr) timesPtr->init( beamAPtr, beamBPtr);
217  if (doISR && spacePtr) spacePtr->init( beamAPtr, beamBPtr);
218 
219  doMPIMB = multiMB.init( doMPIinit, 0, beamAPtr, beamBPtr, partonVertexPtr);
220 
221  // Initialize MPIs for diffractive system, possibly photon beam from
222  // lepton, possibly VMD from photon.
223  if (doSD || doDD || doSQ || ( doHardDiff && (hardDiffSide == 0
224  || hardDiffSide == 1) && beamBPtr->getGammaMode() < 2 ) ) {
225  BeamParticle* tmpBeamA = (beamAhasGamma) ? beamGamAPtr : beamAPtr;
226  if (infoPtr->isVMDstateA()) tmpBeamA = beamVMDAPtr;
227  doMPISDA = multiSDA.init( !onlyDirGamma, 1, tmpBeamA, beamPomBPtr,
228  partonVertexPtr, (beamAisGamma || beamAhasGamma) );
229  }
230  if (doSD || doDD || doSQ || ( doHardDiff && (hardDiffSide == 0
231  || hardDiffSide == 2) && beamAPtr->getGammaMode() < 2 ) ) {
232  BeamParticle* tmpBeamB = (beamBhasGamma) ? beamGamBPtr : beamBPtr;
233  if (infoPtr->isVMDstateB()) tmpBeamB = beamVMDBPtr;
234  doMPISDB = multiSDB.init( !onlyDirGamma, 2, beamPomAPtr, tmpBeamB,
235  partonVertexPtr, (beamBisGamma || beamBhasGamma) );
236  }
237  if (doCD || doSQ) doMPICD = multiCD.init( doMPIinit, 3, beamPomAPtr,
238  beamPomBPtr, partonVertexPtr);
239  if (!remnants.init( partonVertexPtr, colourReconnectionPtr)) return false;
240  resonanceDecays.init();
241  if (colourReconnectionPtr) colourReconnectionPtr->init();
242  junctionSplitting.init();
243 
244  // Initialize hard diffraction with possible photon beams from leptons.
245  if (doHardDiff && (gammaMode !=4) ) {
246  hardDiffraction.init(beamAhasGamma ? beamGamAPtr : beamAPtr,
247  beamBhasGamma ? beamGamBPtr : beamBPtr);
248  }
249 
250  // Initialize an MPI instance for resolved photons when necessary.
251  if ( beamHasResGamma && (doMPI || doNDgamma) ) {
252  doMPIinit = true;
253  // Photon-hadron.
254  if (beamAhasGamma && !beamBhasGamma ) {
255  doMPIgmgm = multiGmGm.init( doMPIinit, 0, beamGamAPtr, beamBPtr,
256  partonVertexPtr, true);
257  // Hadron-photon.
258  } else if (beamBhasGamma && !beamAhasGamma ) {
259  doMPIgmgm = multiGmGm.init( doMPIinit, 0, beamAPtr, beamGamBPtr,
260  partonVertexPtr, true);
261  // Photon-photon.
262  } else {
263  doMPIgmgm = multiGmGm.init( doMPIinit, 0, beamGamAPtr, beamGamBPtr,
264  partonVertexPtr, true);
265  }
266  doMPIMB = doMPIgmgm;
267  }
268 
269  // Succeeded, or not.
270  multiPtr = &multiMB;
271  if (doMPIinit && !doMPIMB) return false;
272  if (doMPIinit && (doSD || doDD || doSQ) && (!doMPISDA || !doMPISDB))
273  return false;
274  if (doMPIinit && (doCD || doSQ) && !doMPICD) return false;
275  if (!doMPIMB || !doMPISDA || !doMPISDB || !doMPICD) doMPI = false;
276  return true;
277 
278 }
279 
280 //--------------------------------------------------------------------------
281 
282 // Function to reset PartonLevel object for trial shower usage.
283 
284 void PartonLevel::resetTrial() {
285 
286  // Clear input pointers.
287  partonSystemsPtr->clear();
288  beamAPtr->clear();
289  beamBPtr->clear();
290  beamHadAPtr->clear();
291  beamHadBPtr->clear();
292  beamPomAPtr->clear();
293  beamPomBPtr->clear();
294  beamGamAPtr->clear();
295  beamGamBPtr->clear();
296  beamVMDAPtr->clear();
297  beamVMDBPtr->clear();
298 
299  // Clear last branching return values.
300  pTLastBranch = 0.0;
301  typeLastBranch = 0;
302 
303 }
304 
305 //--------------------------------------------------------------------------
306 
307 // Main routine to do the parton-level evolution.
308 
309 bool PartonLevel::next( Event& process, Event& event) {
310 
311  // Current event classification.
312  isResolved = infoPtr->isResolved();
313  isResolvedA = isResolved;
314  isResolvedB = isResolved;
315  isResolvedC = isResolved;
316  isDiffA = infoPtr->isDiffractiveA();
317  isDiffB = infoPtr->isDiffractiveB();
318  isDiffC = infoPtr->isDiffractiveC();
319  isDiff = isDiffA || isDiffB || isDiffC;
320  isCentralDiff = isDiffC;
321  isDoubleDiff = isDiffA && isDiffB;
322  isSingleDiff = isDiff && !isDoubleDiff && !isCentralDiff;
323  isNonDiff = infoPtr->isNonDiffractive();
324  isElastic = infoPtr->isElastic();
325 
326  // Default values for what is to come with diffraction.
327  isHardDiffA = false;
328  isHardDiffB = false;
329  isHardDiff = false;
330  doDiffVeto = false;
331  // Mark hard diffractive events to handle CR correctly.
332  bool doDiffCR = false;
333  // The setup of the diffractive events can come after the first evolution.
334  int nHardDiffLoop = 1;
335  // Flag to check whether hard diffraction system is set up for the process.
336  hardDiffSet = false;
337  // Offset for the initiator position when photons from leptons.
338  gammaOffset = 0;
339 
340  // Parton-level vetoes for matching and merging.
341  doVeto = false;
342  infoPtr->setAbortPartonLevel(false);
343 
344  // Update photon state according to beams set in processContainer.
345  beamAhasResGamma = beamAPtr == nullptr ? false : beamAPtr->hasResGamma();
346  beamBhasResGamma = beamBPtr == nullptr ? false : beamBPtr->hasResGamma();
347  beamHasResGamma = beamAhasResGamma || beamBhasResGamma;
348 
349  // Save if photoproduction from either side.
350  hasGammaA = (beamAPtr != 0) ? beamAPtr->getGammaMode() > 0 : false;
351  hasGammaB = (beamBPtr != 0) ? beamBPtr->getGammaMode() > 0 : false;
352 
353  // Save current photon mode when mixing processes.
354  gammaModeEvent = gammaMode;
355  if ( hasGammaA || hasGammaB ) {
356  if (beamAPtr->getGammaMode() < 2 && beamBPtr->getGammaMode() < 2)
357  gammaModeEvent = 1;
358  if (beamAPtr->getGammaMode() < 2 && beamBPtr->getGammaMode() == 2)
359  gammaModeEvent = 2;
360  if (beamAPtr->getGammaMode() == 2 && beamBPtr->getGammaMode() < 2)
361  gammaModeEvent = 3;
362  if (beamAPtr->getGammaMode() == 2 && beamBPtr->getGammaMode() == 2)
363  gammaModeEvent = 4;
364  }
365 
366  // Check if direct-photon + hadron to set hard system correctly.
367  isGammaHadronDir = !(hasGammaA || hasGammaB) ? false :
368  ( (beamAPtr->getGammaMode() == 2) && (beamBPtr->getGammaMode() == 0) )
369  || ( (beamAPtr->getGammaMode() == 0) && (beamBPtr->getGammaMode() == 2) );
370 
371  // Set up gamma+gamma/p subcollision. May fail due to extreme kinematics.
372  if (beamHasGamma) {
373  if ( !setupResolvedLeptonGamma( process) ) return false;
374  }
375 
376  // Prepare for a potential hard diffractive event.
377  if (doHardDiff) {
378 
379  // Switch for the diffractive side to be considered.
380  bool checkSideA = (hardDiffSide < 2) && (beamBPtr->isHadron() ||
381  ((beamBisGamma || beamBhasGamma) && beamBPtr->getGammaMode() == 1));
382  bool checkSideB = (hardDiffSide%2 == 0) && (beamAPtr->isHadron() ||
383  ((beamAisGamma || beamAhasGamma) && beamAPtr->getGammaMode() == 1));
384 
385  // Preliminary decision based on diffractive-to-inclusive PDF ratio.
386  // If Pomeron taken from side A(=1), then B is the diffractive system.
387  // If Pomeron taken from side B(=2), then A is the diffractive system.
388  // Do not check for diffraction if direct photons.
389  // Rescale the x values when photon from lepton and calculate PDFs
390  // wrt. photon beam.
391  if ( checkSideA ) {
392  double xGammaB = beamBhasGamma ? beamHadBPtr->xGamma() : 1.;
393  double xBrescaled = infoPtr->x2pdf() / xGammaB;
394  double pdfB = beamBhasGamma ? beamGamBPtr->xf(infoPtr->id2pdf(),
395  xBrescaled, infoPtr->Q2Fac()) : infoPtr->pdf2();
396  isHardDiffA = hardDiffraction.isDiffractive(2, infoPtr->id2pdf(),
397  xBrescaled, infoPtr->Q2Fac(), pdfB);
398  }
399  if ( checkSideB ) {
400  double xGammaA = beamAhasGamma ? beamHadAPtr->xGamma() : 1.;
401  double xArescaled = infoPtr->x1pdf() / xGammaA;
402  double pdfA = beamAhasGamma ? beamGamAPtr->xf(infoPtr->id1pdf(),
403  xArescaled, infoPtr->Q2Fac()) : infoPtr->pdf1();
404  isHardDiffB = hardDiffraction.isDiffractive(1, infoPtr->id1pdf(),
405  xArescaled, infoPtr->Q2Fac(), pdfA);
406  }
407 
408  // No hard double diffraction yet, so randomly choose one of the sides.
409  if (isHardDiffA && isHardDiffB) {
410  if (rndmPtr->flat() < 0.5) isHardDiffA = false;
411  else isHardDiffB = false;
412  }
413  isHardDiff = isHardDiffA || isHardDiffB;
414 
415  // Save diffractive values.
416  double xPomA = (isHardDiffB) ? hardDiffraction.getXPomeronA() : 0.;
417  double xPomB = (isHardDiffA) ? hardDiffraction.getXPomeronB() : 0.;
418  double tPomA = (isHardDiffB) ? hardDiffraction.getTPomeronA() : 0.;
419  double tPomB = (isHardDiffA) ? hardDiffraction.getTPomeronB() : 0.;
420  infoPtr->setHardDiff( false, false, isHardDiffA, isHardDiffB,
421  xPomA, xPomB, tPomA, tPomB);
422 
423  // Discard all nondiffractive events if only diffractive sample is wanted.
424  if (!isHardDiff && sampleTypeDiff > 2) {
425  doDiffVeto = true;
426  // Reset beam pointers and set event back to original frame.
427  if (beamHasGamma) leaveResolvedLeptonGamma( process, event, false);
428  return false;
429  }
430 
431  if (isHardDiff) {
432  // Set up the diffractive system if run without MPI veto.
433  if (sampleTypeDiff%2 == 1) setupHardDiff( process);
434  // Allow for second loop if run with MPI veto.
435  else nHardDiffLoop = 2;
436  }
437  }
438 
439  // Check if two subcollisions, from secondHard or Les Houches input.
440  int n21 = 0;
441  for (int i = 1; i < process.size(); ++i)
442  if (process[i].status() == -21) ++n21;
443  twoHard = (n21 == 4);
444 
445  // nHardLoop counts how many hard-scattering subsystems are to be processed.
446  // Almost always 1, but elastic and low-mass diffraction gives 0, while
447  // double diffraction can give up to 2. Not to be confused with SecondHard.
448  int nHardLoop = 1;
449  if (!isResolved) nHardLoop = (isDiff) ? decideResolvedDiff( process) : 0;
450 
451  // Handle unresolved subsystems. Done if no resolved ones.
452  sizeProcess = 0;
453  sizeEvent = 0;
454  if (!isResolvedA || !isResolvedB || !isResolvedC) {
455  bool physical = setupUnresolvedSys( process, event);
456  // Set up the scattered photon if present before exiting.
457  if (!physical || nHardLoop == 0) {
458  if (beamHasGamma) leaveResolvedLeptonGamma( process, event, physical);
459  return physical;
460  }
461  sizeProcess = process.size();
462  sizeEvent = event.size();
463  }
464 
465  // Number of actual branchings.
466  int nBranch = 0;
467  // Number of desired branchings, negative value means no restriction.
468  int nBranchMax = (doTrial) ? nTrialEmissions : -1;
469 
470  // Store merging weight.
471  bool hasMergingHooks = (mergingHooksPtr != 0);
472  if ( hasMergingHooks && canRemoveEvent )
473  mergingHooksPtr->storeWeights(infoPtr->weightContainerPtr->
474  weightsMerging.weightValues);
475 
476  // Reset event weight coming from enhanced branchings.
477  if (userHooksPtr != 0) userHooksPtr->setEnhancedEventWeight(1.);
478 
479  // Loop to set up diffractive system if run with MPI veto.
480  for (int iHardDiffLoop = 1; iHardDiffLoop <= nHardDiffLoop;
481  ++iHardDiffLoop) {
482 
483  // Big outer loop to handle up to two systems (in double diffraction),
484  // but normally one. (Not indented in following, but end clearly marked.)
485  for (int iHardLoop = 1; iHardLoop <= nHardLoop; ++iHardLoop) {
486  infoPtr->setCounter(20, iHardLoop);
487  infoPtr->setCounter(21);
488 
489  // Classification of diffractive system: 1 = A, 2 = B, 3 = central.
490  iDS = 0;
491  if (isDiffA || isDiffB) iDS = (iHardLoop == 2 || !isResolvedA) ? 2 : 1;
492  if (isDiffC) iDS = 3;
493 
494  // Process and event records can be out of step for diffraction.
495  if (iHardLoop == 2) {
496  sizeProcess = process.size();
497  sizeEvent = event.size();
498  partonSystemsPtr->clear();
499  if (event.lastColTag() > process.lastColTag())
500  process.initColTag(event.lastColTag());
501  }
502 
503  // If you need to restore then do not throw existing diffractive system.
504  if (isDiff) {
505  event.saveSize();
506  event.saveJunctionSize();
507 
508  // Allow special treatment of diffractive systems.
509  setupResolvedDiff( process);
510  }
511 
512  // Prepare to do multiparton interactions; at new mass for diffraction.
513  if (doMPIinit || doDiffraction) multiPtr->reset();
514 
515  // Special case if nondiffractive: do hardest interaction.
516  if (isNonDiff || isDiff) {
517  multiPtr->pTfirst();
518  multiPtr->setupFirstSys( process);
519  }
520 
521  // Allow up to ten tries; failure possible for beam remnants.
522  // Main cause: inconsistent colour flow at the end of the day.
523  bool physical = true;
524  int nRad = 0;
525  for (int iTry = 0; iTry < NTRY; ++ iTry) {
526  infoPtr->addCounter(21);
527  for (int i = 22; i < 32; ++i) infoPtr->setCounter(i);
528 
529  // Reset flag, counters and max scales.
530  physical = true;
531  nMPI = (twoHard) ? 2 : 1;
532  nISR = 0;
533  nFSRinProc = 0;
534  nFSRinRes = 0;
535  nISRhard = 0;
536  nFSRhard = 0;
537  pTsaveMPI = 0.;
538  pTsaveISR = 0.;
539  pTsaveFSR = 0.;
540 
541  // Reset nMPI and nISR for showers.
542  infoPtr->setPartEvolved(nMPI, nISR);
543 
544  // Reset parameters related to valence content and remnants of photon
545  // beam if ISR or MPI generated.
546  if (beamAPtr->isGamma() && ( doMPI || doISR ) ) beamAPtr->resetGamma();
547  if (beamBPtr->isGamma() && ( doMPI || doISR ) ) beamBPtr->resetGamma();
548 
549  // Identify hard interaction system for showers.
550  setupHardSys( process, event);
551 
552  // Optionally check for a veto after the hardest interaction.
553  if (canVetoMPIStep) {
554  doVeto = userHooksPtr->doVetoMPIStep( 1, event);
555  // Abort event if vetoed.
556  if (doVeto) {
557  if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
558  if (beamHasResGamma) leaveResolvedLeptonGamma( process, event, false);
559  return false;
560  }
561  }
562 
563  // Check matching of process scale to maximum ISR/FSR/MPI scales.
564  double Q2Fac = infoPtr->Q2Fac();
565  double Q2Ren = infoPtr->Q2Ren();
566  bool limitPTmaxISR = (doISR)
567  ? spacePtr->limitPTmax( event, Q2Fac, Q2Ren) : false;
568  bool limitPTmaxFSR = (doFSRduringProcess)
569  ? timesPtr->limitPTmax( event, Q2Fac, Q2Ren) : false;
570  bool limitPTmaxMPI = (doMPI) ? multiPtr->limitPTmax( event) : false;
571 
572  // Global recoil: reset counters and store locations of outgoing partons.
573  timesPtr->prepareGlobal( event);
574  bool isFirstTrial = true;
575 
576  // Set hard scale, maximum for showers and multiparton interactions.
577  double pTscaleRad = process.scale();
578  double pTscaleMPI = (doMPI && pTmaxMatchMPI == 3)
579  ? multiPtr->scaleLimitPT() : pTscaleRad;
580  if (twoHard) {
581  pTscaleRad = max( pTscaleRad, process.scaleSecond() );
582  pTscaleMPI = min( pTscaleMPI, process.scaleSecond() );
583  }
584  double pTmaxMPI = (limitPTmaxMPI) ? pTscaleMPI : infoPtr->eCM();
585  double pTmaxISR = (limitPTmaxISR) ? spacePtr->enhancePTmax() * pTscaleRad
586  : infoPtr->eCM();
587  double pTmaxFSR = (limitPTmaxFSR) ? timesPtr->enhancePTmax() * pTscaleRad
588  : infoPtr->eCM();
589 
590  // Store the starting scale to use it for valence selection for gamma
591  // beam. In case of MPIs use the pT scale of the last one.
592  beamAPtr->pTMPI( process.scale() );
593  beamBPtr->pTMPI( process.scale() );
594 
595  // Potentially reset starting scales for matrix element merging.
596  if ( hasMergingHooks && (doTrial || canRemoveEvent || canRemoveEmission) )
597  mergingHooksPtr->setShowerStartingScales( doTrial,
598  (canRemoveEvent || canRemoveEmission), pTscaleRad, process, pTmaxFSR,
599  limitPTmaxFSR, pTmaxISR, limitPTmaxISR, pTmaxMPI, limitPTmaxMPI );
600  double pTmax = max( pTmaxMPI, max( pTmaxISR, pTmaxFSR) );
601  pTsaveMPI = pTmaxMPI;
602  pTsaveISR = pTmaxISR;
603  pTsaveFSR = pTmaxFSR;
604 
605  // Prepare the classes to begin the generation.
606  if (doMPI) multiPtr->prepare( event, pTmaxMPI, (iHardDiffLoop == 2) );
607  if (doISR) spacePtr->prepare( 0, event, limitPTmaxISR);
608  if (doFSRduringProcess) timesPtr->prepare( 0, event, limitPTmaxFSR);
609  if (twoHard && doISR) spacePtr->prepare( 1, event, limitPTmaxISR);
610  if (twoHard && doFSRduringProcess) timesPtr->prepare( 1, event,
611  limitPTmaxFSR);
612 
613  // Impact parameter has now been chosen, but not usefully for diffraction.
614  // (Never chosen for low-mass diffraction, twice for double diffraction.)
615  if (!isDiff) infoPtr->setImpact( multiPtr->bMPI(),
616  multiPtr->enhanceMPI(), multiPtr->enhanceMPIavg(), true,
617  (iHardDiffLoop == 2) );
618 
619  // Set up initial veto scale.
620  doVeto = false;
621  double pTveto = pTvetoPT;
622  typeLatest = 0;
623 
624  // Begin evolution down in pT from hard pT scale.
625  do {
626  infoPtr->addCounter(22);
627  typeVetoStep = 0;
628  nRad = nISR + nFSRinProc;
629 
630  // Check whether the beam photon has unresolved during the evolution.
631  bool unresolvedGammaA = (beamAPtr->isGamma()
632  && !(beamAPtr->resolvedGamma()) );
633  bool unresolvedGammaB = (beamBPtr->isGamma()
634  && !(beamBPtr->resolvedGamma()) );
635  bool unresolvedGamma = (unresolvedGammaA || unresolvedGammaB)
636  || gammaModeEvent == 4;
637 
638  // Find next pT value for FSR, MPI and ISR.
639  // Order calls to minimize time expenditure.
640  double pTgen = 0.;
641 
642  // Potentially increase shower stopping scale for trial showers, to
643  // avoid accumulating low-pT emissions (and weights thereof)
644  if ( hasMergingHooks && doTrial)
645  pTgen = max( pTgen, mergingHooksPtr->getShowerStoppingScale() );
646 
647  double pTtimes = (doFSRduringProcess)
648  ? timesPtr->pTnext( event, pTmaxFSR, pTgen, isFirstTrial, doTrial)
649  : -1.;
650  pTgen = max( pTgen, pTtimes);
651  // No MPIs for unresolved photons.
652  double pTmulti = (doMPI && !unresolvedGamma)
653  ? multiPtr->pTnext( pTmaxMPI, pTgen, event) : -1.;
654  pTgen = max( pTgen, pTmulti);
655  double pTspace = (doISR)
656  ? spacePtr->pTnext( event, pTmaxISR, pTgen, nRad, doTrial) : -1.;
657  double pTnow = max( pTtimes, max( pTmulti, pTspace));
658 
659  // Update information.
660  infoPtr->setPTnow( pTnow);
661  isFirstTrial = false;
662 
663  // Allow a user veto. Only do it once, so remember to change pTveto.
664  if (pTveto > 0. && pTveto > pTnow) {
665  pTveto = -1.;
666  doVeto = userHooksPtr->doVetoPT( typeLatest, event);
667  // Abort event if vetoed.
668  if (doVeto) {
669  if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
670  if (beamHasResGamma)
671  leaveResolvedLeptonGamma( process, event, false);
672  return false;
673  }
674  }
675 
676  // Do a multiparton interaction (if allowed).
677  if (pTmulti > 0. && pTmulti > pTspace && pTmulti > pTtimes) {
678  infoPtr->addCounter(23);
679  if (multiPtr->scatter( event)) {
680  typeLatest = 1;
681  ++nMPI;
682  if (canVetoMPIStep && nMPI <= nVetoMPIStep) typeVetoStep = 1;
683 
684  // Break for hard diffraction with MPI veto.
685  if (isHardDiff && sampleTypeDiff == 4 && iHardDiffLoop == 1) {
686  infoPtr->setHardDiff( false, false, false, false, 0., 0.,
687  0., 0.);
688  doDiffVeto = true;
689  // Reset beam pointers and set event back to original frame.
690  if (beamHasResGamma)
691  leaveResolvedLeptonGamma( process, event, false);
692  return false;
693  }
694 
695  // Update ISR and FSR dipoles.
696  if (doISR) spacePtr->prepare( nMPI - 1, event);
697  if (doFSRduringProcess) timesPtr->prepare( nMPI - 1, event);
698  nBranch++;
699  pTLastBranch = pTmulti;
700  typeLastBranch = 1;
701  }
702 
703  // Set maximal scales for next pT to pick.
704  pTmaxMPI = pTmulti;
705  pTmaxISR = min(pTmulti, pTmaxISR);
706  pTmaxFSR = min(pTmulti, pTmaxFSR);
707  pTmax = pTmulti;
708  }
709 
710  // Do an initial-state emission (if allowed).
711  else if (pTspace > 0. && pTspace > pTtimes) {
712  infoPtr->addCounter(24);
713 
714  // If MPIs, construct the gamma->qqbar branching in beamRemnants.
715  if (spacePtr->branch( event)
716  && ( !(nMPI > 1 && spacePtr->wasGamma2qqbar()) ) ) {
717  typeLatest = 2;
718  iSysNow = spacePtr->system();
719  ++nISR;
720  if (iSysNow == 0) ++nISRhard;
721  if (canVetoStep && iSysNow == 0 && nISRhard <= nVetoStep)
722  typeVetoStep = 2;
723 
724  // Update FSR dipoles.
725  if (doFSRduringProcess) timesPtr->update( iSysNow, event,
726  spacePtr->getHasWeaklyRadiated());
727  nBranch++;
728  pTLastBranch = pTspace;
729  typeLastBranch = 2;
730 
731  // Rescatter: it is possible for kinematics to fail, in which
732  // case we need to restart the parton level processing.
733  } else if (spacePtr->doRestart()) {
734  physical = false;
735  break;
736  }
737 
738  // Set maximal scales for next pT to pick.
739  pTmaxMPI = min( min(pTspace,pTmaxISR), pTmaxMPI);
740  pTmaxISR = min(pTspace,pTmaxISR);
741  pTmaxFSR = min( min(pTspace,pTmaxISR), pTmaxFSR);
742  pTmax = pTspace;
743  }
744 
745  // Do a final-state emission (if allowed).
746  else if (pTtimes > 0.) {
747  infoPtr->addCounter(25);
748  if (timesPtr->branch( event, true)) {
749  typeLatest = 3;
750  iSysNow = timesPtr->system();
751  ++nFSRinProc;
752  if (iSysNow == 0) ++nFSRhard;
753  if (canVetoStep && iSysNow == 0 && nFSRhard <= nVetoStep)
754  typeVetoStep = 3;
755 
756  // Update ISR dipoles.
757  if (doISR) spacePtr->update( iSysNow, event,
758  timesPtr->getHasWeaklyRadiated());
759  nBranch++;
760  pTLastBranch = pTtimes;
761  typeLastBranch = 3;
762 
763  }
764 
765  // Set maximal scales for next pT to pick.
766  pTmaxMPI = min( min(pTtimes,pTmaxFSR), pTmaxMPI);
767  pTmaxISR = min( min(pTtimes,pTmaxFSR), pTmaxISR);
768  pTmaxFSR = min(pTtimes, pTmaxFSR);
769  pTmax = pTtimes;
770  }
771 
772  // If no pT scales above zero then nothing to be done.
773  else pTmax = 0.;
774 
775  // Check for double counting for Drell-Yan weak production.
776  // Only look at the second emission.
777  if ( (infoPtr->code() == 221 || infoPtr->code() == 222) &&
778  nISRhard + nFSRhard == 2 && vetoWeakJets) {
779  int id1 = event[partonSystemsPtr->getOut(0,0)].id();
780  int id2 = event[partonSystemsPtr->getOut(0,1)].id();
781  int id3 = event[partonSystemsPtr->getOut(0,2)].id();
782  Vec4 p1 = event[partonSystemsPtr->getOut(0,0)].p();
783  Vec4 p2 = event[partonSystemsPtr->getOut(0,1)].p();
784  Vec4 p3 = event[partonSystemsPtr->getOut(0,2)].p();
785 
786  // Make sure id1 is weak boson, and check that there
787  // only is a single weak boson and no photons.
788  bool doubleCountEvent = true;
789  if (abs(id1) == 24 || abs(id1) == 23) {
790  if (abs(id2) > 21 || abs(id3) > 21)
791  doubleCountEvent = false;
792  } else if (abs(id2) == 24 || abs(id2) == 23) {
793  swap(id1,id2);
794  swap(p1,p2);
795  if (abs(id3) > 21)
796  doubleCountEvent = false;
797  } else if ( abs(id3) == 24 || abs(id3) == 23) {
798  swap(id1,id3);
799  swap(p1,p3);
800  }
801 
802  if (doubleCountEvent) {
803  double d = p1.pT2();
804  bool cut = true;
805  if (p2.pT2() < d) {d = p2.pT2(); cut = false;}
806  if (p3.pT2() < d) {d = p3.pT2(); cut = false;}
807 
808  // Check for angle between weak boson and quarks.
809  // (require final state particle to be a fermion)
810  if (abs(id2) < 20) {
811  double dij = min(p1.pT2(),p2.pT2())
812  * pow2(RRapPhi(p1,p2)) / vetoWeakDeltaR2;
813  if (dij < d) {
814  d = dij;
815  cut = true;
816  }
817  }
818 
819  if (abs(id3) < 20) {
820  double dij = min(p1.pT2(),p3.pT2())
821  * pow2(RRapPhi(p1,p3)) / vetoWeakDeltaR2;
822  if (dij < d) {
823  d = dij;
824  cut = true;
825  }
826  }
827 
828  // Check for angle between recoiler and radiator,
829  // if it is a quark anti-quark pair
830  // or if the recoiler is a gluon.
831  if (abs(id2) == 21 || abs(id3) == 21 || id2 == - id3) {
832  double dij = min(p2.pT2(),p3.pT2())
833  * pow2(RRapPhi(p2,p3)) / vetoWeakDeltaR2;
834  if (dij < d) {
835  d = dij;
836  cut = false;
837  }
838  }
839 
840  // Veto event if it does not belong to Drell-Yan production.
841  if (cut) return false;
842  }
843  }
844 
845  // Optionally check for a veto after the first few interactions,
846  // or after the first few emissions, ISR or FSR, in the hardest system.
847  if (typeVetoStep == 1) {
848  doVeto = userHooksPtr->doVetoMPIStep( nMPI, event);
849  } else if (typeVetoStep > 1) {
850  doVeto = userHooksPtr->doVetoStep( typeVetoStep, nISRhard,
851  nFSRhard, event);
852  }
853 
854  // Abort event if vetoed.
855  if (doVeto) {
856  if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
857  if (beamHasResGamma) leaveResolvedLeptonGamma( process, event);
858  return false;
859  }
860 
861  // Keep on evolving until nothing is left to be done.
862  if (typeLatest > 0 && typeLatest < 4)
863  infoPtr->addCounter(25 + typeLatest);
864  if (!isDiff) infoPtr->setPartEvolved( nMPI, nISR);
865 
866  // Handle potential merging veto.
867  if ( canRemoveEvent && nISRhard + nFSRhard == 1 ) {
868  // Simply check, and possibly reset weights.
869  mergingHooksPtr->doVetoStep( process, event );
870  }
871 
872  // End loop evolution down in pT from hard pT scale.
873  } while (pTmax > 0. && (nBranchMax <= 0 || nBranch < nBranchMax) );
874 
875  // Do all final-state emissions if not already considered above.
876  if (doFSRafterProcess && (nBranchMax <= 0 || nBranch < nBranchMax) ) {
877 
878  // Find largest scale for final partons.
879  pTmax = 0.;
880  for (int i = 0; i < event.size(); ++i)
881  if (event[i].isFinal() && event[i].scale() > pTmax)
882  pTmax = event[i].scale();
883  pTsaveFSR = pTmax;
884 
885  // Prepare all subsystems for evolution.
886  for (int iSys = 0; iSys < partonSystemsPtr->sizeSys(); ++iSys)
887  timesPtr->prepare( iSys, event);
888 
889  // Set up initial veto scale.
890  doVeto = false;
891  pTveto = pTvetoPT;
892 
893  // Begin evolution down in pT from hard pT scale.
894  do {
895  infoPtr->addCounter(29);
896  typeVetoStep = 0;
897  double pTtimes = timesPtr->pTnext( event, pTmax, 0.);
898  infoPtr->setPTnow( pTtimes);
899 
900  // Allow a user veto. Only do it once, so remember to change pTveto.
901  if (pTveto > 0. && pTveto > pTtimes) {
902  pTveto = -1.;
903  doVeto = userHooksPtr->doVetoPT( 4, event);
904  // Abort event if vetoed.
905  if (doVeto) {
906  if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
907  if (beamHasResGamma) leaveResolvedLeptonGamma( process, event);
908  return false;
909  }
910  }
911 
912  // Do a final-state emission (if allowed).
913  if (pTtimes > 0.) {
914  infoPtr->addCounter(30);
915  if (timesPtr->branch( event, true)) {
916  iSysNow = timesPtr->system();
917  ++nFSRinProc;
918  if (iSysNow == 0) ++nFSRhard;
919  if (canVetoStep && iSysNow == 0 && nFSRhard <= nVetoStep)
920  typeVetoStep = 4;
921 
922  nBranch++;
923  pTLastBranch = pTtimes;
924  typeLastBranch = 4;
925 
926  }
927  pTmax = pTtimes;
928  }
929 
930  // If no pT scales above zero then nothing to be done.
931  else pTmax = 0.;
932 
933  // Optionally check for a veto after the first few emissions.
934  if (typeVetoStep > 0) {
935  doVeto = userHooksPtr->doVetoStep( typeVetoStep, nISRhard,
936  nFSRhard, event);
937  // Abort event if vetoed.
938  if (doVeto) {
939  if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
940  if (beamHasResGamma) leaveResolvedLeptonGamma( process, event);
941  return false;
942  }
943  }
944 
945  // Handle potential merging veto.
946  if ( canRemoveEvent && nISRhard + nFSRhard == 1 ) {
947  // Simply check, and possibly reset weights.
948  mergingHooksPtr->doVetoStep( process, event );
949  }
950 
951  // Keep on evolving until nothing is left to be done.
952  infoPtr->addCounter(31);
953 
954  } while (pTmax > 0. && (nBranchMax <= 0 || nBranch < nBranchMax) );
955  }
956 
957  // Handle veto after ISR + FSR + MPI, but before beam remnants
958  // and resonance decays, e.g. for MLM matching.
959  if (canVetoEarly && userHooksPtr->doVetoPartonLevelEarly( event)) {
960  doVeto = true;
961  if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
962  if (beamHasResGamma) leaveResolvedLeptonGamma( process, event);
963  return false;
964  }
965 
966  // Perform showers in resonance decay chains before beams & reconnection.
967  if (earlyResDec) {
968  int oldSizeEvt = event.size();
969  int oldSizeSys = partonSystemsPtr->sizeSys();
970  if (nBranchMax <= 0 || nBranch < nBranchMax)
971  doVeto = !resonanceShowers( process, event, true);
972  // Abort event if vetoed.
973  if (doVeto) return false;
974 
975  // Reassign new decay products to original system, or else beam remnant
976  // handling would be confused by systems without incoming partons.
977  for (int iSys = oldSizeSys; iSys < partonSystemsPtr->sizeSys(); ++iSys)
978  for (int iOut = 0; iOut < partonSystemsPtr->sizeOut(iSys); ++iOut)
979  partonSystemsPtr->addOut(0, partonSystemsPtr->getOut( iSys, iOut) );
980  partonSystemsPtr->setSizeSys( oldSizeSys);
981 
982  // Perform decays and showers of W and Z emitted in shower.
983  // To do: check if W/Z emission is on in ISR or FSR??
984  if (!wzDecayShowers( event)) return false;
985 
986  // User hook to reconnect colours specifically in resonance decays.
987  if (canReconResSys && !userHooksPtr->doReconnectResonanceSystems(
988  oldSizeEvt, event)) return false;
989  }
990 
991  // Find the first particle in the current diffractive system.
992  int iFirst = 0;
993  if (isDiff) {
994  doDiffCR = isDiff;
995  iFirst = (iHardLoop == 1) ? 5 + sizeEvent - sizeProcess : sizeEvent;
996  if (isDiffC) iFirst = 6 + sizeEvent - sizeProcess;
997  }
998 
999  // Change the first particle for hard diffraction.
1000  if (infoPtr->hasPomPsystem()) {
1001  doDiffCR = true;
1002  iFirst = 5;
1003  }
1004 
1005  // Add beam remnants, including primordial kT kick and colour tracing.
1006  if (!doTrial && physical && doRemnants
1007  && (!beamHasGamma || gammaModeEvent != 4)
1008  && !remnants.add( event, iFirst, doDiffCR)) physical = false;
1009 
1010  // If no problems then done.
1011  if (physical) break;
1012 
1013  // Else restore and loop, but do not throw existing diffractive system.
1014  if (!isDiff) event.clear();
1015  else {
1016  event.restoreSize();
1017  event.restoreJunctionSize();
1018  }
1019  beamAPtr->clear();
1020  beamBPtr->clear();
1021  partonSystemsPtr->clear();
1022 
1023  // Restore also the lepton beams if include photons.
1024  if (beamAhasResGamma) beamHadAPtr->clear();
1025  if (beamBhasResGamma) beamHadBPtr->clear();
1026  if (infoPtr->isVMDstateA()) beamVMDAPtr->clear();
1027  if (infoPtr->isVMDstateB()) beamVMDBPtr->clear();
1028 
1029  // End loop over ten tries. Restore from diffraction. Hopefully it worked.
1030  }
1031  if (isDiff) leaveResolvedDiff( iHardLoop, process, event);
1032 
1033  if (!physical) {
1034  // Leave hard diffractive system properly if beam remnant failed.
1035  if (infoPtr->hasPomPsystem()) leaveHardDiff( process, event, false);
1036  // Leave also photon from lepton framework.
1037  if (beamHasGamma) leaveResolvedLeptonGamma( process, event, false);
1038  return false;
1039  }
1040 
1041  // End big outer loop to handle two systems in double diffraction.
1042  }
1043 
1044  // If no additional MPI has been found then set up the diffractive
1045  // system the first time around.
1046  if (isHardDiff && sampleTypeDiff%2 == 0 && iHardDiffLoop == 1 && nMPI == 1) {
1047  event.clear();
1048  beamAPtr->clear();
1049  beamBPtr->clear();
1050  partonSystemsPtr->clear();
1051  setupHardDiff( process);
1052  continue;
1053  }
1054 
1055  // Do colour reconnection for non-diffractive events before resonance decays.
1056  if ( colourReconnectionPtr && !doDiffCR && reconnectMode > 0) {
1057  Event eventSave = event;
1058  bool colCorrect = false;
1059  for (int i = 0; i < 10; ++i) {
1060  colourReconnectionPtr->next(event, 0);
1061  if (junctionSplitting.checkColours(event)) {
1062  colCorrect = true;
1063  break;
1064  }
1065  else event = eventSave;
1066  }
1067  if (!colCorrect) {
1068  infoPtr->errorMsg("Error in PartonLevel::next: "
1069  "Colour reconnection failed.");
1070  return false;
1071  }
1072  }
1073 
1074  // Perform showers in resonance decay chains after beams & reconnection.
1075  int oldSizeEvt = event.size();
1076  if (!earlyResDec) {
1077  if (nBranchMax <= 0 || nBranch < nBranchMax)
1078  doVeto = !resonanceShowers( process, event, true);
1079  // Abort event if vetoed.
1080  if (doVeto) return false;
1081 
1082  // Perform decays and showers of W and Z emitted in shower.
1083  // To do:check if W/Z emission is on in ISR or FSR??
1084  if (!wzDecayShowers( event)) return false;
1085 
1086  // User hook to reconnect colours specifically in resonance decays.
1087  if (canReconResSys && !userHooksPtr->doReconnectResonanceSystems(
1088  oldSizeEvt, event)) return false;
1089  }
1090 
1091  // Store event properties. Not available for diffraction.
1092  if (!isDiff) infoPtr->setEvolution( pTsaveMPI, pTsaveISR, pTsaveFSR,
1093  nMPI, nISR, nFSRinProc, nFSRinRes);
1094  if (isDiff) {
1095  multiPtr->setEmpty();
1096  infoPtr->setImpact( multiPtr->bMPI(), multiPtr->enhanceMPI(),
1097  multiPtr->enhanceMPIavg(), false);
1098  }
1099 
1100  // Do colour reconnection for resonance decays.
1101  if (!earlyResDec && forceResonanceCR && colourReconnectionPtr &&
1102  !doDiffCR && reconnectMode != 0) {
1103  Event eventSave = event;
1104  bool colCorrect = false;
1105  for (int i = 0; i < 10; ++i) {
1106  colourReconnectionPtr->next(event, oldSizeEvt);
1107  if (junctionSplitting.checkColours(event)) {
1108  colCorrect = true;
1109  break;
1110  }
1111  else event = eventSave;
1112  }
1113  if (!colCorrect) {
1114  infoPtr->errorMsg("Error in PartonLevel::next: "
1115  "Colour reconnection failed.");
1116  return false;
1117  }
1118  }
1119 
1120  // Leave diffractive events.
1121  if (isHardDiff) {
1122 
1123  // If inclusive sample wanted for MPI veto and nMPI > 1
1124  // then event is non-diffractive and we can break the loop.
1125  if (sampleTypeDiff == 2 && iHardDiffLoop == 1 && nMPI > 1) {
1126  infoPtr->setHardDiff( false, false, false, false, 0., 0., 0., 0.);
1127  break;
1128  }
1129 
1130  // Leave diffractive system properly.
1131  if (infoPtr->hasPomPsystem()) leaveHardDiff( process, event);
1132  }
1133 
1134  // End big outer loop to handle the setup of the diffractive system.
1135  }
1136 
1137  // If beam photon unresolved during evolution remove the copies of the
1138  // beam particle from the event record.
1139  if ( ( beamAPtr->isGamma() || beamBPtr->isGamma() )
1140  && ( !beamAPtr->resolvedGamma() || !beamBPtr->resolvedGamma() ) ) {
1141  if (!showUnresGamma && (gammaModeEvent != 4) ) cleanEventFromGamma( event);
1142  }
1143 
1144  // After parton level generation, add scattered leptons, restore the event.
1145  if (beamHasGamma) leaveResolvedLeptonGamma( process, event, true);
1146 
1147  // Allow option for QED shower phase after remnants but before hadronisation
1148  // Note: incoming leptons or photons may evolve as part of this phase.
1149  timesPtr->showerQEDafterRemnants(event);
1150 
1151  // Done.
1152  return true;
1153 
1154 }
1155 
1156 //--------------------------------------------------------------------------
1157 
1158 // Decide which diffractive subsystems are resolved (= perturbative).
1159 
1160 int PartonLevel::decideResolvedDiff( Event& process) {
1161 
1162  // Loop over two systems.
1163  int nHighMass = 0;
1164  int iDSmin = (isDiffC) ? 3 : 1;
1165  int iDSmax = (isDiffC) ? 3 : 2;
1166  for (int iDSnow = iDSmin; iDSnow <= iDSmax; ++iDSnow) {
1167 
1168  // Offset for diffractive system when photons from lepton beams.
1169  int iDiffMot = iDSnow + 2 + gammaOffset;
1170 
1171  // Only high-mass diffractive systems should be resolved.
1172  double mDiff = process[iDiffMot].m();
1173  bool isHighMass = ( mDiff > mMinDiff && rndmPtr->flat()
1174  < pMaxDiff * ( 1. - exp( -(mDiff - mMinDiff) / mWidthDiff ) ) );
1175 
1176  // Set outcome and done.
1177  if (isHighMass) ++nHighMass;
1178  if (iDSnow == 1) isResolvedA = isHighMass;
1179  if (iDSnow == 2) isResolvedB = isHighMass;
1180  if (iDSnow == 3) isResolvedC = isHighMass;
1181  }
1182  return nHighMass;
1183 
1184 }
1185 
1186 //--------------------------------------------------------------------------
1187 
1188 // Set up an unresolved process, i.e. elastic or diffractive.
1189 
1190 bool PartonLevel::setupUnresolvedSys( Event& process, Event& event) {
1191 
1192  // No hard scale in event.
1193  process.scale( 0.);
1194 
1195  // Copy particles from process to event.
1196  for (int i = 0; i < process.size(); ++ i) event.append( process[i]);
1197 
1198  // Loop to find diffractively excited beams.
1199  for (iDS = 1; iDS < 4; ++iDS)
1200  if ( (iDS == 1 && isDiffA && !isResolvedA)
1201  || (iDS == 2 && isDiffB && !isResolvedB)
1202  || (iDS == 3 && isDiffC && !isResolvedC) ) {
1203  int iBeam = iDS + 2 + gammaOffset;
1204 
1205  // Diffractive mass. Boost and rotation from diffractive system
1206  // rest frame, aligned along z axis, to event cm frame.
1207  // Or to photon-photon(hadron) cm frame with photoproduction.
1208  double mDiff = process[iBeam].m();
1209  double m2Diff = mDiff * mDiff;
1210  Vec4 pDiffA = (iDS == 1) ? process[1 + gammaOffset].p()
1211  : process[1 + gammaOffset].p() - process[3 + gammaOffset].p();
1212  Vec4 pDiffB = (iDS == 2) ? process[2 + gammaOffset].p()
1213  : process[2 + gammaOffset].p() - process[4 + gammaOffset].p();
1214  RotBstMatrix MtoCM;
1215  MtoCM.fromCMframe( pDiffA, pDiffB);
1216 
1217  // Beam Particle used for flavour content kicked out by Pomeron.
1218  // Randomize for central diffraction; misses closed gluon loop case.
1219  bool beamSideA = (iDS == 1 || (iDS == 3 && rndmPtr->flat() < 0.5));
1220  BeamParticle* beamPtr = (beamSideA) ? beamAPtr : beamBPtr;
1221  if (iDS == 3) beamPtr = (beamSideA) ? beamPomAPtr : beamPomBPtr;
1222 
1223  // Pick quark or gluon kicked out and flavour subdivision.
1224  beamPtr->newValenceContent();
1225  bool gluonIsKicked = beamPtr->pickGluon(mDiff);
1226  int id1 = beamPtr->pickValence();
1227  int id2 = beamPtr->pickRemnant();
1228 
1229  // Find flavour masses. Scale them down if too big.
1230  double m1 = particleDataPtr->constituentMass(id1);
1231  double m2 = particleDataPtr->constituentMass(id2);
1232  if (m1 + m2 > 0.5 * mDiff) {
1233  double reduce = 0.5 * mDiff / (m1 + m2);
1234  m1 *= reduce;
1235  m2 *= reduce;
1236  }
1237 
1238  // If quark is kicked out, then trivial kinematics in rest frame.
1239  if (!gluonIsKicked) {
1240  double pAbs = sqrt( pow2(m2Diff - m1*m1 - m2*m2)
1241  - pow2(2. * m1 * m2) ) / (2. * mDiff);
1242  if (!beamSideA) pAbs = -pAbs;
1243  double e1 = (m2Diff + m1*m1 - m2*m2) / (2. * mDiff);
1244  double e2 = (m2Diff + m2*m2 - m1*m1) / (2. * mDiff);
1245  Vec4 p1( 0., 0., -pAbs, e1);
1246  Vec4 p2( 0., 0., pAbs, e2);
1247 
1248  // Boost and rotate to event cm frame.
1249  p1.rotbst( MtoCM);
1250  p2.rotbst( MtoCM);
1251 
1252  // Set colours.
1253  int col1, acol1, col2, acol2;
1254  if (particleDataPtr->colType(id1) == 1) {
1255  col1 = event.nextColTag();
1256  acol1 = 0;
1257  col2 = 0;
1258  acol2 = col1;
1259  } else {
1260  col1 = 0;
1261  acol1 = event.nextColTag();
1262  col2 = acol1;
1263  acol2 = 0;
1264  }
1265  // Update process colours to stay in step.
1266  process.nextColTag();
1267 
1268  // Store partons of diffractive system and mark system decayed.
1269  int iDauBeg = event.append( id1, 24, iBeam, 0, 0, 0, col1, acol1,
1270  p1, m1);
1271  int iDauEnd = event.append( id2, 63, iBeam, 0, 0, 0, col2, acol2,
1272  p2, m2);
1273  event[iBeam].statusNeg();
1274  event[iBeam].daughters(iDauBeg, iDauEnd);
1275 
1276  // If gluon is kicked out: share momentum between two remnants.
1277  } else {
1278  double m2Sys, zSys, pxSys, pySys, mTS1, mTS2;
1279  zSys = beamPtr->zShare(mDiff, m1, m2);
1280 
1281  // Provide relative pT kick in remnant. Construct (transverse) masses.
1282  pxSys = beamPtr->pxShare();
1283  pySys = beamPtr->pyShare();
1284  mTS1 = m1*m1 + pxSys*pxSys + pySys*pySys;
1285  mTS2 = m2*m2 + pxSys*pxSys + pySys*pySys;
1286  m2Sys = mTS1 / zSys + mTS2 / (1. - zSys);
1287 
1288  // Momentum of kicked-out massless gluon in diffractive rest frame.
1289  double pAbs = (m2Diff - m2Sys) / (2. * mDiff);
1290  double pLRem = (beamSideA) ? pAbs : -pAbs;
1291  Vec4 pG( 0., 0., -pLRem, pAbs);
1292  Vec4 pRem(0., 0., pLRem, mDiff - pAbs);
1293 
1294  // Momenta of the two beam remnant flavours. (Lightcone p+ = m_diff!)
1295  double e1 = 0.5 * (zSys * mDiff + mTS1 / (zSys * mDiff));
1296  double pL1 = 0.5 * (zSys * mDiff - mTS1 / (zSys * mDiff));
1297  if (!beamSideA) pL1 = -pL1;
1298  Vec4 p1(pxSys, pySys, pL1, e1);
1299  Vec4 p2 = pRem - p1;
1300 
1301  // Boost and rotate to event cm frame. Improve precision.
1302  pG.rotbst( MtoCM);
1303  p1.rotbst( MtoCM);
1304  p2.rotbst( MtoCM);
1305  pG.e( pG.pAbs());
1306 
1307  // Set colours.
1308  int colG, acolG, col1, acol1, col2, acol2;
1309  if (particleDataPtr->colType(id1) == 1) {
1310  col1 = event.nextColTag();
1311  acol1 = 0;
1312  colG = event.nextColTag();
1313  acolG = col1;
1314  col2 = 0;
1315  acol2 = colG;
1316  } else {
1317  col1 = 0;
1318  acol1 = event.nextColTag();
1319  colG = acol1;
1320  acolG = event.nextColTag();
1321  col2 = acolG;
1322  acol2 = 0;
1323  }
1324  // Update process colours to stay in step.
1325  process.nextColTag();
1326  process.nextColTag();
1327 
1328  // Store partons of diffractive system and mark system decayed.
1329  int iDauBeg = event.append( 21, 24, iBeam, 0, 0, 0, colG, acolG, pG, 0.);
1330  event.append( id1, 63, iBeam, 0, 0, 0, col1, acol1, p1, m1);
1331  int iDauEnd = event.append( id2, 63, iBeam, 0, 0, 0, col2, acol2,
1332  p2, m2);
1333  event[iBeam].statusNeg();
1334  event[iBeam].daughters(iDauBeg, iDauEnd);
1335  }
1336 
1337  // End loop over beams. Done.
1338  }
1339  return true;
1340 
1341 }
1342 
1343 //--------------------------------------------------------------------------
1344 
1345 // Set up the hard process(es), excluding subsequent resonance decays.
1346 
1347 void PartonLevel::setupHardSys( Event& process, Event& event) {
1348 
1349  // Incoming partons to hard process are stored in slots 3 and 4.
1350  int inS = 0;
1351  int inP = 3;
1352  int inM = 4;
1353 
1354  // Mother and last entry of diffractive system. Offset.
1355  int iDiffMot = iDS + 2;
1356  int iDiffDau = process.size() - 1;
1357  int nOffset = sizeEvent - sizeProcess;
1358 
1359  // Corrected information for hard diffraction.
1360  if (infoPtr->hasPomPsystem()) {
1361  iDiffMot = (isHardDiffB) ? 4 : 3;
1362  inS = iDiffMot;
1363  inP = 7;
1364  inM = 8;
1365  }
1366 
1367  // If photons inside leptons more entries in event.
1368  // Further offset if hard diffraction set up.
1369  int nGammaOffset = 0;
1370  int nGammaDiffOffset = 0;
1371  if ( beamHasResGamma || (beamHasGamma && isGammaHadronDir) ) {
1372  nGammaOffset = 2;
1373  if (!isDiff) {
1374  inP += nGammaOffset;
1375  inM += nGammaOffset;
1376  } else {
1377  iDiffMot += nGammaOffset;
1378  inS += nGammaOffset;
1379  }
1380  if ( (isHardDiffA || isHardDiffB) && hardDiffSet ) nGammaDiffOffset = 4;
1381  }
1382 
1383  // Resolved diffraction means more entries.
1384  if (isDiff) {
1385  inS = iDiffMot;
1386  inP = iDiffDau - 3;
1387  inM = iDiffDau - 2;
1388 
1389  // Diffractively excited particle described as Pomeron-hadron beams.
1390  event[inS].statusNeg();
1391  event[inS].daughters( inP - 2 + nOffset, inM - 2 + nOffset);
1392  }
1393 
1394  // If two hard interactions then find where second begins.
1395  int iBeginSecond = process.size();
1396  if (twoHard) {
1397  iBeginSecond = 5;
1398  while (process[iBeginSecond].status() != -21) ++iBeginSecond;
1399  }
1400 
1401  // If incoming partons are massive then recalculate to put them massless.
1402  if (process[inP].m() != 0. || process[inM].m() != 0.) {
1403  double pPos = process[inP].pPos() + process[inM].pPos();
1404  double pNeg = process[inP].pNeg() + process[inM].pNeg();
1405  process[inP].pz( 0.5 * pPos);
1406  process[inP].e( 0.5 * pPos);
1407  process[inP].m( 0.);
1408  process[inM].pz(-0.5 * pNeg);
1409  process[inM].e( 0.5 * pNeg);
1410  process[inM].m( 0.);
1411  }
1412 
1413  // Add incoming hard-scattering partons to list in beam remnants.
1414  double x1, x2;
1415  // If photon sub-beam calculate x with respect to photon beams.
1416  // With diffraction the beam offsets already taken care of.
1417  if ( (beamHasResGamma || (beamHasGamma && isGammaHadronDir) )
1418  && !isDiff ) {
1419  if ( hasGammaA)
1420  beamHadAPtr->append( 3, process[3].id(), beamHadAPtr->xGamma() );
1421  if ( hasGammaB)
1422  beamHadBPtr->append( 4, process[4].id(), beamHadBPtr->xGamma() );
1423  x1 = process[inP].pPos() / ( process[3 + nGammaDiffOffset].p()
1424  + process[4 + nGammaDiffOffset].p() ).mCalc();
1425  x2 = process[inM].pNeg() / ( process[3 + nGammaDiffOffset].p()
1426  + process[4 + nGammaDiffOffset].p() ).mCalc();
1427  } else {
1428  x1 = process[inP].pPos() / process[inS].m();
1429  x2 = process[inM].pNeg() / process[inS].m();
1430  }
1431  beamAPtr->append( inP + nOffset, process[inP].id(), x1);
1432  beamBPtr->append( inM + nOffset, process[inM].id(), x2);
1433 
1434  // Scale. Find whether incoming partons are valence or sea. Store.
1435  // When an x-dependent matter profile is used with nonDiffractive,
1436  // trial interactions mean that the valence/sea choice has already
1437  // been made and should be restored here.
1438  double scale = process.scale();
1439  int vsc1, vsc2;
1440  beamAPtr->xfISR( 0, process[inP].id(), x1, scale*scale);
1441  if (isNonDiff && (vsc1 = multiPtr->getVSC1()) != 0)
1442  (*beamAPtr)[0].companion(vsc1);
1443  else if (beamAPtr->isGamma()) vsc1 = beamAPtr->gammaValSeaComp(0);
1444  else vsc1 = beamAPtr->pickValSeaComp();
1445  beamBPtr->xfISR( 0, process[inM].id(), x2, scale*scale);
1446  if (isNonDiff && (vsc2 = multiPtr->getVSC2()) != 0)
1447  (*beamBPtr)[0].companion(vsc2);
1448  else if (beamBPtr->isGamma()) vsc2 = beamBPtr->gammaValSeaComp(0);
1449  else vsc2 = beamBPtr->pickValSeaComp();
1450  bool isVal1 = (vsc1 == -3);
1451  bool isVal2 = (vsc2 == -3);
1452  infoPtr->setValence( isVal1, isVal2);
1453 
1454  // Initialize info needed for subsequent sequential decays + showers.
1455  nHardDone = sizeProcess;
1456  iPosBefShow.resize( process.size() );
1457  fill( iPosBefShow.begin(), iPosBefShow.end(), 0);
1458 
1459  // Add the beam and hard subprocess partons to the event record.
1460  for (int i = sizeProcess; i < iBeginSecond; ++i) {
1461  if (process[i].mother1() > inM) break;
1462  int j = event.append(process[i]);
1463  iPosBefShow[i] = i;
1464 
1465  // Offset history if process and event not in step.
1466  if (nOffset != 0) {
1467  int iOrd = i - iBeginSecond + 7;
1468  if (iOrd == 1 || iOrd == 2)
1469  event[j].offsetHistory( 0, 0, 0, nOffset);
1470  else if (iOrd == 3 || iOrd == 4)
1471  event[j].offsetHistory( 0, nOffset, 0, nOffset);
1472  else if (iOrd == 5 || iOrd == 6)
1473  event[j].offsetHistory( 0, nOffset, 0, 0);
1474  }
1475 
1476  // Currently outgoing ones should not count as decayed.
1477  if (event[j].status() == -22) {
1478  event[j].statusPos();
1479  event[j].daughters(0, 0);
1480  }
1481 
1482  // Complete task of copying hard subsystem into event record.
1483  ++nHardDone;
1484  }
1485 
1486  // Store participating partons as first set in list of all systems.
1487  partonSystemsPtr->addSys();
1488  partonSystemsPtr->setInA(0, inP + nOffset);
1489  partonSystemsPtr->setInB(0, inM + nOffset);
1490  for (int i = inM + 1; i < nHardDone; ++i)
1491  partonSystemsPtr->addOut(0, i + nOffset);
1492  partonSystemsPtr->setSHat( 0,
1493  (event[inP + nOffset].p() + event[inM + nOffset].p()).m2Calc() );
1494  partonSystemsPtr->setPTHat( 0, scale);
1495 
1496  // Identify second hard process where applicable.
1497  // Since internally generated incoming partons are guaranteed massless.
1498  if (twoHard) {
1499  int inP2 = iBeginSecond;
1500  int inM2 = iBeginSecond + 1;
1501 
1502  // Add incoming hard-scattering partons to list in beam remnants.
1503  // Not valid if not in rest frame??
1504  x1 = process[inP2].pPos() / process[0].e();
1505  beamAPtr->append( inP2, process[inP2].id(), x1);
1506  x2 = process[inM2].pNeg() / process[0].e();
1507  beamBPtr->append( inM2, process[inM2].id(), x2);
1508 
1509  // Find whether incoming partons are valence or sea.
1510  scale = process.scaleSecond();
1511  beamAPtr->xfISR( 1, process[inP2].id(), x1, scale*scale);
1512  beamAPtr->pickValSeaComp();
1513  beamBPtr->xfISR( 1, process[inM2].id(), x2, scale*scale);
1514  beamBPtr->pickValSeaComp();
1515 
1516  // Add the beam and hard subprocess partons to the event record.
1517  for (int i = inP2; i < process.size(); ++ i) {
1518  int mother = process[i].mother1();
1519  if ( (mother > 2 && mother < inP2) || mother > inM2 ) break;
1520  event.append(process[i]);
1521  iPosBefShow[i] = i;
1522 
1523  // Currently outgoing ones should not count as decayed.
1524  if (event[i].status() == -22) {
1525  event[i].statusPos();
1526  event[i].daughters(0, 0);
1527  }
1528 
1529  // Complete task of copying hard subsystem into event record.
1530  ++nHardDone;
1531  }
1532 
1533  // Store participating partons as second set in list of all systems.
1534  partonSystemsPtr->addSys();
1535  partonSystemsPtr->setInA(1, inP2);
1536  partonSystemsPtr->setInB(1, inM2);
1537  for (int i = inM2 + 1; i < nHardDone; ++i)
1538  partonSystemsPtr->addOut(1, i);
1539  partonSystemsPtr->setSHat( 1,
1540  (event[inP2].p() + event[inM2].p()).m2Calc() );
1541  partonSystemsPtr->setPTHat( 1, scale);
1542 
1543  // End code for second hard process.
1544  }
1545 
1546  // Update event colour tag to maximum in whole process.
1547  int maxColTag = 0;
1548  for (int i = 0; i < process.size(); ++ i) {
1549  if (process[i].col() > maxColTag) maxColTag = process[i].col();
1550  if (process[i].acol() > maxColTag) maxColTag = process[i].acol();
1551  }
1552  event.initColTag(maxColTag);
1553 
1554  // Copy junctions from process to event.
1555  for (int iJun = 0; iJun < process.sizeJunction(); ++iJun) {
1556  // Resonance decay products may not have been copied from process to
1557  // event yet. If so, do not add junctions associated with decays yet.
1558  int kindJunction = process.kindJunction(iJun);
1559  bool doCopy = true;
1560  // For junction types <= 4, check if final-state legs were copied.
1561  if (kindJunction <= 4) {
1562  int iLegF1 = (kindJunction - 1) / 2;
1563  for (int iLeg = iLegF1; iLeg <= 2; ++iLeg) {
1564  bool colFound = false;
1565  for (int i = inM + 1; i < event.size(); ++i) {
1566  int col = (kindJunction % 2 == 1) ? event[i].col() : event[i].acol();
1567  if (col == process.colJunction(iJun,iLeg)) colFound = true;
1568  }
1569  if (!colFound) doCopy = false;
1570  }
1571  }
1572  if (doCopy) {
1573  event.appendJunction( process.getJunction(iJun));
1574  }
1575  }
1576 
1577  // Done.
1578 }
1579 
1580 //--------------------------------------------------------------------------
1581 
1582 // Set up the event for subsequent resonance decays and showers.
1583 
1584 void PartonLevel::setupShowerSys( Event& process, Event& event) {
1585 
1586  // Reset event record to only contain line 0.
1587  event.clear();
1588  event.append( process[0]);
1589 
1590  // Initialize info needed for subsequent sequential decays + showers.
1591  nHardDone = 1;
1592  iPosBefShow.resize( process.size());
1593  fill( iPosBefShow.begin(), iPosBefShow.end(), 0);
1594 
1595  // Add the hard subprocess partons to the event record.
1596  for (int i = 1; i < process.size(); ++i) {
1597  if (process[i].mother1() > 0) break;
1598  int j = event.append(process[i]);
1599  iPosBefShow[i] = i;
1600 
1601  // Currently outgoing ones should not count as decayed.
1602  if (event[j].status() == -22) {
1603  event[j].statusPos();
1604  event[j].daughters(0, 0);
1605  }
1606 
1607  // Complete task of copying hard subsystem into event record.
1608  ++nHardDone;
1609  }
1610 
1611  // Store participating partons as first set in list of all systems.
1612  partonSystemsPtr->clear();
1613  partonSystemsPtr->addSys();
1614  for (int i = 1; i < nHardDone; ++i) partonSystemsPtr->addOut(0, i);
1615  partonSystemsPtr->setSHat( 0, pow2(process[0].m()) );
1616  partonSystemsPtr->setPTHat( 0, 0.5 * process[0].m() );
1617 
1618  // Copy junctions from process to event.
1619  for (int iJun = 0; iJun < process.sizeJunction(); ++iJun) {
1620  // Resonance decay products may not have been copied from process to
1621  // event yet. If so, do not add junctions associated with decays yet.
1622  int kindJunction = process.kindJunction(iJun);
1623  bool doCopy = true;
1624  // For junction types <= 4, check if final-state legs were copied.
1625  if (kindJunction <= 4) {
1626  int iLegF1 = (kindJunction - 1) / 2;
1627  for (int iLeg = iLegF1; iLeg <= 2; ++iLeg) {
1628  bool colFound = false;
1629  for (int i = 1; i < event.size(); ++i) {
1630  int col = (kindJunction % 2 == 1) ? event[i].col() : event[i].acol();
1631  if (col == process.colJunction(iJun,iLeg)) colFound = true;
1632  }
1633  if (!colFound) doCopy = false;
1634  }
1635  }
1636  if (doCopy) {
1637  event.appendJunction( process.getJunction(iJun));
1638  }
1639  }
1640 
1641  // Done.
1642 }
1643 
1644 //--------------------------------------------------------------------------
1645 
1646 // Resolved diffraction: replace full event with diffractive subsystem.
1647 
1648 void PartonLevel::setupResolvedDiff( Event& process) {
1649 
1650  // Mother and last entry of diffractive system.
1651  int iDiffMot = iDS + 2 + gammaOffset;
1652  int iDiffDau = process.size() - 1;
1653 
1654  // Diffractively excited particle to be replaced by Pomeron-hadron beams
1655  // (or Pomeron-Pomeron beams for central diffraction).
1656  process[iDiffMot].statusNeg();
1657  process[iDiffMot].daughters( iDiffDau + 1, iDiffDau + 2);
1658 
1659  // Diffractive system mass.
1660  double mDiff = process[iDiffMot].m();
1661  double m2Diff = mDiff * mDiff;
1662 
1663  // Set up Pomeron-proton or Pomeron-Pomeron system as if it were
1664  // the complete collision. Set Pomeron "beam particle" massless.
1665  int idDiffA = (iDS == 1) ? process[1 + gammaOffset].id() : 990;
1666  int idDiffB = (iDS == 2) ? process[2 + gammaOffset].id() : 990;
1667  double mDiffA = (iDS == 1) ? process[1 + gammaOffset].m() : 0.;
1668  double mDiffB = (iDS == 2) ? process[2 + gammaOffset].m() : 0.;
1669  if (idDiffA == 22 && infoPtr->isVMDstateA()) {
1670  idDiffA = (iDS == 1) ? infoPtr->idVMDA() : 990;
1671  mDiffA = (iDS == 1) ? infoPtr->mVMDA() : 0.;
1672  }
1673  if (idDiffB == 22 && infoPtr->isVMDstateB()) {
1674  idDiffB = (iDS == 2) ? infoPtr->idVMDB() : 990;
1675  mDiffB = (iDS == 2) ? infoPtr->mVMDB() : 0.;
1676  }
1677  double m2DiffA = mDiffA * mDiffA;
1678  double m2DiffB = mDiffB * mDiffB;
1679  double eDiffA = 0.5 * (m2Diff + m2DiffA - m2DiffB) / mDiff;
1680  double eDiffB = 0.5 * (m2Diff + m2DiffB - m2DiffA) / mDiff;
1681  double pzDiff = 0.5 * sqrtpos( pow2(m2Diff - m2DiffA - m2DiffB)
1682  - 4. * m2DiffA * m2DiffB ) / mDiff;
1683  process.append( idDiffA, 13, iDiffMot, 0, 0, 0, 0, 0,
1684  0., 0., pzDiff, eDiffA, mDiffA);
1685  process.append( idDiffB, 13, iDiffMot, 0, 0, 0, 0, 0,
1686  0., 0., -pzDiff, eDiffB, mDiffB);
1687 
1688  // Reassign beam pointers to refer to subsystem effective beams.
1689  // If VMD state in gamma, then use VMD instead of gamma as beam pointer.
1690  beamAPtr = (iDS == 1) ? beamHadAPtr : beamPomAPtr;
1691  beamBPtr = (iDS == 2) ? beamHadBPtr : beamPomBPtr;
1692  if (infoPtr->isVMDstateA())
1693  beamAPtr = (iDS == 1) ? beamVMDAPtr : beamPomAPtr;
1694  if (infoPtr->isVMDstateB())
1695  beamBPtr = (iDS == 2) ? beamVMDBPtr : beamPomBPtr;
1696 
1697  // Pretend that the diffractive system is the whole collision.
1698  eCMsave = infoPtr->eCM();
1699  infoPtr->setECM( mDiff);
1700  beamAPtr->newPzE( pzDiff, eDiffA);
1701  beamBPtr->newPzE( -pzDiff, eDiffB);
1702 
1703  // Keep track of pomeron momentum fraction.
1704  if ( beamAPtr->id() == 990 )
1705  beamAPtr->xPom(pow2(mDiff/eCMsave));
1706  if ( beamBPtr->id() == 990 )
1707  beamBPtr->xPom(pow2(mDiff/eCMsave));
1708 
1709  // Beams not found in normal slots 1 and 2.
1710  int beamOffset = (sizeEvent > 0) ? sizeEvent - 1 : 4;
1711 
1712  // Reassign beam pointers in other classes.
1713  timesPtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
1714  timesDecPtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
1715  spacePtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
1716  remnants.reassignBeamPtrs( beamAPtr, beamBPtr, iDS);
1717  if (colourReconnectionPtr)
1718  colourReconnectionPtr->reassignBeamPtrs( beamAPtr, beamBPtr);
1719 
1720  // Reassign multiparton interactions pointer to right object.
1721  if (iDS == 1) multiPtr = &multiSDA;
1722  else if (iDS == 2) multiPtr = &multiSDB;
1723  else multiPtr = &multiCD;
1724 
1725 }
1726 
1727 //--------------------------------------------------------------------------
1728 
1729 // Resolved diffraction: restore to original behaviour.
1730 
1731 void PartonLevel::leaveResolvedDiff( int iHardLoop, Event& process,
1732  Event& event) {
1733 
1734  // Reconstruct boost and rotation to event cm frame.
1735  // In case of photoproduction boost to photon-photon(hadrom) cm frame.
1736  Vec4 pDiffA = (iDS == 1) ? process[1 + gammaOffset].p()
1737  : process[1 + gammaOffset].p() - process[3 + gammaOffset].p();
1738  Vec4 pDiffB = (iDS == 2) ? process[2 + gammaOffset].p()
1739  : process[2 + gammaOffset].p() - process[4 + gammaOffset].p();
1740  RotBstMatrix MtoCM;
1741  MtoCM.fromCMframe( pDiffA, pDiffB);
1742 
1743  // Perform rotation and boost on diffractive system.
1744  for (int i = sizeProcess; i < process.size(); ++i)
1745  process[i].rotbst( MtoCM);
1746  int iFirst = (iHardLoop == 1) ? 5 + sizeEvent - sizeProcess + gammaOffset
1747  : sizeEvent;
1748  if (isDiffC) iFirst = 6 + sizeEvent - sizeProcess;
1749  for (int i = iFirst; i < event.size(); ++i)
1750  event[i].rotbst( MtoCM);
1751 
1752  // Restore cm energy.
1753  infoPtr->setECM( eCMsave);
1754  beamAPtr->newPzE( event[1].pz(), event[1].e());
1755  beamBPtr->newPzE( event[2].pz(), event[2].e());
1756  // Keeping track of pomeron momentum fraction.
1757  beamAPtr->xPom();
1758  beamBPtr->xPom();
1759 
1760  // Restore beam pointers to incoming hadrons.
1761  beamAPtr = beamHadAPtr;
1762  beamBPtr = beamHadBPtr;
1763 
1764  // Reassign beam pointers in other classes.
1765  timesPtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
1766  timesDecPtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
1767  spacePtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
1768  remnants.reassignBeamPtrs( beamAPtr, beamBPtr, 0);
1769  if (colourReconnectionPtr)
1770  colourReconnectionPtr->reassignBeamPtrs( beamAPtr, beamBPtr);
1771 
1772  // Restore multiparton interactions pointer to default object.
1773  multiPtr = &multiMB;
1774 
1775 }
1776 
1777 //--------------------------------------------------------------------------
1778 
1779 // Set up special handling of hard diffraction.
1780 
1781 void PartonLevel::setupHardDiff( Event& process) {
1782 
1783  // Create a temporary event record holding the info of the hard process.
1784  Event tmpProcess = process;
1785  process.clear();
1786  process.scale(tmpProcess.scale());
1787 
1788  // Add the first three entries: system + incoming beams.
1789  for (int iEntry = 0; iEntry < 3; ++iEntry)
1790  process.append( tmpProcess[iEntry]);
1791 
1792  // Get system info and calculate diffractive system mass.
1793  double eCM = infoPtr->eCM();
1794  double sNow = eCM * eCM;
1795  double xPom = (isHardDiffB) ? infoPtr->xPomeronA()
1796  : infoPtr->xPomeronB();
1797  double phiPom = 2. * M_PI * rndmPtr->flat();
1798  double thetaPom = (isHardDiffB) ? hardDiffraction.getThetaPomeronA()
1799  : hardDiffraction.getThetaPomeronB();
1800  double m2Diff = xPom * sNow;
1801  double mDiff = sqrt(m2Diff);
1802 
1803  // Add possible photon beams from leptons.
1804  if (beamAhasGamma || beamBhasGamma) {
1805  process.append( tmpProcess[3]);
1806  process.append( tmpProcess[4]);
1807  }
1808 
1809  // Particle masses and ids.
1810  // If isHardDiffB (or A) then m1 + m2 -> m1 + mDiff (or mDiff + m2).
1811  // Change an elastically scattered gamma to a rho, since a Pomeron only
1812  // can be taken from a VMD particle, not from the gamma proper.
1813  int id1 = process[1 + gammaOffset].id();
1814  int id2 = process[2 + gammaOffset].id();
1815  int idEl = (isHardDiffB) ? id1 : id2;
1816  if (idEl == 22) idEl = 113;
1817  int idX = (isHardDiffB) ? id2 : id1;
1818  double m1 = process[1 + gammaOffset].m();
1819  double m2 = process[2 + gammaOffset].m();
1820  double mEl = (isHardDiffB) ? m1 : m2;
1821 
1822  // Evaluate momenta of outgoing particles, initially along beam axis.
1823  // Special handling for rho with too high a Breit-Wigner-selected mass,
1824  // where kinematics failures leads to retries.
1825  double m3, m4, s3, s4, lambda34;
1826  if (idEl == 113) {
1827  int nTry = 0;
1828  do {
1829  mEl = particleDataPtr->mSel(113);
1830  m3 = (isHardDiffB) ? mEl : mDiff;
1831  m4 = (isHardDiffA) ? mEl : mDiff;
1832  s3 = pow2(m3);
1833  s4 = pow2(m4);
1834  lambda34 = sqrtpos( pow2( sNow - s3 - s4) - 4. * s3 * s4 );
1835  ++nTry;
1836  } while (lambda34 <= 0. && nTry < 10);
1837  } else {
1838  m3 = (isHardDiffB) ? mEl : mDiff;
1839  m4 = (isHardDiffA) ? mEl : mDiff;
1840  s3 = pow2(m3);
1841  s4 = pow2(m4);
1842  lambda34 = sqrtpos( pow2( sNow - s3 - s4) - 4. * s3 * s4 );
1843  }
1844  double pAbs = 0.5 * lambda34 / eCM;
1845  Vec4 p3 = Vec4( 0., 0., pAbs, 0.5 * (sNow + s3 - s4) / eCM);
1846  Vec4 p4 = Vec4( 0., 0., -pAbs, 0.5 * (sNow + s4 - s3) / eCM);
1847 
1848  // Take copies for later longitudinal boost; then rotate outgoing beams.
1849  Vec4 pD3 = p3;
1850  Vec4 pD4 = p4;
1851  p3.rot( thetaPom, phiPom);
1852  p4.rot( thetaPom, phiPom);
1853 
1854  // Append intermediate states to the event record.
1855  int status3 = (isHardDiffB) ? 14 : 15;
1856  int status4 = (isHardDiffA) ? 14 : 15;
1857  int sign = (idX > 0) ? 1 : -1;
1858  int idDiff = (idX == 22) ? 9900020 : sign * 9902210;
1859  int id3 = (isHardDiffB) ? idEl : idDiff;
1860  int id4 = (isHardDiffA) ? idEl : idDiff;
1861  process.append( id3, status3, 1 + gammaOffset, 0, 0, 0, 0, 0, p3, m3);
1862  process.append( id4, status4, 2 + gammaOffset, 0, 0, 0, 0, 0, p4, m4);
1863 
1864  // Correct event record history accordingly.
1865  process[1 + gammaOffset].daughters(3 + gammaOffset, 0);
1866  process[2 + gammaOffset].daughters(4 + gammaOffset, 0);
1867  int iDiffMot = (isHardDiffB) ? 4 + gammaOffset: 3 + gammaOffset;
1868  int iDiffRad = process.size() - 1;
1869  process[iDiffMot].statusNeg();
1870  process[iDiffMot].daughters( iDiffRad + 1, iDiffRad + 2);
1871 
1872  // Set up Pomeron-particle system as if it were the complete collision.
1873  // Set Pomeron "beam particle" massless.
1874  int idDiffA = (isHardDiffB) ? 990 : process[1 + gammaOffset].id();
1875  int idDiffB = (isHardDiffA) ? 990 : process[2 + gammaOffset].id();
1876  double mDiffA = (isHardDiffB) ? 0. : process[1 + gammaOffset].m();
1877  double mDiffB = (isHardDiffA) ? 0. : process[2 + gammaOffset].m();
1878  double m2DiffA = mDiffA * mDiffA;
1879  double m2DiffB = mDiffB * mDiffB;
1880  double eDiffA = 0.5 * (m2Diff + m2DiffA - m2DiffB) / mDiff;
1881  double eDiffB = 0.5 * (m2Diff + m2DiffB - m2DiffA) / mDiff;
1882  double pzDiff = 0.5 * sqrtpos( pow2(m2Diff - m2DiffA - m2DiffB)
1883  - 4. * m2DiffA * m2DiffB ) / mDiff;
1884  process.append( idDiffA, 13, iDiffMot, 0, 0, 0, 0, 0,
1885  0., 0., pzDiff, eDiffA, mDiffA);
1886  process.append( idDiffB, 13, iDiffMot, 0, 0, 0, 0, 0,
1887  0., 0., -pzDiff, eDiffB, mDiffB);
1888 
1889  // Append hard process.
1890  vector<int> hardParton;
1891  for (int iHard = 3 + gammaOffset; iHard < tmpProcess.size(); ++iHard)
1892  hardParton.push_back( process.append(tmpProcess[iHard]) );
1893 
1894  // Boost the hard partons in z-direction (from pp to Pp system).
1895  Vec4 pDiffA = (isHardDiffA) ? process[1 + gammaOffset].p()
1896  : process[1 + gammaOffset].p() - pD3;
1897  Vec4 pDiffB = (isHardDiffB) ? process[2 + gammaOffset].p()
1898  : process[2 + gammaOffset].p() - pD4;
1899  RotBstMatrix MtoCM;
1900  MtoCM.toCMframe( pDiffA, pDiffB);
1901  for (unsigned int i = 0; i < hardParton.size(); ++i)
1902  process[hardParton[i]].rotbst(MtoCM);
1903 
1904  // Change mothers and daughters after appending hard process.
1905  for (unsigned int j = 0; j < hardParton.size(); ++j) {
1906  int mother1 = (tmpProcess[j + 3 + gammaOffset].mother1() == 0)
1907  ? 0 : tmpProcess[j + 3 + gammaOffset].mother1() + 4;
1908  int mother2 = (tmpProcess[j + 3 + gammaOffset].mother2() == 0)
1909  ? 0 : tmpProcess[j + 3 + gammaOffset].mother2() + 4;
1910  int daughter1 = (tmpProcess[j + 3 + gammaOffset].daughter1() == 0)
1911  ? 0 : tmpProcess[j + 3 + gammaOffset].daughter1() + 4;
1912  int daughter2 = (tmpProcess[j + 3 + gammaOffset].daughter2() == 0)
1913  ? 0 : tmpProcess[j + 3 + gammaOffset].daughter2() + 4;
1914  process[hardParton[j]].mothers( mother1,mother2);
1915  process[hardParton[j]].daughters( daughter1, daughter2);
1916  }
1917 
1918  // Search for pomeron and particle with status codes 13 (beam-inside-beam).
1919  int iPomeron = 0;
1920  int iPrtcl = 0;
1921  for (int i = 0; i < process.size(); ++i) {
1922  if (process[i].id() == 990 && process[i].status() == 13) iPomeron = i;
1923  if (process[i].idAbs() == idX && process[i].status() == 13) iPrtcl = i;
1924  }
1925 
1926  if (isHardDiffB) {
1927  process[iPomeron].daughters(hardParton[0], 0);
1928  process[iPrtcl].daughters(hardParton[1],0);
1929  process[hardParton[0]].mothers(iPomeron,0);
1930  process[hardParton[1]].mothers(iPrtcl, 0);
1931  } else {
1932  process[iPomeron].daughters(hardParton[1], 0);
1933  process[iPrtcl].daughters(hardParton[0],0);
1934  process[hardParton[1]].mothers(iPomeron,0);
1935  process[hardParton[0]].mothers(iPrtcl, 0);
1936  }
1937 
1938  // Negate status of Pomeron and proton
1939  process[iPomeron].statusNeg();
1940  process[iPrtcl].statusNeg();
1941 
1942  // Change state of system to unresolved to avoid aborting from Pythia.
1943  infoPtr->setHasUnresolvedBeams( true);
1944 
1945  // Reassign beam pointers to refer to subsystem effective beams.
1946  // If gamma-in-lepton change to beamGamPtr.
1947  beamAPtr = (isHardDiffB) ? beamPomAPtr
1948  : (beamAhasGamma ? beamGamAPtr : beamHadAPtr);
1949  beamBPtr = (isHardDiffA) ? beamPomBPtr
1950  : (beamBhasGamma ? beamGamBPtr : beamHadBPtr);
1951 
1952  // Pretend that the diffractive system is the whole collision.
1953  eCMsave = infoPtr->eCM();
1954  infoPtr->setECM( mDiff);
1955  beamAPtr->newPzE( pzDiff, eDiffA);
1956  beamBPtr->newPzE( -pzDiff, eDiffB);
1957 
1958  // Beams not found in normal slots 1 and 2.
1959  int beamOffset = 4 + gammaOffset;
1960  int beamRemnOffset = (isHardDiffB) ? 2 : 1;
1961 
1962  // Reassign beam pointers in other classes.
1963  timesPtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
1964  timesDecPtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
1965  spacePtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
1966  remnants.reassignBeamPtrs( beamAPtr, beamBPtr, beamRemnOffset);
1967  if (colourReconnectionPtr)
1968  colourReconnectionPtr->reassignBeamPtrs( beamAPtr, beamBPtr);
1969 
1970  // Reassign multiparton interactions pointer to right object.
1971  if (isHardDiffA) multiPtr = &multiSDA;
1972  else if (isHardDiffB) multiPtr = &multiSDB;
1973 
1974  // Set the beam offset for MPIs.
1975  multiPtr->setBeamOffset(beamOffset);
1976 
1977  // Hard diffractive system set.
1978  hardDiffSet = true;
1979 
1980  // Done.
1981  infoPtr->setHasPomPsystem( true);
1982 
1983 }
1984 
1985 //--------------------------------------------------------------------------
1986 
1987 // Leave special handling of hard diffraction.
1988 
1989 void PartonLevel::leaveHardDiff( Event& process, Event& event,
1990  bool physical) {
1991 
1992  // Calculate kinematics only for physical events.
1993  if (physical) {
1994 
1995  // Reconstruct boost and rotation to event cm frame.
1996  Vec4 pDiffA = (isHardDiffA) ? process[1 + gammaOffset].p()
1997  : process[1 + gammaOffset].p() - process[3 + gammaOffset].p();
1998  Vec4 pDiffB = (isHardDiffB) ? process[2 + gammaOffset].p()
1999  : process[2 + gammaOffset].p() - process[4 + gammaOffset].p();
2000  RotBstMatrix MtoCM;
2001  MtoCM.fromCMframe( pDiffA, pDiffB);
2002 
2003  // Perform rotation and boost on diffractive system.
2004  for (int i = 5 + gammaOffset; i < process.size(); ++i)
2005  process[i].rotbst( MtoCM);
2006  for (int i = 5 + gammaOffset; i < event.size(); ++i)
2007  event[i].rotbst( MtoCM);
2008 
2009  // Reset beam energies.
2010  beamAPtr->newPzE( event[1 + gammaOffset].pz(), event[1 + gammaOffset].e());
2011  beamBPtr->newPzE( event[2 + gammaOffset].pz(), event[2 + gammaOffset].e());
2012 
2013  }
2014 
2015  // Clear diffractive info.
2016  isHardDiffA = isHardDiffB = isHardDiff = false;
2017 
2018  // Restore cm energy.
2019  infoPtr->setECM( eCMsave);
2020 
2021  // Restore beam pointers to incoming hadrons.
2022  // If gamma-in-lepton need to change to beamGamPtr.
2023  beamAPtr = beamAhasGamma ? beamGamAPtr : beamHadAPtr;
2024  beamBPtr = beamBhasGamma ? beamGamBPtr : beamHadBPtr;
2025 
2026  // Reassign beam pointers in other classes.
2027  timesPtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
2028  timesDecPtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
2029  spacePtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
2030  remnants.reassignBeamPtrs( beamAPtr, beamBPtr, 0);
2031  if (colourReconnectionPtr)
2032  colourReconnectionPtr->reassignBeamPtrs( beamAPtr, beamBPtr);
2033 
2034  // Reset the beam offset to normal.
2035  multiPtr->setBeamOffset(0);
2036 
2037  // Restore multiparton interactions pointer to default object.
2038  multiPtr = &multiMB;
2039 
2040 }
2041 
2042 //--------------------------------------------------------------------------
2043 
2044 // Replace full event with photon-photon/hadron subsystem.
2045 // Use the sampled kinematics to construct the momenta.
2046 
2047 bool PartonLevel::setupResolvedLeptonGamma( Event& process) {
2048 
2049  // Save the collision energy of the lepton system.
2050  eCMsaveGamma = infoPtr->eCM();
2051 
2052  // Beams not found in normal slots 1 and 2 but 2 step forward.
2053  int beamOffset = 2;
2054  int iBeamA = 3;
2055  int iBeamB = 4;
2056  gammaOffset = beamOffset;
2057 
2058  // Retrieve the information set on GammaKinematics. Use sHat for 2->1.
2059  double mGmGm = (infoPtr->nFinal() > 1) || (gammaModeEvent != 4)
2060  ? infoPtr->eCMsub() : sqrt( infoPtr->sHat());
2061  double m2GmGm = pow2(mGmGm);
2062 
2063  // Massless photons here, virtualities added after parton level evolution.
2064  double m2Gamma1 = hasGammaA ? 0. : pow2(beamAPtr->m());
2065  double m2Gamma2 = hasGammaB ? 0. : pow2(beamBPtr->m());
2066 
2067  // Derive the new momenta in the CM frame of the gamma-gamma system.
2068  double eGamA = 0.5 * (m2GmGm + m2Gamma1 - m2Gamma2) / mGmGm;
2069  double eGamB = 0.5 * (m2GmGm + m2Gamma2 - m2Gamma1) / mGmGm;
2070  double pzGam = 0.5 * sqrtpos( pow2(m2GmGm - m2Gamma1 - m2Gamma2)
2071  - 4. * m2Gamma1 * m2Gamma2 ) / mGmGm;
2072  Vec4 pGammaANew( 0, 0, pzGam, eGamA);
2073  Vec4 pGammaBNew( 0, 0, -pzGam, eGamB);
2074 
2075  // Set the beam momenta to new rest frame of gamma-gamma.
2076  beamGamAPtr->newPzE( pzGam, eGamA);
2077  beamGamBPtr->newPzE( -pzGam, eGamB);
2078 
2079  // Save the original photon momenta.
2080  Vec4 pGammaA = process[iBeamA].p();
2081  Vec4 pGammaB = process[iBeamB].p();
2082 
2083  // Boost the process to gamma-gamma rest frame (no kT added yet).
2084  // For diffractive and elastic boost only final state particles.
2085  RotBstMatrix MtoGammaGamma;
2086  MtoGammaGamma.toCMframe( pGammaA, pGammaB);
2087  if (!isDiff && !isElastic) process.rotbst(MtoGammaGamma);
2088  else {
2089  for (int i = 0; i < 5; ++i) process[i].rotbst(MtoGammaGamma);
2090  }
2091 
2092  // Set momenta of photons according to new m2GmGm.
2093  process[iBeamA].p(pGammaANew);
2094  process[iBeamB].p(pGammaBNew);
2095 
2096  // If another beam not a photon set the mass as well.
2097  if ( !hasGammaA && !(beamBPtr->getGammaMode() == 2) )
2098  process[iBeamA].m( sqrt(m2Gamma1) );
2099  if ( !hasGammaB && !(beamAPtr->getGammaMode() == 2) )
2100  process[iBeamB].m( sqrt(m2Gamma2) );
2101 
2102  // Done for direct-direct and elastic processes since no need to reassign
2103  // beams.
2104  if ( (gammaModeEvent == 4) || isElastic ) return true;
2105 
2106  // Copy sampled VMD states to photon beams when necessary.
2107  if (infoPtr->isVMDstateA() ) beamGamAPtr->setVMDstate(true,
2108  infoPtr->idVMDA(), infoPtr->mVMDA(), infoPtr->scaleVMDA(), false);
2109  if (infoPtr->isVMDstateB() ) beamGamBPtr->setVMDstate(true,
2110  infoPtr->idVMDB(), infoPtr->mVMDB(), infoPtr->scaleVMDB(), false);
2111 
2112  // Reassign beam pointers to refer to subsystem effective beams.
2113  if ( hasGammaA) beamAPtr = beamGamAPtr;
2114  else beamAPtr->newPzE( pzGam, eGamA);
2115  if ( hasGammaB) beamBPtr = beamGamBPtr;
2116  else beamBPtr->newPzE( -pzGam, eGamB);
2117 
2118  // Change state of system to unresolved to avoid aborting from Pythia.
2119  if ( (beamAhasResGamma && (!beamBhasResGamma && hasGammaB))
2120  || ( (!beamAhasResGamma && hasGammaA) && beamBhasResGamma) )
2121  infoPtr->setHasUnresolvedBeams( true);
2122 
2123  // Pretend that the gamma-gamma system is the whole collision.
2124  infoPtr->setECM( mGmGm);
2125 
2126  // Reassign beam pointers in other classes.
2127  timesPtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
2128  timesDecPtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
2129  spacePtr->reassignBeamPtrs( beamAPtr, beamBPtr, beamOffset);
2130  remnants.reassignBeamPtrs( beamAPtr, beamBPtr, 0);
2131  if (colourReconnectionPtr)
2132  colourReconnectionPtr->reassignBeamPtrs( beamAPtr, beamBPtr);
2133 
2134  // Set the MPI to point the gamma-gamma system.
2135  multiPtr = &multiGmGm;
2136  multiPtr->setBeamOffset(beamOffset);
2137 
2138  // Done.
2139  return true;
2140 
2141 }
2142 
2143 //--------------------------------------------------------------------------
2144 
2145 // Move back to CM-frame of colliding leptons. Add also the scatterd lepton
2146 // if remnants are constructed.
2147 
2148 void PartonLevel::leaveResolvedLeptonGamma( Event& process, Event& event,
2149  bool physical) {
2150 
2151  // Restore beam pointers to incoming leptons.
2152  if ( hasGammaA) beamAPtr = beamHadAPtr;
2153  if ( hasGammaB) beamBPtr = beamHadBPtr;
2154 
2155  // Restore cm energy.
2156  infoPtr->setECM( eCMsaveGamma);
2157 
2158  // Set the new kinematics only for physical events.
2159  if (physical) {
2160 
2161  // Find the momenta of incoming leptons and photons.
2162  Vec4 pLeptonA = process[1].p();
2163  Vec4 pLeptonB = process[2].p();
2164 
2165  // Momenta for scattered leptons to be set later according to final state.
2166  Vec4 pLepton1scat;
2167  Vec4 pLepton2scat;
2168 
2169  // Skip the boost of the extra intermediate photon in hard diffraction.
2170  int iSkipHardDiff = -1;
2171 
2172  // Reconstruct boost and rotation to event cm frame.
2173  RotBstMatrix MtoLeptonLepton;
2174  MtoLeptonLepton.toCMframe( pLeptonA, pLeptonB);
2175 
2176  // Boost event to cm frame.
2177  process.rotbst(MtoLeptonLepton);
2178  event.rotbst(MtoLeptonLepton);
2179 
2180  // Get the masses of beam particles.
2181  double m2BeamA = pow2( beamAPtr->m());
2182  double m2BeamB = pow2( beamBPtr->m());
2183 
2184  // Get the original collision energy and derive the lepton energies in CMS.
2185  double sCM = infoPtr->s();
2186  double eCM2A = 0.25 * pow2(sCM + m2BeamA - m2BeamB) / sCM;
2187  double eCM2B = 0.25 * pow2(sCM - m2BeamA + m2BeamB) / sCM;
2188 
2189  // Find the current momenta of photons.
2190  Vec4 pGamma1Orig = process[3].p();
2191  Vec4 pGamma2Orig = process[4].p();
2192  Vec4 pGamma1 = pGamma1Orig;
2193  Vec4 pGamma2 = pGamma2Orig;
2194  double mGamma1 = sqrt(m2BeamA);
2195  double mGamma2 = sqrt(m2BeamB);
2196 
2197  // Separate treatment for 2 -> 1 processes with two direct gammas
2198  // to preserve sampled invariant mass. Corresponds to the usual
2199  // beam remnant handling.
2200  if ( (infoPtr->nFinal() == 1) && (gammaModeEvent == 4)
2201  && hasGammaA && hasGammaB ) {
2202 
2203  // Save the virtualities and transverse mometum of the photons.
2204  mGamma1 = -sqrt( beamAPtr->Q2Gamma());
2205  mGamma2 = -sqrt( beamBPtr->Q2Gamma());
2206  double kTxA = beamAPtr->gammaKTx();
2207  double kTyA = beamAPtr->gammaKTy();
2208  double kTxB = beamBPtr->gammaKTx();
2209  double kTyB = beamBPtr->gammaKTy();
2210 
2211  // Derive transverse mass and new sHat.
2212  double mT2A = pow2( beamAPtr->gammaKT() ) - pow2(mGamma1);
2213  double mT2B = pow2( beamBPtr->gammaKT() ) - pow2(mGamma2);
2214  double sHatBef = infoPtr->sHat();
2215  double sHatAft = infoPtr->sHat() + pow2(kTxA + kTxB)
2216  + pow2(kTyA + kTyB);
2217  double lambda = pow2(sHatAft) + pow2(mT2A) + pow2(mT2B)
2218  - 2. * ( sHatAft * (mT2A + mT2B) + mT2A * mT2B );
2219  double kz2New = 0.25 * lambda / sHatAft;
2220 
2221  // Photon momenta in CM frame.
2222  Vec4 pGamma1New(kTxA, kTyA, sqrt(kz2New), sqrt(kz2New + mT2A) );
2223  Vec4 pGamma2New(kTxB, kTyB, -sqrt(kz2New), sqrt(kz2New + mT2B) );
2224 
2225  // Boost and rotate the new photon momenta.
2226  RotBstMatrix MfromGmGmOrig;
2227  MfromGmGmOrig.toCMframe( pGamma1Orig, pGamma2Orig);
2228  MfromGmGmOrig.invert();
2229  pGamma1New.rotbst(MfromGmGmOrig);
2230  pGamma2New.rotbst(MfromGmGmOrig);
2231 
2232  // Set the new photon momenta.
2233  pGamma1 = pGamma1New;
2234  pGamma2 = pGamma2New;
2235 
2236  // Modify the mass and momenta in event record.
2237  event[3].p( pGamma1);
2238  event[3].m( mGamma1);
2239  event[4].p( pGamma2);
2240  event[4].m( mGamma2);
2241 
2242  // Light-cone momentum removed by the photons.
2243  double rescale = sqrt(sHatAft / sHatBef);
2244  double wPosBef = beamAPtr->xGamma() * infoPtr->eCM();
2245  double wNegBef = beamBPtr->xGamma() * infoPtr->eCM();
2246 
2247  // Transverse mass of the leptons and invariant mass left for remnants.
2248  double w2BeamA = pow2(beamAPtr->gammaKT()) + m2BeamA;
2249  double w2BeamB = pow2(beamBPtr->gammaKT()) + m2BeamB;
2250  double wPosRem = infoPtr->eCM() - rescale * wPosBef;
2251  double wNegRem = infoPtr->eCM() - rescale * wNegBef;
2252  double w2Rem = wPosRem * wNegRem;
2253  double xLepA = 1. - beamAPtr->xGamma();
2254  double xLepB = 1. - beamBPtr->xGamma();
2255 
2256  // Rescaling factors for leptons.
2257  double lambdaRoot = sqrtpos( pow2(w2Rem - w2BeamA - w2BeamB)
2258  - 4. * w2BeamA * w2BeamB );
2259  double rescaleA = (w2Rem + w2BeamA - w2BeamB + lambdaRoot)
2260  / (2. * w2Rem * xLepA);
2261  double rescaleB = (w2Rem + w2BeamB - w2BeamA + lambdaRoot)
2262  / (2. * w2Rem * xLepB);
2263 
2264  // Momenta of the scattered leptons.
2265  double pPosA = rescaleA * xLepA * wPosRem;
2266  double pNegA = w2BeamA / pPosA;
2267  double eLepA = 0.5 * (pPosA + pNegA);
2268  double pzLepA = 0.5 * (pPosA - pNegA);
2269  double pNegB = rescaleB * xLepB * wNegRem;
2270  double pPosB = w2BeamB / pNegB;
2271  double eLepB = 0.5 * (pPosB + pNegB);
2272  double pzLepB = 0.5 * (pPosB - pNegB);
2273  Vec4 pLeptonANew( -kTxA, -kTyA, pzLepA, eLepA);
2274  Vec4 pLeptonBNew( -kTxB, -kTyB, pzLepB, eLepB);
2275 
2276  // Save the momenta of scattered leptons.
2277  pLepton1scat = pLeptonANew;
2278  pLepton2scat = pLeptonBNew;
2279 
2280  // Save the scattering angles of the leptons.
2281  double theta1 = pLepton1scat.theta();
2282  double theta2 = M_PI - pLepton2scat.theta();
2283  infoPtr->setTheta1(theta1);
2284  infoPtr->setTheta2(theta2);
2285  infoPtr->setECMsub(sqrt(sHatBef));
2286  infoPtr->setsHatNew(sHatBef);
2287 
2288  // Otherwise derive the kinematics according to sampled virtualities.
2289  } else {
2290 
2291  // Calculate the new momentum for virtual photon if present for side A.
2292  if ( hasGammaA ) {
2293 
2294  // Get the x_gamma and virtuality and derive mass.
2295  double xGamma1 = beamAPtr->xGamma();
2296  double Q2gamma1 = beamAPtr->Q2Gamma();
2297  mGamma1 = -sqrt( Q2gamma1);
2298  beamGamAPtr->newM( mGamma1);
2299 
2300  // Derive the kinematics with virtuality and kT.
2301  double eGamma1 = xGamma1 * sqrt( eCM2A);
2302  double kz1 = (eCM2A * xGamma1 + 0.5 * Q2gamma1)
2303  / sqrt(eCM2A - m2BeamA);
2304 
2305  // Set the new momemtum and mass. Set appropriate mass also for the
2306  // intermediate zero-virtual photon to keep kinematics physical.
2307  pGamma1 = Vec4( beamAPtr->gammaKTx(), beamAPtr->gammaKTy(),
2308  kz1, eGamma1);
2309  if (!sampleQ2gamma) mGamma1 = pGamma1.mCalc();
2310  event[3].p( pGamma1);
2311  event[3].m( mGamma1);
2312 
2313  // For hard diffraction set the new kinematics also for the copy.
2314  if (infoPtr->isHardDiffractiveA()) {
2315  event[7].p( pGamma1);
2316  event[7].m( mGamma1);
2317  iSkipHardDiff = 7;
2318  }
2319  }
2320 
2321  // Calculate the new momentum for virtual photon if present for side B.
2322  if ( hasGammaB ) {
2323 
2324  // Get the x_gamma and virtuality and derive mass.
2325  double xGamma2 = beamBPtr->xGamma();
2326  double Q2gamma2 = beamBPtr->Q2Gamma();
2327  mGamma2 = -sqrt( Q2gamma2);
2328  beamGamBPtr->newM( mGamma2);
2329 
2330  // Derive the kinematics with virtuality and kT.
2331  double eGamma2 = xGamma2 * sqrt( eCM2B);
2332  double kz2 = (eCM2B * xGamma2 + 0.5 * Q2gamma2)
2333  / sqrt(eCM2B - m2BeamB);
2334 
2335  // Set the new momemtum and mass. Set appropriate mass also for the
2336  // intermediate zero-virtual photon to keep kinematics physical.
2337  pGamma2 = Vec4( beamBPtr->gammaKTx(), beamBPtr->gammaKTy(),
2338  -kz2, eGamma2);
2339  if (!sampleQ2gamma) mGamma2 = pGamma2.mCalc();
2340  event[4].p( pGamma2);
2341  event[4].m( mGamma2);
2342 
2343  // For hard diffraction set the new kinematics also for the copy.
2344  if (infoPtr->isHardDiffractiveB()) {
2345  event[8].p( pGamma2);
2346  event[8].m( mGamma2);
2347  iSkipHardDiff = 8;
2348  }
2349  }
2350 
2351  // Find momenta for scattered lepton.
2352  Vec4 pLepton1 = process[1].p();
2353  Vec4 pLepton2 = process[2].p();
2354  pLepton1scat = pLepton1 - pGamma1;
2355  pLepton2scat = pLepton2 - pGamma2;
2356  }
2357 
2358  // For photon-hadron cases use the 4-momentum of the original beam particle
2359  // since virtual photon kinematics are derived in this frame.
2360  // Effect negligible when mass of the beam providing photon is small.
2361  if ( hasGammaA && !hasGammaB) pGamma2 = event[2].p();
2362  else if (!hasGammaA && hasGammaB) pGamma1 = event[1].p();
2363 
2364  // Find the boost from rest frame of collinear photons to rest frame of
2365  // photons with kT.
2366  RotBstMatrix MfromGmGm;
2367  MfromGmGm.toCMframe( pGamma1, pGamma2);
2368  MfromGmGm.fromCMframe( pGamma1Orig, pGamma2Orig);
2369  MfromGmGm.invert();
2370 
2371  // Copy the momentum and mass of the unresolved photon for direct-resolved
2372  // processes to have correct virtualities in the event record.
2373  int iSkipGamma = -1;
2374  if ( gammaModeEvent == 3 ) {
2375  iSkipGamma = 5;
2376  event[iSkipGamma].m( mGamma1);
2377  event[iSkipGamma].p( pGamma1);
2378  } else if ( gammaModeEvent == 2 ) {
2379  iSkipGamma = 6;
2380  event[iSkipGamma].m( mGamma2);
2381  event[iSkipGamma].p( pGamma2);
2382  }
2383 
2384  // Boost scattered system to frame where photon beam has non-zero kT.
2385  // Do not boost photons which has already correct four momenta.
2386  // For elastic events skip both photons.
2387  int iProcessBegin = 5;
2388  int iSkipGammaEl = -1;
2389  if (isElastic) {
2390  iProcessBegin = 3;
2391  if (hasGammaA) iSkipGamma = 3;
2392  if (hasGammaB) iSkipGammaEl = 4;
2393  }
2394  for (int i = iProcessBegin; i < event.size(); ++i) {
2395  if ( (i != iSkipGamma) && (i != iSkipHardDiff) && (i != iSkipGammaEl) )
2396  event[i].rotbst( MfromGmGm);
2397  }
2398 
2399  // For photon-hadron cases set the beam particle copy originally derived
2400  // using zero virtuality for photon to match the derived kinematics.
2401  if ( hasGammaA && !hasGammaB) event[4].p(pGamma2);
2402  else if (!hasGammaA && hasGammaB) event[3].p(pGamma1);
2403 
2404  // Add the scattered leptons if remnants are constructed.
2405  if (doRemnants) {
2406 
2407  // Add scattered leptons and fix the daughter codes.
2408  if ( hasGammaA) {
2409  int iPosLepton1 = event.append( beamAPtr->id(), 63, 1, 0, 0, 0, 0, 0,
2410  pLepton1scat, beamAPtr->m());
2411  event[1].daughter2( event[1].daughter1());
2412  event[1].daughter1( iPosLepton1);
2413  }
2414  if ( hasGammaB) {
2415  int iPosLepton2 = event.append( beamBPtr->id(), 63, 2, 0, 0, 0, 0, 0,
2416  pLepton2scat, beamBPtr->m());
2417  event[2].daughter2( event[2].daughter1());
2418  event[2].daughter1( iPosLepton2);
2419  }
2420  }
2421 
2422  // Reset all pointers also for non-physical events.
2423  }
2424 
2425  // Done for direct-direct and elastic processes.
2426  if ( (gammaModeEvent == 4) || isElastic ) return;
2427 
2428  // Reassign beam pointers in other classes.
2429  timesPtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
2430  timesDecPtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
2431  spacePtr->reassignBeamPtrs( beamAPtr, beamBPtr, 0);
2432  remnants.reassignBeamPtrs( beamAPtr, beamBPtr, 0);
2433  if (colourReconnectionPtr)
2434  colourReconnectionPtr->reassignBeamPtrs( beamAPtr, beamBPtr);
2435 
2436  // Set the MPI pointer back to the original collisions.
2437  multiPtr = &multiMB;
2438  multiPtr->setBeamOffset(0);
2439 
2440 }
2441 
2442 //--------------------------------------------------------------------------
2443 
2444 // Remove the copies of the beam photon from the event record.
2445 
2446 void PartonLevel::cleanEventFromGamma( Event& event) {
2447 
2448  // Offset to normal beam position when photons emitted from a lepton beam.
2449  int beamOffset = 2;
2450  // If hard diffraction more offset for sub-system beams.
2451  if (infoPtr->isHardDiffractiveA() || infoPtr->isHardDiffractiveB())
2452  beamOffset += 4;
2453  int iPosBeam1 = 1 + beamOffset;
2454  int iPosBeam2 = 2 + beamOffset;
2455 
2456  // Go through the event record from the end and find the copies.
2457  int iPosGamma1 = 0;
2458  int iPosGamma2 = 0;
2459  for (int i = event.size() - 1; i > 0; --i) {
2460  if ( (event[i].id() == 22 && event[i].mother1() == iPosBeam1)
2461  && beamAhasResGamma ) iPosGamma1 = i;
2462  if ( (event[i].id() == 22 && event[i].mother1() == iPosBeam2)
2463  && beamBhasResGamma ) iPosGamma2 = i;
2464  }
2465 
2466  // Check how many unresolved photons are present in the event.
2467  int nGamma = 0;
2468  if (iPosGamma1 > 0) ++nGamma;
2469  if (iPosGamma2 > 0) ++nGamma;
2470 
2471  // Exit if no copies found.
2472  if ( nGamma == 0 ) return;
2473 
2474  // Loop over two beams if required.
2475  for (int i = 0; i < nGamma; ++i) {
2476 
2477  // Set the positions to match the beam.
2478  int iPosGamma = (iPosGamma1 > 0 && i == 0) ? iPosGamma1 : iPosGamma2;
2479  int iPosBeam = (iPosGamma1 > 0 && i == 0) ? iPosBeam1 : iPosBeam2;
2480 
2481  // Go through the history of the beam photon.
2482  while ( iPosGamma > iPosBeam ) {
2483  int iDaughter1 = event[iPosGamma].daughter1();
2484  int iDaughter2 = event[iPosGamma].daughter2();
2485  int iMother1 = event[iPosGamma].mother1();
2486  int iMother2 = event[iPosGamma].mother2();
2487 
2488  // If equal daughters photon just a carbon copy.
2489  if ( iDaughter1 == iDaughter2 ) {
2490  event[iDaughter1].mothers( iMother1, iMother2 );
2491  event.remove( iPosGamma, iPosGamma);
2492  iPosGamma = iDaughter1;
2493 
2494  // If non-equal daughters the photon from ISR branching.
2495  } else {
2496  event[iMother1].daughters( iDaughter1, iDaughter2 );
2497  event[iDaughter1].mother1( iMother1 );
2498  event[iDaughter2].mother1( iMother1 );
2499  event.remove( iPosGamma, iPosGamma);
2500  iPosGamma = iMother1;
2501  }
2502 
2503  // If both beams unresolved fix the position of the latter one.
2504  if ( (i == 0 && nGamma > 1) && iPosGamma2 > iPosGamma ) --iPosGamma2;
2505 
2506  }
2507  }
2508 }
2509 
2510 //--------------------------------------------------------------------------
2511 
2512 // Handle showers in successive resonance decays.
2513 
2514 bool PartonLevel::resonanceShowers( Event& process, Event& event,
2515  bool skipForR) {
2516 
2517  // Prepare to start over from beginning for R-hadron decays.
2518  if (allowRH) {
2519  if (skipForR) {
2520  nHardDoneRHad = nHardDone;
2521  inRHadDecay.resize(0);
2522  for (int i = 0; i < process.size(); ++i)
2523  inRHadDecay.push_back( false);
2524  } else nHardDone = nHardDoneRHad;
2525  }
2526 
2527  // Isolate next system to be processed, if anything remains.
2528  int nRes = 0;
2529  int nFSRres = 0;
2530  // Number of desired branchings, negative value means no restriction.
2531  int nBranchMax = (doTrial) ? nTrialEmissions : -1;
2532  // Vector to tell which junctions have already been copied
2533  vector<int> iJunCopied;
2534 
2535  while (nHardDone < process.size()) {
2536  ++nRes;
2537  int iBegin = nHardDone;
2538 
2539  // In first call (skipForR = true) skip over daughters
2540  // of resonances that should form R-hadrons
2541  if (allowRH) {
2542  if (skipForR) {
2543  bool comesFromR = false;
2544  int iTraceUp = process[iBegin].mother1();
2545  do {
2546  if ( rHadronsPtr->givesRHadron(process[iTraceUp].id()) )
2547  comesFromR = true;
2548  iTraceUp = process[iTraceUp].mother1();
2549  } while (iTraceUp > 0 && !comesFromR);
2550  if (comesFromR) {
2551  inRHadDecay[iBegin] = true;
2552  ++nHardDone;
2553  continue;
2554  }
2555 
2556  // In optional second call (skipForR = false) process decay chains
2557  // inside R-hadrons.
2558  } else if (!inRHadDecay[iBegin]) {
2559  ++nHardDone;
2560  continue;
2561  }
2562  }
2563 
2564  // Mother in hard process and in complete event (after shower).
2565  int iHardMother = process[iBegin].mother1();
2566  Particle& hardMother = process[iHardMother];
2567  int iBefMother = iPosBefShow[iHardMother];
2568  if (event[iBefMother].daughter1() >= event.size())
2569  event[iBefMother].daughters( 0, 0);
2570  int iAftMother = event[iBefMother].iBotCopyId();
2571  // Possibly trace across intermediate R-hadron state.
2572  if (allowRH) {
2573  int iTraceRHadron = rHadronsPtr->trace( iAftMother);
2574  if (iTraceRHadron > 0) iAftMother = iTraceRHadron;
2575  }
2576  Particle& aftMother = event[iAftMother];
2577 
2578  // From now on mother counts as decayed.
2579  aftMother.statusNeg();
2580 
2581  // Mother can have been moved by showering (in any of previous steps),
2582  // so prepare to update colour and momentum information for system.
2583  int colBef = hardMother.col();
2584  int acolBef = hardMother.acol();
2585  int colAft = aftMother.col();
2586  int acolAft = aftMother.acol();
2587  RotBstMatrix M;
2588  M.bst( hardMother.p(), aftMother.p());
2589 
2590  // New colour reconnection can not handle late resonance decay
2591  // of coloured particles so abort event.
2592  if ( (colBef != 0 || acolBef != 0) && doReconnect && reconnectMode == 1
2593  && forceResonanceCR && !earlyResDec) {
2594  infoPtr->errorMsg("Abort from PartonLevel::resonanceShower: "
2595  "new CR can't handle separate CR for coloured resonance decays");
2596  infoPtr->setAbortPartonLevel(true);
2597  return false;
2598  }
2599 
2600  // Extract next partons from hard event into normal event record.
2601  vector<bool> doCopyJun;
2602  for (int i = iBegin; i < process.size(); ++i) {
2603  if (process[i].mother1() != iHardMother) break;
2604  int iNow = event.append( process[i] );
2605  iPosBefShow[i] = iNow;
2606  Particle& now = event.back();
2607 
2608  // Currently outgoing ones should not count as decayed.
2609  if (now.status() == -22) {
2610  now.statusPos();
2611  now.daughters(0, 0);
2612  }
2613 
2614  // Update daughter and mother information.
2615  if (i == iBegin) event[iAftMother].daughter1( iNow);
2616  else event[iAftMother].daughter2( iNow);
2617  now.mother1(iAftMother);
2618 
2619  // Check if this parton came from a BNV (junction) decay in hard event.
2620  for (int iJun = 0; iJun < process.sizeJunction(); ++iJun) {
2621  if (iJun >= int(doCopyJun.size())) doCopyJun.push_back(false);
2622  // Skip if we already decided we're going to copy this junction
2623  if (doCopyJun[iJun]) continue;
2624  // Only consider junctions that can appear in decays.
2625  int kindJunction = process.kindJunction(iJun);
2626  if (kindJunction <= 2) {
2627  // Junction Kinds 1 and 2: all legs in final state
2628  int nMatch = 0;
2629  // Loop over resonance-decay daughters
2630  int iDau1 = hardMother.daughter1();
2631  int iDau2 = hardMother.daughter2();
2632  // Must have at least 3 decay products
2633  if (iDau1 == 0 || iDau2 - iDau1 < 2) continue;
2634  for (int iDau=iDau1; iDau<=iDau2; ++iDau) {
2635  int colDau = (kindJunction == 1 ? process[iDau].col()
2636  : process[iDau].acol());
2637  for (int iLeg = 0; iLeg <= 2; ++iLeg)
2638  if ( process.colJunction(iJun,iLeg) == colDau ) nMatch += 1;
2639  }
2640  // If three legs match
2641  if (nMatch == 3) doCopyJun[iJun] = true;
2642  } else if (kindJunction <= 4) {
2643  // Junction Kinds 3 and 4: copy if initial-state leg matches
2644  // this resonance.
2645  int col = (kindJunction == 3 ? hardMother.acol() : hardMother.col());
2646  if ( process.colJunction(iJun,0) == col ) doCopyJun[iJun] = true;
2647  }
2648  // Extra safety: Check if this junction has already been copied
2649  // (e.g., in setupHardSys). If so, do not copy again.
2650  for (int kJun = 0; kJun < event.sizeJunction(); ++kJun) {
2651  int nMatch = 0;
2652  for (int iLeg = 0; iLeg <= 2; ++iLeg)
2653  if (event.colJunction(kJun,iLeg) == process.colJunction(iJun,iLeg))
2654  ++nMatch;
2655  if (nMatch == 3) doCopyJun[iJun] = false;
2656  }
2657  }
2658 
2659  // Update colour and momentum information.
2660  if (now.col() == colBef) now.col( colAft);
2661  if (now.acol() == acolBef) now.acol( acolAft);
2662  // Sextet mothers have additional (negative) tag
2663  if (now.col() == -acolBef) now.col( -acolAft);
2664  if (now.acol() == -colBef) now.acol( -colAft);
2665  now.rotbst( M);
2666 
2667  // Update vertex information.
2668  if (now.hasVertex()) now.vProd( event[iAftMother].vDec() );
2669 
2670  // Complete task of copying next subsystem into event record.
2671  ++nHardDone;
2672  }
2673  int iEnd = nHardDone - 1;
2674 
2675  // Copy down junctions from hard event into normal event record.
2676  for (int iJun = 0; iJun < int(doCopyJun.size()); ++iJun) {
2677  // Check if this junction was already copied
2678  for (int jJun = 0; jJun < int(iJunCopied.size()); ++jJun)
2679  if (iJunCopied[jJun] == iJun) doCopyJun[iJun] = false;
2680  // Skip if not doing anything
2681  if (!doCopyJun[iJun]) continue;
2682  // Check for changed colors and update as necessary.
2683  Junction junCopy = process.getJunction(iJun);
2684  for (int iLeg = 0; iLeg <= 2; ++iLeg) {
2685  int colLeg = junCopy.col(iLeg);
2686  if (colLeg == colBef) junCopy.col(iLeg, colAft);
2687  if (colLeg == acolBef) junCopy.col(iLeg, acolAft);
2688  }
2689  event.appendJunction(junCopy);
2690  // Mark junction as copied (to avoid later recopying)
2691  iJunCopied.push_back(iJun);
2692  }
2693 
2694  // Reset pT of last branching
2695  pTLastBranch = 0.0;
2696 
2697  // Add new resonance-decay system (with empty beam slots).
2698  int iSys = partonSystemsPtr->addSys();
2699  partonSystemsPtr->setInRes( iSys,iAftMother);
2700  partonSystemsPtr->setSHat( iSys, pow2(hardMother.m()) );
2701  partonSystemsPtr->setPTHat( iSys, 0.5 * hardMother.m() );
2702 
2703  // Loop over allowed range to find all final-state particles.
2704  for (int i = iPosBefShow[iBegin]; i <= iPosBefShow[iEnd]; ++i)
2705  if (event[i].isFinal()) partonSystemsPtr->addOut( iSys, i);
2706 
2707  // Do parton showers inside subsystem: maximum scale by mother mass.
2708  if (doFSRinResonances) {
2709  double pTmax = 0.5 * hardMother.m();
2710  if (canSetScale) pTmax
2711  = userHooksPtr->scaleResonance( iAftMother, event);
2712  nFSRhard = 0;
2713 
2714  // Set correct scale for trial showers.
2715  if (doTrial) pTmax = process.scale();
2716 
2717  // Set correct scale for showers off multi-parton events when
2718  // merging e+e- -> V -> jets.
2719  int iMother1 = hardMother.mother1();
2720  int iMother2 = hardMother.mother2();
2721  if ( canRemoveEvent
2722  && event[iMother1].colType() == 0 && event[iMother2].colType() == 0)
2723  pTmax = process.scale();
2724 
2725  // Let prepare routine do the setup.
2726  timesDecPtr->prepare( iSys, event);
2727 
2728  // Number of actual branchings
2729  int nBranch = 0;
2730 
2731  // Set up initial veto scale.
2732  doVeto = false;
2733  double pTveto = pTvetoPT;
2734 
2735  // Begin evolution down in pT from hard pT scale.
2736  do {
2737  typeVetoStep = 0;
2738  double pTtimes = timesDecPtr->pTnext( event, pTmax, 0.);
2739 
2740  // Allow a user veto. Only do it once, so remember to change pTveto.
2741  if (pTveto > 0. && pTveto > pTtimes) {
2742  pTveto = -1.;
2743  doVeto = userHooksPtr->doVetoPT( 5, event);
2744  // Abort event if vetoed.
2745  if (doVeto) return false;
2746  }
2747 
2748  // Do a final-state emission (if allowed).
2749  if (pTtimes > 0.) {
2750  if (timesDecPtr->branch( event)) {
2751  ++nFSRres;
2752  ++nFSRhard;
2753  if (canVetoStep && nFSRhard <= nVetoStep) typeVetoStep = 5;
2754 
2755  nBranch++;
2756  pTLastBranch = pTtimes;
2757  typeLastBranch = 5;
2758 
2759  }
2760  pTmax = pTtimes;
2761  }
2762 
2763  // If no pT scales above zero then nothing to be done.
2764  else pTmax = 0.;
2765 
2766  // Optionally check for a veto after the first few emissions.
2767  if (typeVetoStep > 0) {
2768  doVeto = userHooksPtr->doVetoStep( typeVetoStep, 0, nFSRhard,
2769  event);
2770  // Abort event if vetoed.
2771  if (doVeto) return false;
2772  }
2773 
2774  // Handle potential merging veto.
2775  if ( canRemoveEvent && nFSRhard == 1 ) {
2776  // Simply check, and possibly reset weights.
2777  mergingHooksPtr->doVetoStep( process, event, true );
2778  }
2779 
2780  // Keep on evolving until nothing is left to be done.
2781  } while (pTmax > 0. && (nBranchMax <= 0 || nBranch < nBranchMax) );
2782 
2783  }
2784 
2785  // No more systems to be processed. Set total number of emissions.
2786  }
2787  if (skipForR) nFSRinRes = nFSRres;
2788  return true;
2789 
2790 }
2791 
2792 //--------------------------------------------------------------------------
2793 
2794 // Perform decays and showers of W and Z emitted in shower.
2795 
2796 bool PartonLevel::wzDecayShowers( Event& event) {
2797 
2798  // Identify W/Z produced by a parton shower.
2799  for (int iWZ = 0; iWZ < event.size(); ++iWZ)
2800  if (event[iWZ].isFinal()
2801  && (event[iWZ].id() == 23 || event[iWZ].idAbs() == 24) ) {
2802 
2803  // Do nothing if particle should not be decayed.
2804  if ( event[iWZ].canDecay() && event[iWZ].mayDecay()
2805  && event[iWZ].isResonance() ) ;
2806  else continue;
2807 
2808  int iWZtop = event[iWZ].iTopCopy();
2809  int typeWZ = 0;
2810  if (event[iWZtop].statusAbs() == 56) typeWZ = 1;
2811  if (event[iWZtop].statusAbs() == 47) typeWZ = 2;
2812  int sizeSave = event.size();
2813 
2814  // Map id_Z = 23 -> 93 and id_W = 24 -> 94, for separate decay settings.
2815  // Let W/Z resonance decay. Restore correct identity and status codes.
2816  if (typeWZ > 0) {
2817  int idSave = event[iWZ].id();
2818  event[iWZ].id( (idSave > 0) ? idSave + 70 : idSave - 70);
2819  int statusSave = event[iWZ].status();
2820  resonanceDecays.next( event, iWZ);
2821  event[iWZ].id( idSave);
2822  if (event.size() - sizeSave != 2) return true;
2823  event[iWZ].status( -statusSave);
2824  }
2825 
2826  // FSR decays.
2827  if (typeWZ == 1) {
2828 
2829  // Identify fermion after W/Z emission.
2830  vector<int> iSisters = event[iWZtop].sisterList();
2831  if (iSisters.size() != 1) {
2832  infoPtr->errorMsg("Error in PartonLevel::wzDecayShowers: "
2833  "Not able to find a single sister particle");
2834  return false;
2835  }
2836  int iEmitter = iSisters[0];
2837 
2838  // Boosts to study decay in W/Z rest frame.
2839  RotBstMatrix MtoNew, MtoRest, MtoCM;
2840  MtoNew.bst( event[iWZtop].p(), event[iWZ].p());
2841  MtoRest.bstback( event[iWZ].p());
2842  MtoCM.bst( event[iWZ].p());
2843 
2844  // Emitter and recoiler in W/Z rest frame.
2845  Vec4 pEmitter = event[iEmitter].p();
2846  pEmitter.rotbst( MtoNew);
2847  pEmitter.rotbst( MtoRest);
2848  if (event[iWZtop + 1].statusAbs() != 52) {
2849  infoPtr->errorMsg("Error in PartonLevel::wzDecayShowers: "
2850  "Found wrong recoiler");
2851  return false;
2852  }
2853  Vec4 pRecoiler = event[iWZtop + 1].p();
2854  pRecoiler.rotbst( MtoNew);
2855  pRecoiler.rotbst( MtoRest);
2856  Vec4 pWZRest = event[iWZ].p();
2857  pWZRest.rotbst( MtoRest);
2858 
2859  // Always choose p4 as the particle and p5 as the anti-particle.
2860  Vec4 p4 = pEmitter;
2861  Vec4 p5 = pRecoiler;
2862  if (event[iEmitter].id() < 0) swap( p4, p5);
2863 
2864  // Decay daughters in W/Z rest frame.
2865  // Always choose pDec1 as the particle and p2Dec as the anti-particle.
2866  Vec4 pDec1 = event[sizeSave].p();
2867  Vec4 pDec2 = event[sizeSave + 1].p();
2868  if (event[sizeSave].id() < 0) swap( pDec1, pDec2);
2869  pDec1.rotbst( MtoRest);
2870  pDec2.rotbst( MtoRest);
2871 
2872  // Couplings.
2873  double li2, ri2, lf2, rf2;
2874  // Z couplings: make use of initial fermion polarization if set.
2875  if (event[iWZ].id() == 23) {
2876  li2 = pow2(coupSMPtr->lf( event[iEmitter].idAbs() ));
2877  ri2 = pow2(coupSMPtr->rf( event[iEmitter].idAbs() ));
2878  lf2 = pow2(coupSMPtr->lf( event[sizeSave].idAbs() ));
2879  rf2 = pow2(coupSMPtr->rf( event[sizeSave].idAbs() ));
2880  if ( abs( event[iEmitter].pol() + 1.) < 0.1) ri2 = 0.;
2881  if ( abs( event[iEmitter].pol() - 1.) < 0.1) li2 = 0.;
2882  // W couplings.
2883  } else {
2884  li2 = 1.;
2885  ri2 = 0.;
2886  lf2 = 1.;
2887  rf2 = 0.;
2888  }
2889 
2890  // Different needed kinematic variables.
2891  double sWZER = (p4 + pWZRest + p5).m2Calc();
2892  double x1 = 2. * p4 * (p4 + pWZRest + p5) / sWZER;
2893  double x2 = 2. * p5 * (p4 + pWZRest + p5) / sWZER;
2894  double x1s = x1 * x1;
2895  double x2s = x2 * x2;
2896  double m2Sel = pWZRest.m2Calc();
2897  double rWZER = m2Sel / sWZER;
2898 
2899  // Calculate constants needed in correction.
2900  double con[9];
2901  con[0] = 2. * m2Sel * (1.-x1) * ((x2s+1.-x1-x2) - rWZER * (1.-x2))
2902  * (li2 * lf2 + ri2 * rf2);
2903  con[1] = 2. * m2Sel * (1.-x2) * ((x1s+1.-x1-x2) - rWZER * (1.-x1))
2904  * (li2 * rf2 + ri2 * lf2);
2905  con[2] = 2. * m2Sel * (1.-x1) * ((x2s+1.-x1-x2) - rWZER * (1.-x2))
2906  * (li2 * rf2 + ri2 * lf2);
2907  con[3] = 2. * m2Sel * (1.-x2) * ((x1s+1.-x1-x2) - rWZER * (1.-x1))
2908  * (li2 * lf2 + ri2 * rf2);
2909  con[4] = m2Sel * sWZER * (1.-x1) * (1.-x2) * ((x1+x2-1.) + rWZER)
2910  * (li2 + ri2) * (lf2 + rf2);
2911  con[5] = -4. * (1.-x1) * (1.-x2) * (li2 + ri2) * (lf2 + rf2);
2912  con[6] = -4. * (1.-x1) * (1.-x2) * (li2 + ri2) * (lf2 + rf2);
2913  con[7] = 4. * (1.-x1) * ((1.-x1) - rWZER * (1.-x2))
2914  * (li2 + ri2) * (lf2 + rf2);
2915  con[8] = 4. * (1.-x2) * ((1.-x2) - rWZER * (1.-x1))
2916  * (li2 + ri2) * (lf2 + rf2);
2917 
2918  // Find maximum value: try pDec1 and pDec2 = -pDec1 along +-x, +-y, +-z.
2919  double wtMax = 0.;
2920  double pAbs12 = pDec1.pAbs();
2921  for (int j = 0; j < 6; ++j) {
2922  Vec4 pDec1Test( 0., 0., 0., pDec1.e());
2923  Vec4 pDec2Test( 0., 0., 0., pDec2.e());
2924  if (j == 0) { pDec1Test.px( pAbs12); pDec1Test.px( -pAbs12);}
2925  else if (j == 1) { pDec1Test.px( -pAbs12); pDec1Test.px( pAbs12);}
2926  else if (j == 2) { pDec1Test.py( pAbs12); pDec1Test.py( -pAbs12);}
2927  else if (j == 3) { pDec1Test.py( -pAbs12); pDec1Test.py( pAbs12);}
2928  else if (j == 4) { pDec1Test.pz( pAbs12); pDec1Test.pz( -pAbs12);}
2929  else if (j == 5) { pDec1Test.pz( -pAbs12); pDec1Test.pz( pAbs12);}
2930 
2931  // Evaluate matrix element and compare with current maximum.
2932  double p2p4Test = p4 * pDec1Test;
2933  double p3p4Test = p4 * pDec2Test;
2934  double p2p5Test = p5 * pDec1Test;
2935  double p3p5Test = p5 * pDec2Test;
2936  double testValues[9] = { p2p4Test, p2p5Test, p3p4Test, p3p5Test, 1.,
2937  p2p5Test * p3p4Test, p2p4Test * p3p5Test, p2p4Test * p3p4Test,
2938  p2p5Test * p3p5Test};
2939  double wtTest = 0.;
2940  for (int i = 0; i < 9; ++i) wtTest += con[i] * testValues[i];
2941  if (wtTest > wtMax) wtMax = wtTest;
2942  }
2943 
2944  // Multiply by four to ensure maximum is an overestimate.
2945  wtMax *= 4.;
2946 
2947  // Iterate with new angles until weighting succeeds.
2948  int nRot = -1;
2949  double wt = 0.;
2950  do {
2951  ++nRot;
2952  if (nRot > 0) {
2953  RotBstMatrix MrndmRot;
2954  MrndmRot.rot( acos(2. * rndmPtr->flat() - 1.),
2955  2. * M_PI * rndmPtr->flat());
2956  pDec1.rotbst(MrndmRot);
2957  pDec2.rotbst(MrndmRot);
2958  }
2959 
2960  // p2 is decay product, p3 is anti decay product,
2961  // p4 is dipole particle, p5 is dipole anti particle.
2962  // So far assumed that we always have qQ-dipole.
2963  double p2p4 = p4 * pDec1;
2964  double p3p4 = p4 * pDec2;
2965  double p2p5 = p5 * pDec1;
2966  double p3p5 = p5 * pDec2;
2967 
2968  // Calculate weight and compare with maximum weight.
2969  double wtValues[9] = { p2p4, p2p5, p3p4, p3p5, 1., p2p5 * p3p4,
2970  p2p4 * p3p5, p2p4 * p3p4, p2p5 * p3p5};
2971  wt = 0.;
2972  for (int i = 0; i < 9; ++i) wt += con[i] * wtValues[i];
2973  if (wt > wtMax || wt < 0.) {
2974  infoPtr->errorMsg("Error in PartonLevel::wzDecayShowers: "
2975  "wt bigger than wtMax or less than zero");
2976  return false;
2977  }
2978  } while (wt < wtMax * rndmPtr->flat());
2979 
2980  // If momenta rotated then store new ones.
2981  if (nRot > 0) {
2982  pDec1.rotbst( MtoCM);
2983  pDec2.rotbst( MtoCM);
2984  if (event[sizeSave].id() > 0) {
2985  event[sizeSave].p( pDec1);
2986  event[sizeSave + 1].p( pDec2);
2987  }
2988  else {
2989  event[sizeSave].p( pDec2);
2990  event[sizeSave + 1].p( pDec1);
2991  }
2992  }
2993  }
2994 
2995  // ISR decays.
2996  if (typeWZ == 2) {
2997 
2998  // Identify mother of W/Z emission.
2999  double iMother = event[iWZtop].mother1();
3000 
3001  // Boosts to study decay in W/Z rest frame.
3002  RotBstMatrix MtoNew, MtoRest, MtoCM;
3003  MtoNew.bst( event[iWZtop].p(), event[iWZ].p());
3004  MtoRest.bstback( event[iWZ].p());
3005  MtoCM.bst( event[iWZ].p());
3006 
3007  // Find recoiler.
3008  int iRecoiler;
3009  if (event[iMother + 1].statusAbs() == 42) iRecoiler = iMother + 1;
3010  else if (event[iMother - 1].statusAbs() == 42) iRecoiler = iMother - 1;
3011  else {
3012  infoPtr->errorMsg("Error in PartonLevel::wzDecayShowers: "
3013  "Found wrong recoiler");
3014  return false;
3015  }
3016 
3017  // Emitter and recoiler in W/Z rest frame.
3018  Vec4 pMother = event[iMother].p();
3019  pMother.rotbst( MtoNew);
3020  pMother.rotbst( MtoRest);
3021  Vec4 pRecoiler = event[iRecoiler].p();
3022  pRecoiler.rotbst( MtoNew);
3023  pRecoiler.rotbst( MtoRest);
3024  Vec4 pWZRest = event[iWZ].p();
3025  pWZRest.rotbst( MtoRest);
3026 
3027  // Always choose p1 as the particle and p2 as the anti-particle.
3028  // If no anti-particles just continue.
3029  Vec4 p1 = pMother;
3030  Vec4 p2 = pRecoiler;
3031  if (event[iMother].id() < 0) swap( p1, p2);
3032 
3033  // Decay daughters in W/Z rest frame.
3034  // Always choose pDec1 as the particle and p2Dec as the anti-particle.
3035  Vec4 pDec1 = event[sizeSave].p();
3036  Vec4 pDec2 = event[sizeSave + 1].p();
3037  if (event[sizeSave].id() < 0) swap( pDec1, pDec2);
3038  pDec1.rotbst( MtoRest);
3039  pDec2.rotbst( MtoRest);
3040 
3041  // Couplings.
3042  double li2, ri2, lf2, rf2;
3043  // Z couplings: make use of initial fermion polarization if set.
3044  if (event[iWZ].id() == 23) {
3045  li2 = pow2(coupSMPtr->lf( event[iMother].idAbs() ));
3046  ri2 = pow2(coupSMPtr->rf( event[iMother].idAbs() ));
3047  lf2 = pow2(coupSMPtr->lf( event[sizeSave].idAbs() ));
3048  rf2 = pow2(coupSMPtr->rf( event[sizeSave].idAbs() ));
3049  if ( abs( event[iMother].pol() + 1.) < 0.1) ri2 = 0.;
3050  if ( abs( event[iMother].pol() - 1.) < 0.1) li2 = 0.;
3051  // W couplings.
3052  } else {
3053  li2 = 1.;
3054  ri2 = 0.;
3055  lf2 = 1.;
3056  rf2 = 0.;
3057  }
3058 
3059  // Different needed kinematic variables.
3060  double s = (p1 + p2).m2Calc();
3061  double t = (p1-pWZRest).m2Calc();
3062  double u = (p2-pWZRest).m2Calc();
3063  double m2Sel = pWZRest.m2Calc();
3064  double m2Final = t + u + s - m2Sel;
3065 
3066  // Calculate constants needed in correction.
3067  double con[9];
3068  con[0] = 2. * m2Sel * (u * (1. - m2Final / t) + s)
3069  * (li2 * rf2 + ri2 * lf2);
3070  con[1] = 2. * m2Sel * (u * (1. - m2Final / t) + s)
3071  * (li2 * lf2 + ri2 * rf2);
3072  con[2] = 2. * m2Sel * (t * (1. - m2Final / u) + s)
3073  * (li2 * lf2 + ri2 * rf2);
3074  con[3] = 2. * m2Sel * (t * (1. - m2Final / u) + s)
3075  * (li2 * rf2 + ri2 * lf2);
3076  con[4] = m2Sel * m2Final * s * (li2 + ri2) * (lf2 + rf2);
3077  con[5] = -4. * m2Final * (li2 + ri2) * (lf2 + rf2);
3078  con[6] = -4. * m2Final * (li2 + ri2) * (lf2 + rf2);
3079  con[7] = 4. * (m2Final * u / t - m2Sel) * (li2 + ri2) * (lf2 + rf2);
3080  con[8] = 4. * (m2Final * t / u - m2Sel) * (li2 + ri2) * (lf2 + rf2);
3081 
3082  // Find maximum value: try pDec1 and pDec2 = -pDec1 along +-x, +-y, +-z.
3083  double wtMax = 0.;
3084  double pAbs12 = pDec1.pAbs();
3085  for (int j = 0; j < 6; ++j) {
3086  Vec4 pDec1Test( 0., 0., 0., pDec1.e());
3087  Vec4 pDec2Test( 0., 0., 0., pDec2.e());
3088  if (j == 0) { pDec1Test.px( pAbs12); pDec1Test.px( -pAbs12);}
3089  else if (j == 1) { pDec1Test.px( -pAbs12); pDec1Test.px( pAbs12);}
3090  else if (j == 2) { pDec1Test.py( pAbs12); pDec1Test.py( -pAbs12);}
3091  else if (j == 3) { pDec1Test.py( -pAbs12); pDec1Test.py( pAbs12);}
3092  else if (j == 4) { pDec1Test.pz( pAbs12); pDec1Test.pz( -pAbs12);}
3093  else if (j == 5) { pDec1Test.pz( -pAbs12); pDec1Test.pz( pAbs12);}
3094 
3095  // Evaluate matrix element and compare with current maximum.
3096  double p1p4Test = p1 * pDec1Test;
3097  double p1p5Test = p1 * pDec2Test;
3098  double p2p4Test = p2 * pDec1Test;
3099  double p2p5Test = p2 * pDec2Test;
3100  double testValues[9] = { p1p4Test, p1p5Test, p2p4Test, p2p5Test, 1.,
3101  p1p4Test * p2p5Test, p1p5Test * p2p4Test, p1p4Test * p1p5Test,
3102  p2p4Test * p2p5Test};
3103  double wtTest = 0.;
3104  for (int i = 0; i < 9; ++i) wtTest += con[i] * testValues[i];
3105  if (wtTest > wtMax) wtMax = wtTest;
3106  }
3107 
3108  // Multiply by four to ensure maximum is an overestimate.
3109  wtMax *= 4.;
3110 
3111  // Iterate with new angles until weighting succeeds.
3112  int nRot = -1;
3113  double wt = 0.;
3114  do {
3115  ++nRot;
3116  if (nRot > 0) {
3117  RotBstMatrix MrndmRot;
3118  MrndmRot.rot( acos(2. * rndmPtr->flat() - 1.),
3119  2. * M_PI * rndmPtr->flat());
3120  pDec1.rotbst(MrndmRot);
3121  pDec2.rotbst(MrndmRot);
3122  }
3123 
3124  // p2 is decay product, p3 is anti decay product,
3125  // p4 is dipole particle, p5 is dipole anti particle.
3126  // So far assumed that we always have qQ-dipole.
3127  double p1p4 = p1 * pDec1;
3128  double p1p5 = p1 * pDec2;
3129  double p2p4 = p2 * pDec1;
3130  double p2p5 = p2 * pDec2;
3131 
3132  // Calculate weight and compare with maximum weight.
3133  double wtValues[9] = { p1p4, p1p5, p2p4, p2p5, 1., p1p4 * p2p5,
3134  p1p5 * p2p4, p1p4 * p1p5, p2p4 * p2p5};
3135  wt = 0.;
3136  for (int i = 0; i < 9; ++i) wt += con[i] * wtValues[i];
3137  if (wt > wtMax || wt < 0.) {
3138  infoPtr->errorMsg("Error in PartonLevel::wzDecayShowers: "
3139  "wt bigger than wtMax or less than zero");
3140  return false;
3141  }
3142  } while (wt < wtMax * rndmPtr->flat());
3143 
3144  // If momenta rotated then store new ones.
3145  if (nRot > 0) {
3146  pDec1.rotbst( MtoCM);
3147  pDec2.rotbst( MtoCM);
3148  if (event[sizeSave].id() > 0) {
3149  event[sizeSave].p( pDec1);
3150  event[sizeSave + 1].p( pDec2);
3151  }
3152  else {
3153  event[sizeSave].p( pDec2);
3154  event[sizeSave + 1].p( pDec1);
3155  }
3156  }
3157  }
3158 
3159  // Add new resonance-decay system (with empty beam slots).
3160  if (typeWZ > 0) {
3161  // Maximum shower scale set by mother mass.
3162  double pTmax = 0.5 * event[iWZ].m();
3163  int iSys = partonSystemsPtr->addSys();
3164  partonSystemsPtr->setInRes( iSys, iWZ);
3165  partonSystemsPtr->setSHat( iSys, pow2(event[iWZ].m()) );
3166  partonSystemsPtr->setPTHat( iSys, pTmax);
3167  for (int i = sizeSave; i < event.size(); ++i)
3168  partonSystemsPtr->addOut( iSys, i);
3169 
3170  // Do parton showers inside subsystem.
3171  if (doFSRinResonances) {
3172 
3173  // Let prepare routine do the setup.
3174  timesDecPtr->prepare( iSys, event);
3175 
3176  // Begin evolution down in pT from hard pT scale.
3177  do {
3178  double pTtimes = timesDecPtr->pTnext( event, pTmax, 0.);
3179 
3180  // Do a final-state emission (if allowed).
3181  if (pTtimes > 0.) {
3182  timesDecPtr->branch( event);
3183  pTmax = pTtimes;
3184  }
3185 
3186  // If no pT scales above zero then nothing to be done.
3187  else pTmax = 0.;
3188 
3189  // Keep on evolving until nothing is left to be done.
3190  } while (pTmax > 0.);
3191  }
3192  }
3193 
3194  // End loop over event to find W/Z gauge bosons.
3195  }
3196 
3197  // Done.
3198  return true;
3199 
3200 }
3201 
3202 //==========================================================================
3203 
3204 } // end namespace Pythia8
Definition: AgUStep.h:26