StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ProcessLevel.cc
1 // ProcessLevel.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 
6 // Function definitions (not found in the header) for the ProcessLevel class.
7 
8 #include "Pythia8/ProcessLevel.h"
9 
10 namespace Pythia8 {
11 
12 //==========================================================================
13 
14 // The ProcessLevel class.
15 
16 //--------------------------------------------------------------------------
17 
18 // Constants: could be changed here if desired, but normally should not.
19 // These are of technical nature, as described for each.
20 
21 // Allow a few failures in final construction of events.
22 const int ProcessLevel::MAXLOOP = 5;
23 
24 //--------------------------------------------------------------------------
25 
26 // Destructor.
27 
28 ProcessLevel::~ProcessLevel() {
29 
30  // Run through list of first hard processes and delete them.
31  for (int i = 0; i < int(containerPtrs.size()); ++i)
32  delete containerPtrs[i];
33 
34  // Run through list of second hard processes and delete them.
35  for (int i = 0; i < int(container2Ptrs.size()); ++i)
36  delete container2Ptrs[i];
37 
38 }
39 
40 //--------------------------------------------------------------------------
41 
42 // Main routine to initialize generation process.
43 
44 bool ProcessLevel::init( bool doLHA, SLHAinterface* slhaInterfacePtrIn,
45  vector<SigmaProcess*>& sigmaPtrs, vector<PhaseSpace*>& phaseSpacePtrs) {
46 
47  // Store other input pointers.
48  slhaInterfacePtr = slhaInterfacePtrIn;
49 
50  // Reference to Settings.
51  Settings& settings = *settingsPtr;
52 
53  // Check whether photon inside lepton and save the mode.
54  bool beamA2gamma = settings.flag("PDF:beamA2gamma");
55  bool beamB2gamma = settings.flag("PDF:beamB2gamma");
56  beamHasGamma = beamA2gamma || beamB2gamma;
57  gammaMode = settings.mode("Photon:ProcessType");
58 
59  // initialize gammaKinematics when relevant.
60  if (beamHasGamma)
61  gammaKin.init();
62 
63  // Send on some input pointers.
64  resonanceDecays.init();
65 
66  // Set up SigmaTotal. Store sigma_nondiffractive for future use.
67  int idA = infoPtr->idA();
68  int idB = infoPtr->idB();
69  double eCM = infoPtr->eCM();
70  if (beamHasGamma) {
71  int idAin = beamA2gamma ? 22 : idA;
72  int idBin = beamB2gamma ? 22 : idB;
73  sigmaTotPtr->calc( idAin, idBin, eCM);
74  }
75  else sigmaTotPtr->calc( idA, idB, eCM);
76  sigmaND = sigmaTotPtr->sigmaND();
77 
78  // Options to allow second hard interaction and resonance decays.
79  doSecondHard = settings.flag("SecondHard:generate");
80  doSameCuts = settings.flag("PhaseSpace:sameForSecond");
81  doResDecays = settings.flag("ProcessLevel:resonanceDecays");
82  startColTag = settings.mode("Event:startColTag");
83  maxPDFreweight = settings.parm("SecondHard:maxPDFreweight");
84 
85  // Check whether ISR or MPI applied. Affects processes with photon beams.
86  doISR = ( settings.flag("PartonLevel:ISR")
87  && settings.flag("PartonLevel:all") );
88  doMPI = ( settings.flag("PartonLevel:MPI")
89  && settings.flag("PartonLevel:all") );
90 
91  // Second interaction not to be combined with biased phase space.
92  if (doSecondHard && userHooksPtr != 0
93  && userHooksPtr->canBiasSelection()) {
94  infoPtr->errorMsg("Error in ProcessLevel::init: "
95  "cannot combine second interaction with biased phase space");
96  return false;
97  }
98 
99  // Mass and pT cuts for two hard processes.
100  mHatMin1 = settings.parm("PhaseSpace:mHatMin");
101  mHatMax1 = settings.parm("PhaseSpace:mHatMax");
102  if (mHatMax1 < mHatMin1) mHatMax1 = eCM;
103  pTHatMin1 = settings.parm("PhaseSpace:pTHatMin");
104  pTHatMax1 = settings.parm("PhaseSpace:pTHatMax");
105  if (pTHatMax1 < pTHatMin1) pTHatMax1 = eCM;
106  mHatMin2 = settings.parm("PhaseSpace:mHatMinSecond");
107  mHatMax2 = settings.parm("PhaseSpace:mHatMaxSecond");
108  if (mHatMax2 < mHatMin2) mHatMax2 = eCM;
109  pTHatMin2 = settings.parm("PhaseSpace:pTHatMinSecond");
110  pTHatMax2 = settings.parm("PhaseSpace:pTHatMaxSecond");
111  if (pTHatMax2 < pTHatMin2) pTHatMax2 = eCM;
112 
113  // Check whether mass and pT ranges agree or overlap.
114  cutsAgree = doSameCuts;
115  if (mHatMin2 == mHatMin1 && mHatMax2 == mHatMax1 && pTHatMin2 == pTHatMin1
116  && pTHatMax2 == pTHatMax1) cutsAgree = true;
117  cutsOverlap = cutsAgree;
118  if (!cutsAgree) {
119  bool mHatOverlap = (max( mHatMin1, mHatMin2)
120  < min( mHatMax1, mHatMax2));
121  bool pTHatOverlap = (max( pTHatMin1, pTHatMin2)
122  < min( pTHatMax1, pTHatMax2));
123  if (mHatOverlap && pTHatOverlap) cutsOverlap = true;
124  }
125 
126  // Set up containers for all the internal hard processes.
127  SetupContainers setupContainers;
128  setupContainers.init(containerPtrs, infoPtr);
129 
130  // Append containers for external hard processes, if any.
131  if (sigmaPtrs.size() > 0) {
132  for (int iSig = 0; iSig < int(sigmaPtrs.size()); ++iSig) {
133  containerPtrs.push_back( new ProcessContainer(sigmaPtrs[iSig],
134  true, phaseSpacePtrs[iSig]) );
135  containerPtrs.back()->initInfoPtr(*infoPtr);
136  }
137  }
138 
139  // Append single container for Les Houches processes, if any.
140  if (doLHA) {
141  SigmaProcess* sigmaPtr = new SigmaLHAProcess();
142  containerPtrs.push_back( new ProcessContainer(sigmaPtr) );
143  containerPtrs.back()->initInfoPtr(*infoPtr);
144 
145  // Store location of this container, and send in LHA pointer.
146  iLHACont = containerPtrs.size() - 1;
147  containerPtrs[iLHACont]->setLHAPtr(lhaUpPtr);
148  }
149 
150  // If no processes found then refuse to do anything.
151  if ( int(containerPtrs.size()) == 0) {
152  infoPtr->errorMsg("Error in ProcessLevel::init: "
153  "no process switched on");
154  return false;
155  }
156 
157  // Check whether pT-based weighting in 2 -> 2 is requested.
158  bool bias2Sel = false;
159  if (settings.flag("PhaseSpace:bias2Selection")) {
160  if (sigmaPtrs.size() == 0 && !doLHA && !doSecondHard) {
161  bias2Sel = true;
162  for (int i = 0; i < int(containerPtrs.size()); ++i) {
163  if (containerPtrs[i]->nFinal() != 2) bias2Sel = false;
164  int code = containerPtrs[i]->code();
165  if (code > 100 && code < 110) bias2Sel = false;
166  }
167  }
168  if (!bias2Sel) {
169  infoPtr->errorMsg("Error in ProcessLevel::init: "
170  "requested event weighting not possible");
171  return false;
172  }
173  }
174 
175  // Check that SUSY couplings were indeed initialized where necessary.
176  bool hasSUSY = false;
177  for (int i = 0; i < int(containerPtrs.size()); ++i)
178  if (containerPtrs[i]->isSUSY()) hasSUSY = true;
179 
180  // If SUSY processes requested but no SUSY couplings present
181  if (hasSUSY && !coupSUSYPtr->isSUSY) {
182  infoPtr->errorMsg("Error in ProcessLevel::init: "
183  "SUSY process switched on but no SUSY couplings found");
184  return false;
185  }
186 
187  // Fill SLHA blocks SMINPUTS and MASS from PYTHIA SM parameter values.
188  slhaInterfacePtr->pythia2slha();
189 
190  // Initialize each process.
191  int numberOn = 0;
192  for (int i = 0; i < int(containerPtrs.size()); ++i)
193  if (containerPtrs[i]->init(true, &resonanceDecays, slhaInterfacePtr,
194  &gammaKin))
195  ++numberOn;
196 
197  // Sum maxima for Monte Carlo choice.
198  sigmaMaxSum = 0.;
199  for (int i = 0; i < int(containerPtrs.size()); ++i)
200  sigmaMaxSum += containerPtrs[i]->sigmaMax();
201 
202  // Option to pick a second hard interaction: repeat as above.
203  int number2On = 0;
204  if (doSecondHard) {
205  setupContainers.init2(container2Ptrs, infoPtr);
206  if ( int(container2Ptrs.size()) == 0) {
207  infoPtr->errorMsg("Error in ProcessLevel::init: "
208  "no second hard process switched on");
209  return false;
210  }
211  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
212  if (container2Ptrs[i2]->init(false, &resonanceDecays,
213  slhaInterfacePtr, &gammaKin)) ++number2On;
214 
215  sigma2MaxSum = 0.;
216  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
217  sigma2MaxSum += container2Ptrs[i2]->sigmaMax();
218  }
219 
220  // Check whether to create event weight from components.
221  doWt2 = !doLHA && !bias2Sel && !settings.flag("PhaseSpace:increaseMaximum");
222 
223  // Printout during initialization is optional.
224  if (settings.flag("Init:showProcesses")) {
225 
226  // Construct string with incoming beams and for cm energy.
227  string collision = "We collide " + particleDataPtr->name(idA)
228  + " with " + particleDataPtr->name(idB) + " at a CM energy of ";
229  string pad( max( 0, 51 - int(collision.length())), ' ');
230 
231  // Print initialization information: header.
232  cout << "\n *------- PYTHIA Process Initialization ---------"
233  << "-----------------*\n"
234  << " | "
235  << " |\n"
236  << " | " << collision << scientific << setprecision(3)
237  << setw(9) << eCM << " GeV" << pad << " |\n"
238  << " | "
239  << " |\n"
240  << " |---------------------------------------------------"
241  << "---------------|\n"
242  << " | "
243  << " | |\n"
244  << " | Subprocess Code"
245  << " | Estimated |\n"
246  << " | "
247  << " | max (mb) |\n"
248  << " | "
249  << " | |\n"
250  << " |---------------------------------------------------"
251  << "---------------|\n"
252  << " | "
253  << " | |\n";
254 
255  // Loop over existing processes: print individual process info.
256  map<int, double> sigmaMaxM;
257  map<int, string> nameM;
258  for (int i = 0; i < int(containerPtrs.size()); ++i) {
259  int code = containerPtrs[i]->code();
260  nameM[code] = containerPtrs[i]->name();
261  sigmaMaxM[code] = containerPtrs[i]->sigmaMax() > sigmaMaxM[code] ?
262  containerPtrs[i]->sigmaMax() : sigmaMaxM[code];
263  }
264  for (map<int, string>::iterator i = nameM.begin(); i != nameM.end(); ++i)
265  cout << " | " << left << setw(45) << i->second
266  << right << setw(5) << i->first << " | "
267  << scientific << setprecision(3) << setw(11)
268  << sigmaMaxM[i->first] << " |\n";
269 
270  // Loop over second hard processes, if any, and repeat as above.
271  if (doSecondHard) {
272  cout << " | "
273  << " | |\n"
274  << " |---------------------------------------------------"
275  <<"---------------|\n"
276  << " | "
277  <<" | |\n";
278  sigmaMaxM.clear();
279  nameM.clear();
280  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
281  int code = container2Ptrs[i2]->code();
282  nameM[code] = container2Ptrs[i2]->name();
283  sigmaMaxM[code] = container2Ptrs[i2]->sigmaMax() > sigmaMaxM[code] ?
284  container2Ptrs[i2]->sigmaMax() : sigmaMaxM[code];
285  }
286  for (map<int, string>::iterator i2 = nameM.begin(); i2 != nameM.end();
287  ++i2)
288  cout << " | " << left << setw(45) << i2->second
289  << right << setw(5) << i2->first << " | "
290  << scientific << setprecision(3) << setw(11)
291  << sigmaMaxM[i2->first] << " |\n";
292  }
293 
294  // Listing finished.
295  cout << " | "
296  << " |\n"
297  << " *------- End PYTHIA Process Initialization ----------"
298  <<"-------------*" << endl;
299  }
300 
301  // If sum of maxima vanishes then refuse to do anything.
302  if ( numberOn == 0 || sigmaMaxSum <= 0.) {
303  infoPtr->errorMsg("Error in ProcessLevel::init: "
304  "all processes have vanishing cross sections");
305  return false;
306  }
307  if ( doSecondHard && (number2On == 0 || sigma2MaxSum <= 0.) ) {
308  infoPtr->errorMsg("Error in ProcessLevel::init: "
309  "all second hard processes have vanishing cross sections");
310  return false;
311  }
312 
313  // If two hard processes then check whether some (but not all) agree.
314  allHardSame = true;
315  noneHardSame = true;
316  if (doSecondHard) {
317  bool foundMatch = false;
318 
319  // Check for each first process if matched in second.
320  for (int i = 0; i < int(containerPtrs.size()); ++i) {
321  foundMatch = false;
322  if (cutsOverlap)
323  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
324  if (container2Ptrs[i2]->code() == containerPtrs[i]->code())
325  foundMatch = true;
326  containerPtrs[i]->isSame( foundMatch );
327  if (!foundMatch) allHardSame = false;
328  if ( foundMatch) noneHardSame = false;
329  }
330 
331  // Check for each second process if matched in first.
332  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
333  foundMatch = false;
334  if (cutsOverlap)
335  for (int i = 0; i < int(containerPtrs.size()); ++i)
336  if (containerPtrs[i]->code() == container2Ptrs[i2]->code())
337  foundMatch = true;
338  container2Ptrs[i2]->isSame( foundMatch );
339  if (!foundMatch) allHardSame = false;
340  if ( foundMatch) noneHardSame = false;
341  }
342  }
343 
344  // Concluding classification, including cuts.
345  if (!cutsAgree) allHardSame = false;
346  someHardSame = !allHardSame && !noneHardSame;
347 
348  // Done.
349  return true;
350 }
351 
352 //--------------------------------------------------------------------------
353 
354 // Main routine to generate the hard process.
355 
356 bool ProcessLevel::next( Event& process) {
357 
358  // Generate the next event with two or one hard interactions.
359  bool physical = (doSecondHard) ? nextTwo( process) : nextOne( process);
360 
361  // Check that colour assignments make sense.
362  if (physical) physical = checkColours( process);
363 
364  // Done.
365  return physical;
366 }
367 
368 //--------------------------------------------------------------------------
369 
370 // Generate (= read in) LHA input of resonance decay only.
371 
372 bool ProcessLevel::nextLHAdec( Event& process) {
373 
374  // Read resonance decays from LHA interface.
375  infoPtr->setEndOfFile(false);
376  if (!lhaUpPtr->setEvent()) {
377  infoPtr->setEndOfFile(true);
378  return false;
379  }
380 
381  // Store LHA output in standard event record format.
382  containerLHAdec.constructDecays( process);
383 
384  // Done.
385  return true;
386 }
387 
388 //--------------------------------------------------------------------------
389 
390 // Accumulate and update statistics (after possible user veto).
391 
392 void ProcessLevel::accumulate( bool doAccumulate) {
393 
394  // Increase number of accepted events.
395  if (doAccumulate) containerPtrs[iContainer]->accumulate();
396 
397  // Provide current generated cross section estimate.
398  long nTrySum = 0;
399  long nSelSum = 0;
400  long nAccSum = 0;
401  double sigmaSum = 0.;
402  double delta2Sum = 0.;
403  double sigSelSum = 0.;
404  double weightSum = 0.;
405  int codeNow;
406  long nTryNow, nSelNow, nAccNow;
407  double sigmaNow, deltaNow, sigSelNow, weightNow;
408  map<int, bool> duplicate;
409  for (int i = 0; i < int(containerPtrs.size()); ++i)
410  if (containerPtrs[i]->sigmaMax() != 0.) {
411  codeNow = containerPtrs[i]->code();
412  nTryNow = containerPtrs[i]->nTried();
413  nSelNow = containerPtrs[i]->nSelected();
414  nAccNow = containerPtrs[i]->nAccepted();
415  sigmaNow = containerPtrs[i]->sigmaMC(doAccumulate);
416  deltaNow = containerPtrs[i]->deltaMC(doAccumulate);
417  sigSelNow = containerPtrs[i]->sigmaSelMC(doAccumulate);
418  weightNow = containerPtrs[i]->weightSum();
419  nTrySum += nTryNow;
420  nSelSum += nSelNow;
421  nAccSum += nAccNow;
422  sigmaSum += sigmaNow;
423  delta2Sum += pow2(deltaNow);
424  sigSelSum += sigSelNow;
425  weightSum += weightNow;
426  if (!doSecondHard) {
427  if (!duplicate[codeNow])
428  infoPtr->setSigma( codeNow, containerPtrs[i]->name(),
429  nTryNow, nSelNow, nAccNow, sigmaNow, deltaNow, weightNow);
430  else
431  infoPtr->addSigma( codeNow, nTryNow, nSelNow, nAccNow, sigmaNow,
432  deltaNow);
433  duplicate[codeNow] = true;
434  }
435  }
436 
437  // Normally only one hard interaction. Then store info and done.
438  if (!doSecondHard) {
439  double deltaSum = sqrtpos(delta2Sum);
440  infoPtr->setSigma( 0, "sum", nTrySum, nSelSum, nAccSum, sigmaSum,
441  deltaSum, weightSum);
442  return;
443  }
444 
445  // Increase counter for a second hard interaction.
446  if (doAccumulate) container2Ptrs[i2Container]->accumulate();
447 
448  // Cross section estimate for second hard process.
449  double sigma2Sum = 0.;
450  double sig2SelSum = 0.;
451  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
452  if (container2Ptrs[i2]->sigmaMax() != 0.) {
453  nTrySum += container2Ptrs[i2]->nTried();
454  if (doAccumulate) {
455  sigma2Sum += container2Ptrs[i2]->sigmaMC();
456  sig2SelSum += container2Ptrs[i2]->sigmaSelMC();
457  }
458  }
459 
460  // Average impact-parameter factor.
461  double impactFac = max( 1., infoPtr->enhanceMPIavg() );
462 
463  // Cross section estimate for combination of first and second process.
464  // Combine two possible ways and take average.
465  double sigmaComb = 0.5 * (sigmaSum * sig2SelSum + sigSelSum * sigma2Sum);
466  sigmaComb *= impactFac * maxPDFreweight / sigmaND;
467  if (allHardSame) sigmaComb *= 0.5;
468  double deltaComb = (nAccSum == 0) ? 0. : sqrtpos(2. / nAccSum) * sigmaComb;
469 
470  // Store info and done.
471  infoPtr->setSigma( 0, "sum", nTrySum, nSelSum, nAccSum, sigmaComb,
472  deltaComb, weightSum);
473 
474 }
475 
476 //--------------------------------------------------------------------------
477 
478 // Print statistics on cross sections and number of events.
479 
480 void ProcessLevel::statistics(bool reset) {
481 
482  // Special processing if two hard interactions selected.
483  if (doSecondHard) {
484  statistics2(reset);
485  return;
486  }
487 
488  // Header.
489  cout << "\n *------- PYTHIA Event and Cross Section Statistics ------"
490  << "-------------------------------------------------------*\n"
491  << " | "
492  << " |\n"
493  << " | Subprocess Code | "
494  << " Number of events | sigma +- delta |\n"
495  << " | | "
496  << "Tried Selected Accepted | (estimated) (mb) |\n"
497  << " | | "
498  << " | |\n"
499  << " |------------------------------------------------------------"
500  << "-----------------------------------------------------|\n"
501  << " | | "
502  << " | |\n";
503 
504  // Reset sum counters.
505  long nTrySum = 0;
506  long nSelSum = 0;
507  long nAccSum = 0;
508  double sigmaSum = 0.;
509  double delta2Sum = 0.;
510 
511  // Reset process maps.
512  map<int, string> nameM;
513  map<int, long> nTryM, nSelM, nAccM;
514  map<int, double> sigmaM, delta2M;
515  vector<ProcessContainer*> lheContainerPtrs;
516 
517  // Loop over existing processes.
518  for (int i = 0; i < int(containerPtrs.size()); ++i)
519  if (containerPtrs[i]->sigmaMax() != 0.) {
520 
521  // Read info for process. Sum counters.
522  nTrySum += containerPtrs[i]->nTried();
523  nSelSum += containerPtrs[i]->nSelected();
524  nAccSum += containerPtrs[i]->nAccepted();
525  sigmaSum += containerPtrs[i]->sigmaMC();
526  delta2Sum += pow2(containerPtrs[i]->deltaMC());
527 
528  // Skip Les Houches containers.
529  if (containerPtrs[i]->code() == 9999) {
530  lheContainerPtrs.push_back(containerPtrs[i]);
531  continue;
532  }
533 
534  // Internal process info.
535  int code = containerPtrs[i]->code();
536  nameM[code] = containerPtrs[i]->name();
537  nTryM[code] += containerPtrs[i]->nTried();
538  nSelM[code] += containerPtrs[i]->nSelected();
539  nAccM[code] += containerPtrs[i]->nAccepted();
540  sigmaM[code] += containerPtrs[i]->sigmaMC();
541  delta2M[code]+= pow2(containerPtrs[i]->deltaMC());
542  }
543 
544  // Print internal process info.
545  for (map<int, string>::iterator i = nameM.begin(); i != nameM.end(); ++i) {
546  int code = i->first;
547  cout << " | " << left << setw(45) << i->second
548  << right << setw(5) << code << " | "
549  << setw(11) << nTryM[code] << " " << setw(10) << nSelM[code] << " "
550  << setw(10) << nAccM[code] << " | " << scientific << setprecision(3)
551  << setw(11) << sigmaM[code]
552  << setw(11) << sqrtpos(delta2M[code]) << " |\n";
553  }
554 
555  // Print Les Houches process info.
556  for (int i = 0; i < int(lheContainerPtrs.size()); ++i) {
557  ProcessContainer *ptr = lheContainerPtrs[i];
558  cout << " | " << left << setw(45) << ptr->name()
559  << right << setw(5) << ptr->code() << " | "
560  << setw(11) << ptr->nTried() << " " << setw(10) << ptr->nSelected()
561  << " " << setw(10) << ptr->nAccepted() << " | " << scientific
562  << setprecision(3) << setw(11) << ptr->sigmaMC() << setw(11)
563  << ptr->deltaMC() << " |\n";
564 
565  // Print subdivision by user code for Les Houches process.
566  for (int j = 0; j < ptr->codeLHASize(); ++j)
567  cout << " | ... whereof user classification code " << setw(10)
568  << ptr->subCodeLHA(j) << " | " << setw(11) << ptr->nTriedLHA(j)
569  << " " << setw(10) << ptr->nSelectedLHA(j) << " " << setw(10)
570  << ptr->nAcceptedLHA(j) << " | | \n";
571  }
572 
573  // Print summed process info.
574  cout << " | | "
575  << " | |\n"
576  << " | " << left << setw(50) << "sum" << right << " | " << setw(11)
577  << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
578  << nAccSum << " | " << scientific << setprecision(3) << setw(11)
579  << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
580 
581  // Listing finished.
582  cout << " | "
583  << " |\n"
584  << " *------- End PYTHIA Event and Cross Section Statistics -----"
585  << "-----------------------------------------------------*" << endl;
586 
587  // Optionally reset statistics contants.
588  if (reset) resetStatistics();
589 
590 }
591 
592 //--------------------------------------------------------------------------
593 
594 // Reset statistics on cross sections and number of events.
595 
596 void ProcessLevel::resetStatistics() {
597 
598  for (int i = 0; i < int(containerPtrs.size()); ++i)
599  containerPtrs[i]->reset();
600  if (doSecondHard)
601  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
602  container2Ptrs[i2]->reset();
603 
604 }
605 
606 //--------------------------------------------------------------------------
607 
608 // Generate the next event with one interaction.
609 
610 bool ProcessLevel::nextOne( Event& process) {
611 
612  // Update CM energy for phase space selection.
613  double eCM = infoPtr->eCM();
614  for (int i = 0; i < int(containerPtrs.size()); ++i)
615  containerPtrs[i]->newECM(eCM);
616 
617  // Outer loop in case of rare failures.
618  bool physical = true;
619  for (int loop = 0; loop < MAXLOOP; ++loop) {
620  if (!physical) process.clear();
621  physical = true;
622 
623  // Loop over tries until trial event succeeds.
624  for ( ; ; ) {
625 
626  // Pick one of the subprocesses.
627  double sigmaMaxNow = sigmaMaxSum * rndmPtr->flat();
628  int iMax = containerPtrs.size() - 1;
629  iContainer = -1;
630  do sigmaMaxNow -= containerPtrs[++iContainer]->sigmaMax();
631  while (sigmaMaxNow > 0. && iContainer < iMax);
632 
633  // Do a trial event of this subprocess; accept or not.
634  if (containerPtrs[iContainer]->trialProcess()) break;
635 
636  // Check for end-of-file condition for Les Houches events.
637  if (infoPtr->atEndOfFile()) return false;
638  }
639 
640  // Update sum of maxima if current maximum violated.
641  if (containerPtrs[iContainer]->newSigmaMax()) {
642  sigmaMaxSum = 0.;
643  for (int i = 0; i < int(containerPtrs.size()); ++i)
644  sigmaMaxSum += containerPtrs[i]->sigmaMax();
645  }
646 
647  // Construct kinematics of acceptable process.
648  containerPtrs[iContainer]->constructState();
649  if ( !containerPtrs[iContainer]->constructProcess( process) )
650  physical = false;
651 
652  // For photon beams from leptons copy the state to additional photon beams.
653  if (beamHasGamma) {
654  beamGamAPtr->setGammaMode(beamAPtr->getGammaMode());
655  beamGamBPtr->setGammaMode(beamBPtr->getGammaMode());
656  }
657 
658  // Do all resonance decays.
659  if ( physical && doResDecays
660  && !containerPtrs[iContainer]->decayResonances( process) )
661  physical = false;
662 
663  // Retry process for unphysical states.
664  for (int i =1; i < process.size(); ++i)
665  if (process[i].e() < 0.) {
666  infoPtr->errorMsg("Error in ProcessLevel::nextOne: "
667  "Constructed particle with negative energy.");
668  physical = false;
669  }
670 
671  // Add any junctions to the process event record list.
672  if (physical) findJunctions( process);
673 
674  // Check that enough room for beam remnants in the photon beams and
675  // set the valence content for photon beams.
676  // Do not check for softQCD processes since no initiators yet.
677  if ( ( ( ( beamAPtr->isGamma() && !beamAPtr->isUnresolved() )
678  || ( beamBPtr->isGamma() && !beamBPtr->isUnresolved() ) )
679  || ( beamAPtr->hasResGamma() || beamBPtr->hasResGamma() ) )
680  && !containerPtrs[iContainer]->isSoftQCD() ) {
681  if ( !roomForRemnants() ) {
682  physical = false;
683  continue;
684  }
685  }
686 
687  // Outer loop should normally work first time around.
688  if (physical) break;
689  }
690 
691  // Update information in VMD beams according to chosen state.
692  if (infoPtr->isVMDstateA()) {
693  beamVMDAPtr->setGammaMode(beamAPtr->getGammaMode());
694  beamVMDAPtr->setVMDstate(true, infoPtr->idVMDA(), infoPtr->mVMDA(),
695  infoPtr->scaleVMDA(), true);
696  }
697  if (infoPtr->isVMDstateB()) {
698  beamVMDBPtr->setGammaMode(beamBPtr->getGammaMode());
699  beamVMDBPtr->setVMDstate(true, infoPtr->idVMDB(), infoPtr->mVMDB(),
700  infoPtr->scaleVMDB(), true);
701  }
702 
703  // Done.
704  return physical;
705 }
706 
707 //--------------------------------------------------------------------------
708 
709 // Generate the next event with two hard interactions.
710 
711 bool ProcessLevel::nextTwo( Event& process) {
712 
713  // Update CM energy for phase space selection.
714  double eCM = infoPtr->eCM();
715  for (int i = 0; i < int(containerPtrs.size()); ++i)
716  containerPtrs[i]->newECM(eCM);
717  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
718  container2Ptrs[i2]->newECM(eCM);
719 
720  // Outer loop in case of rare failures.
721  bool physical = true;
722  double wtViol1 = 1.;
723  double wtViol2 = 1.;
724  for (int loop = 0; loop < MAXLOOP; ++loop) {
725  if (!physical) process.clear();
726  physical = true;
727 
728  // Loop over both hard processes to find consistent common kinematics.
729  for ( ; ; ) {
730 
731  // Loop internally over tries for hardest process until succeeds.
732  for ( ; ; ) {
733 
734  // Pick one of the subprocesses.
735  double sigmaMaxNow = sigmaMaxSum * rndmPtr->flat();
736  int iMax = containerPtrs.size() - 1;
737  iContainer = -1;
738  do sigmaMaxNow -= containerPtrs[++iContainer]->sigmaMax();
739  while (sigmaMaxNow > 0. && iContainer < iMax);
740 
741  // Do a trial event of this subprocess; accept or not.
742  if (containerPtrs[iContainer]->trialProcess()) break;
743 
744  // Check for end-of-file condition for Les Houches events.
745  if (infoPtr->atEndOfFile()) return false;
746  }
747 
748  // Update sum of maxima if current maximum violated. Event weight.
749  if (containerPtrs[iContainer]->newSigmaMax()) {
750  sigmaMaxSum = 0.;
751  for (int i = 0; i < int(containerPtrs.size()); ++i)
752  sigmaMaxSum += containerPtrs[i]->sigmaMax();
753  }
754  wtViol1 = (doWt2) ? infoPtr->weight() : 1.;
755 
756  // Loop internally over tries for second hardest process until succeeds.
757  for ( ; ; ) {
758 
759  // Pick one of the subprocesses.
760  double sigma2MaxNow = sigma2MaxSum * rndmPtr->flat();
761  int i2Max = container2Ptrs.size() - 1;
762  i2Container = -1;
763  do sigma2MaxNow -= container2Ptrs[++i2Container]->sigmaMax();
764  while (sigma2MaxNow > 0. && i2Container < i2Max);
765 
766  // Do a trial event of this subprocess; accept or not.
767  if (container2Ptrs[i2Container]->trialProcess()) break;
768  }
769 
770  // Update sum of maxima if current maximum violated.
771  if (container2Ptrs[i2Container]->newSigmaMax()) {
772  sigma2MaxSum = 0.;
773  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
774  sigma2MaxSum += container2Ptrs[i2]->sigmaMax();
775  }
776  wtViol2 = (doWt2) ? infoPtr->weight() : 1.;
777 
778  // Pick incoming flavours (etc), needed for PDF reweighting.
779  containerPtrs[iContainer]->constructState();
780  container2Ptrs[i2Container]->constructState();
781 
782  // Check whether common set of x values is kinematically possible.
783  double xA1 = containerPtrs[iContainer]->x1();
784  double xB1 = containerPtrs[iContainer]->x2();
785  double xA2 = container2Ptrs[i2Container]->x1();
786  double xB2 = container2Ptrs[i2Container]->x2();
787  if (xA1 + xA2 >= 1. || xB1 + xB2 >= 1.) continue;
788 
789  // Parton densities for independent interactions.
790  int idA1 = containerPtrs[iContainer]->id1();
791  int idB1 = containerPtrs[iContainer]->id2();
792  int idA2 = container2Ptrs[i2Container]->id1();
793  int idB2 = container2Ptrs[i2Container]->id2();
794  double Q2Fac1 = containerPtrs[iContainer]->Q2Fac();
795  double Q2Fac2 = container2Ptrs[i2Container]->Q2Fac();
796  double pdfA1Raw = beamAPtr->xf( idA1, xA1,Q2Fac1);
797  double pdfB1Raw = beamBPtr->xf( idB1, xB1,Q2Fac1);
798  double pdfA2Raw = beamAPtr->xf( idA2, xA2,Q2Fac2);
799  double pdfB2Raw = beamBPtr->xf( idB2, xB2,Q2Fac2);
800 
801  // Reset beam contents. Remove partons in second interaction from beams,
802  // and reevaluate pdf's for first interaction.
803  beamAPtr->clear();
804  beamBPtr->clear();
805  beamAPtr->append( 3, idA2, xA2);
806  beamAPtr->xfISR( 0, idA2, xA2, Q2Fac2);
807  beamAPtr->pickValSeaComp();
808  beamBPtr->append( 4, idB2, xB2);
809  beamBPtr->xfISR( 0, idB2, xB2, Q2Fac2);
810  beamBPtr->pickValSeaComp();
811  double pdfA1Mod = beamAPtr->xfMPI( idA1, xA1,Q2Fac1);
812  double pdfB1Mod = beamBPtr->xfMPI( idB1, xB1,Q2Fac1);
813 
814  // Reset beam contents. Remove partons in first interaction from beams,
815  // and reevaluate pdf's for second interaction.
816  beamAPtr->clear();
817  beamBPtr->clear();
818  beamAPtr->append( 3, idA1, xA1);
819  beamAPtr->xfISR( 0, idA1, xA1, Q2Fac1);
820  beamAPtr->pickValSeaComp();
821  beamBPtr->append( 4, idB1, xB1);
822  beamBPtr->xfISR( 0, idB1, xB1, Q2Fac1);
823  beamBPtr->pickValSeaComp();
824  double pdfA2Mod = beamAPtr->xfMPI( idA2, xA2,Q2Fac2);
825  double pdfB2Mod = beamBPtr->xfMPI( idB2, xB2,Q2Fac2);
826 
827  // Define modified PDF weight as average of two orderings above.
828  double wtPdf1 = (pdfA1Mod * pdfB1Mod) / (pdfA1Raw * pdfB1Raw);
829  double wtPdf2 = (pdfA2Mod * pdfB2Mod) / (pdfA2Raw * pdfB2Raw);
830  double wtPdfSame = 0.5 * (wtPdf1 + wtPdf2);
831 
832  // Reduce by a factor of 2 for identical processes when others not,
833  // and when in same phase space region.
834  if ( someHardSame && containerPtrs[iContainer]->isSame()
835  && container2Ptrs[i2Container]->isSame()) {
836  if (cutsAgree) wtPdfSame *= 0.5;
837  else {
838  double mHat1 = containerPtrs[iContainer]->mHat();
839  double pTHat1 = containerPtrs[iContainer]->pTHat();
840  double mHat2 = container2Ptrs[i2Container]->mHat();
841  double pTHat2 = container2Ptrs[i2Container]->pTHat();
842  if (mHat1 > mHatMin2 && mHat1 < mHatMax2
843  && pTHat1 > pTHatMin2 && pTHat1 < pTHatMax2
844  && mHat2 > mHatMin1 && mHat2 < mHatMax1
845  && pTHat2 > pTHatMin1 && pTHat2 < pTHatMax1) wtPdfSame *= 0.5;
846  }
847  }
848 
849  // Hit-and-miss to compensate for PDF weights. Catch maximum violation.
850  wtPdfSame *= wtViol1 * wtViol2 / maxPDFreweight;
851  if (doWt2) infoPtr->setWeight( max( 1., wtPdfSame), 0 );
852  if (wtPdfSame > 1.) infoPtr->errorMsg("Warning in ProcessLevel::next"
853  "Two: joint PDF correction gives weight above unity");
854  if (wtPdfSame < rndmPtr->flat()) continue;
855 
856  // If come this far then acceptable event.
857  break;
858  }
859 
860  // Construct kinematics of acceptable processes.
861  Event process2;
862  process2.init( "(second hard)", particleDataPtr, startColTag);
863  process2.initColTag();
864  if ( !containerPtrs[iContainer]->constructProcess( process) )
865  physical = false;
866  if (physical && !container2Ptrs[i2Container]->constructProcess( process2,
867  false) ) physical = false;
868 
869  // Do all resonance decays.
870  if ( physical && doResDecays
871  && !containerPtrs[iContainer]->decayResonances( process) )
872  physical = false;
873  if ( physical && doResDecays
874  && !container2Ptrs[i2Container]->decayResonances( process2) )
875  physical = false;
876 
877  // Append second hard interaction to normal process object.
878  if (physical) {
879  combineProcessRecords( process, process2);
880 
881  // Add any junctions to the process event record list.
882  findJunctions( process);
883 
884  // Outer loop should normally work first time around.
885  break;
886  }
887  }
888 
889  // Done.
890  return physical;
891 }
892 
893 //--------------------------------------------------------------------------
894 
895 // Check that enough room for beam remnants is left and fix the valence
896 // content for photon beams.
897 
898 bool ProcessLevel::roomForRemnants() {
899 
900  // Set the beamParticle pointers to photon beams.
901  bool beamAhasResGamma = beamAPtr->hasResGamma();
902  bool beamBhasResGamma = beamBPtr->hasResGamma();
903  bool beamHasResGamma = beamAhasResGamma || beamBhasResGamma;
904  BeamParticle* tmpBeamAPtr = beamAhasResGamma ? beamGamAPtr : beamAPtr;
905  BeamParticle* tmpBeamBPtr = beamBhasResGamma ? beamGamBPtr : beamBPtr;
906 
907  // Check whether photons are unresolved.
908  bool resGammaA = !(beamGamAPtr->isUnresolved());
909  bool resGammaB = !(beamGamBPtr->isUnresolved());
910 
911  // Get the x_gamma values from beam particle.
912  double xGamma1 = beamAPtr->xGamma();
913  double xGamma2 = beamBPtr->xGamma();
914 
915  // Clear the previous choice.
916  tmpBeamAPtr->posVal(-1);
917  tmpBeamBPtr->posVal(-1);
918 
919  // Store the relevant information.
920  int id1 = containerPtrs[iContainer]->id1();
921  int id2 = containerPtrs[iContainer]->id2();
922  double x1 = containerPtrs[iContainer]->x1();
923  double x2 = containerPtrs[iContainer]->x2();
924  double Q2 = containerPtrs[iContainer]->Q2Fac();
925 
926  // Invariant mass of gamma-gamma system.
927  double eCMgmgm = infoPtr->eCM();
928 
929  // If photon(s) from beam particle(s) use the derived gmgm CM energy.
930  if (beamHasResGamma) eCMgmgm = infoPtr->eCMsub();
931 
932  // Calculate the mT left for the beams after hard interaction.
933  double mTRem = 0;
934 
935  // Direct-resolved processes with photons from lepton beams.
936  if ( resGammaA != resGammaB && beamHasResGamma ) {
937  double wTot = infoPtr->eCMsub();
938  double w2scat = infoPtr->sHatNew();
939  mTRem = wTot - sqrt(w2scat);
940 
941  // Direct-resolved processes with photons beams.
942  } else if ( tmpBeamAPtr->isUnresolved() && !tmpBeamBPtr->isUnresolved() ) {
943  mTRem = eCMgmgm*( 1. - sqrt( x2) );
944  } else if ( !tmpBeamAPtr->isUnresolved() && tmpBeamBPtr->isUnresolved() ) {
945  mTRem = eCMgmgm*( 1. - sqrt( x1) );
946 
947  // Resolved-resolved processes.
948  } else {
949 
950  // Photons from lepton beams.
951  if ( beamAhasResGamma && beamBhasResGamma) {
952 
953  // Rescale the x_gamma values according to the new invariant mass
954  // of the gamma+gamma system and rescale x values.
955  double sCM = infoPtr->s();
956  x1 /= xGamma1 * pow2(eCMgmgm) / ( xGamma1 * xGamma2 * sCM);
957  x2 /= xGamma2 * pow2(eCMgmgm) / ( xGamma1 * xGamma2 * sCM);
958  }
959 
960  // Invariant mass left with resolved photons.
961  mTRem = eCMgmgm * sqrt( (1. - x1)*(1. - x2) );
962  }
963 
964  // Initial values.
965  double m1 = 0, m2 = 0;
966  bool physical = false;
967 
968  // If no ISR or MPI decide the valence content according to the hard process.
969  if ( !doISR && !doMPI ) {
970 
971  // For physical process a few tries for the valence content should suffice.
972  int nTry = 0, maxTry = 4;
973 
974  while (!physical) {
975 
976  // Check whether the hard parton is a valence quark and if not use the
977  // parametrization for the valence flavor ratios.
978  bool init1Val = tmpBeamAPtr->isGamma() ?
979  tmpBeamAPtr->gammaInitiatorIsVal(0, id1, x1, Q2) : false;
980  bool init2Val = tmpBeamBPtr->isGamma() ?
981  tmpBeamBPtr->gammaInitiatorIsVal(0, id2, x2, Q2) : false;
982 
983  // If no ISR is generated must leave room for beam remnants.
984  // Calculate the required amount of energy for three different cases:
985  // Hard parton is a valence quark: Remnant mass = m_val.
986  // Hard parton is a gluon: Remnant mass = 2*m_val.
987  // Hard parton is not valence quark: Remnant mass = 2*m_val + m_hard.
988  // Unresolved photon: Remnant mass = 0.
989  if ( tmpBeamAPtr->isGamma() ) {
990  if ( !resGammaA) {
991  m1 = 0;
992  } else if (init1Val) {
993  m1 = particleDataPtr->m0(id1);
994  } else {
995  m1 = 2*( particleDataPtr->m0( tmpBeamAPtr->getGammaValFlavour() ) );
996  if (id1 != 21) m1 += particleDataPtr->m0(id1);
997  }
998 
999  // For hadrons start with hadron mass.
1000  } else if ( tmpBeamAPtr->isHadron() ) {
1001  m1 = particleDataPtr->m0(tmpBeamAPtr->id());
1002 
1003  // If a valence flavor, remove the mass from remnants, else add.
1004  int valSign1 = (tmpBeamAPtr->nValence(id1) > 0) ? -1 : 1;
1005  m1 = m1 + valSign1 * particleDataPtr->m0(id1);
1006  }
1007 
1008  // Photons.
1009  if ( tmpBeamBPtr->isGamma() ) {
1010  if ( !resGammaB) {
1011  m2 = 0;
1012  } else if (init2Val) {
1013  m2 = particleDataPtr->m0(id2);
1014  } else {
1015  m2 = 2*( particleDataPtr->m0( tmpBeamBPtr->getGammaValFlavour() ) );
1016  if (id2 != 21) m2 += particleDataPtr->m0(id2);
1017  }
1018 
1019  // For hadrons start with hadron mass.
1020  } else if ( tmpBeamBPtr->isHadron() ) {
1021  m2 = particleDataPtr->m0(tmpBeamBPtr->id());
1022 
1023  // If a valence flavor, remove the mass from remnants, else add.
1024  int valSign2 = (tmpBeamBPtr->nValence(id2) > 0) ? -1 : 1;
1025  m2 = m2 + valSign2 * particleDataPtr->m0(id2);
1026  }
1027 
1028  // Check whether room for remnants.
1029  physical = ( (m1 + m2) < mTRem );
1030 
1031  // Check that maximum number of trials not exceeded.
1032  ++nTry;
1033  if (nTry == maxTry) {
1034  if ( abs(id1) == 5 || abs(id2) == 5 ) {
1035  infoPtr->errorMsg("Warning in ProcessLevel::roomForRemnants: "
1036  "No room for bottom quarks in beam remnants");
1037  } else if ( abs(id1) == 4 || abs(id2) == 4 ) {
1038  infoPtr->errorMsg("Warning in ProcessLevel::roomForRemnants: "
1039  "No room for charm quarks in beam remnants");
1040  } else {
1041  infoPtr->errorMsg("Warning in ProcessLevel::roomForRemnants: "
1042  "No room for light quarks in beam remnants");
1043  }
1044  break;
1045  }
1046  }
1047 
1048  // With ISR or MPI the initiator list can change so reject only
1049  // process which will surely fail.
1050  } else {
1051 
1052  // Do not allow processes that ISR cannot turn into physical one.
1053  int idLight = 2;
1054 
1055  // Side A with a photon or hadron.
1056  if ( tmpBeamAPtr->isGamma() ) {
1057  m1 = (id1 == 21) ? 2*( particleDataPtr->m0( idLight ) ) :
1058  particleDataPtr->m0( id1 );
1059  } else if ( tmpBeamAPtr->isHadron() ) {
1060  m1 = particleDataPtr->m0( tmpBeamAPtr->id() );
1061  int valSign1 = (tmpBeamAPtr->nValence(id1) > 0) ? -1 : 1;
1062  m1 = m1 + valSign1 * particleDataPtr->m0(id1);
1063  }
1064 
1065  // Side B with a photon or hadron.
1066  if ( tmpBeamBPtr->isGamma() ) {
1067  m2 = (id2 == 21) ? 2*( particleDataPtr->m0( idLight ) ) :
1068  particleDataPtr->m0( id2 );
1069  } else if ( tmpBeamBPtr->isHadron() ) {
1070  m2 = particleDataPtr->m0( tmpBeamBPtr->id() );
1071  int valSign2 = (tmpBeamBPtr->nValence(id2) > 0) ? -1 : 1;
1072  m2 = m2 + valSign2 * particleDataPtr->m0(id2);
1073  }
1074 
1075  // No remnants needed for direct photons.
1076  if ( !resGammaA && !(tmpBeamAPtr->isHadron()) ) m1 = 0;
1077  if ( !resGammaB && !(tmpBeamBPtr->isHadron()) ) m2 = 0;
1078 
1079  // Check whether room for remnants.
1080  physical = ( (m1 + m2) < mTRem );
1081  if (physical == false) {
1082  if ( abs(id1) == 5 || abs(id2) == 5 ) {
1083  infoPtr->errorMsg("Warning in ProcessLevel::roomForRemnants: "
1084  "No room for bottom quarks in beam remnants");
1085  } else if ( abs(id1) == 4 || abs(id2) == 4 ) {
1086  infoPtr->errorMsg("Warning in ProcessLevel::roomForRemnants: "
1087  "No room for charm quarks in beam remnants");
1088  } else {
1089  infoPtr->errorMsg("Warning in ProcessLevel::roomForRemnants: "
1090  "No room for light quarks in beam remnants");
1091  }
1092  }
1093  }
1094 
1095  return physical;
1096 }
1097 
1098 //--------------------------------------------------------------------------
1099 
1100 // Append second hard interaction to normal process object.
1101 // Complication: all resonance decay chains must be put at the end.
1102 
1103 void ProcessLevel::combineProcessRecords( Event& process, Event& process2) {
1104 
1105  // Find first event record size, excluding resonances.
1106  int nSize = process.size();
1107  int nHard = 5;
1108  while (nHard < nSize && process[nHard].mother1() == 3) ++nHard;
1109 
1110  // Save resonance products temporarily elsewhere.
1111  vector<Particle> resProd;
1112  if (nSize > nHard) {
1113  for (int i = nHard; i < nSize; ++i) resProd.push_back( process[i] );
1114  process.popBack(nSize - nHard);
1115  }
1116 
1117  // Find second event record size, excluding resonances.
1118  int nSize2 = process2.size();
1119  int nHard2 = 5;
1120  while (nHard2 < nSize2 && process2[nHard2].mother1() == 3) ++nHard2;
1121 
1122  // Find amount of necessary position and colour offset for second process.
1123  int addPos = nHard - 3;
1124  int addCol = process.lastColTag() - startColTag;
1125 
1126  // Loop over all particles (except beams) from second process.
1127  for (int i = 3; i < nSize2; ++i) {
1128 
1129  // Offset mother and daughter pointers and colour tags of particle.
1130  process2[i].offsetHistory( 2, addPos, 2, addPos);
1131  process2[i].offsetCol( addCol);
1132 
1133  // Append hard-process particles from process2 to process.
1134  if (i < nHard2) process.append( process2[i] );
1135  }
1136 
1137  // Reinsert resonance decay chains of first hard process.
1138  int addPos2 = nHard2 - 3;
1139  if (nHard < nSize) {
1140 
1141  // Offset daughter pointers of unmoved mothers.
1142  for (int i = 5; i < nHard; ++i)
1143  process[i].offsetHistory( 0, 0, nHard - 1, addPos2);
1144 
1145  // Modify history of resonance products when restoring.
1146  for (int i = 0; i < int(resProd.size()); ++i) {
1147  resProd[i].offsetHistory( nHard - 1, addPos2, nHard - 1, addPos2);
1148  process.append( resProd[i] );
1149  }
1150  }
1151 
1152  // Insert resonance decay chains of second hard process.
1153  if (nHard2 < nSize2) {
1154  int nHard3 = nHard + nHard2 - 3;
1155  int addPos3 = nSize - nHard;
1156 
1157  // Offset daughter pointers of second-process mothers.
1158  for (int i = nHard + 2; i < nHard3; ++i)
1159  process[i].offsetHistory( 0, 0, nHard3 - 1, addPos3);
1160 
1161  // Modify history of second-process resonance products and insert.
1162  for (int i = nHard2; i < nSize2; ++i) {
1163  process2[i].offsetHistory( nHard3 - 1, addPos3, nHard3 - 1, addPos3);
1164  process.append( process2[i] );
1165  }
1166  }
1167 
1168  // Store PDF scale for second interaction.
1169  process.scaleSecond( process2.scale() );
1170 
1171 }
1172 
1173 //--------------------------------------------------------------------------
1174 
1175 // Add any junctions to the process event record list.
1176 // Also check that do not doublebook if called repeatedly.
1177 
1178 void ProcessLevel::findJunctions( Event& junEvent) {
1179 
1180  // Check all hard vertices for BNV
1181  for (int i = 1; i<junEvent.size(); i++) {
1182 
1183  // Ignore colorless particles and stages before hard-scattering
1184  // final state.
1185  if (abs(junEvent[i].status()) <= 21 || junEvent[i].colType() == 0)
1186  continue;
1187  vector<int> motherList = junEvent[i].motherList();
1188  int iMot1 = motherList[0];
1189  vector<int> sisterList = junEvent[iMot1].daughterList();
1190 
1191  // Check baryon number of vertex.
1192  int barSum = 0;
1193  map<int,int> colVertex, acolVertex;
1194 
1195  // Loop over mothers (enter with crossed colors and negative sign).
1196  for (unsigned int indx = 0; indx < motherList.size(); indx++) {
1197  int iMot = motherList[indx];
1198  if ( abs(junEvent[iMot].colType()) == 1 )
1199  barSum -= junEvent[iMot].colType();
1200  else if ( abs(junEvent[iMot].colType()) == 3)
1201  barSum -= 2*junEvent[iMot].colType()/3;
1202  int col = junEvent[iMot].acol();
1203  int acol = junEvent[iMot].col();
1204 
1205  // If unmatched (so far), add end. Else erase matching parton.
1206  if (col > 0) {
1207  if (acolVertex.find(col) == acolVertex.end() ) colVertex[col] = iMot;
1208  else acolVertex.erase(col);
1209  } else if (col < 0) {
1210  if (colVertex.find(-col) == colVertex.end() ) acolVertex[-col] = iMot;
1211  else colVertex.erase(-col);
1212  }
1213  if (acol > 0) {
1214  if (colVertex.find(acol) == colVertex.end()) acolVertex[acol] = iMot;
1215  else colVertex.erase(acol);
1216  } else if (acol < 0) {
1217  if (acolVertex.find(-acol) == acolVertex.end())
1218  colVertex[-acol] = iMot;
1219  else acolVertex.erase(-acol);
1220  }
1221  }
1222 
1223  // Loop over sisters.
1224  for (unsigned int indx = 0; indx < sisterList.size(); indx++) {
1225  int iDau = sisterList[indx];
1226  if ( abs(junEvent[iDau].colType()) == 1 )
1227  barSum += junEvent[iDau].colType();
1228  else if ( abs(junEvent[iDau].colType()) == 3)
1229  barSum += 2*junEvent[iDau].colType()/3;
1230  int col = junEvent[iDau].col();
1231  int acol = junEvent[iDau].acol();
1232 
1233  // If unmatched (so far), add end. Else erase matching parton.
1234  if (col > 0) {
1235  if (acolVertex.find(col) == acolVertex.end() ) colVertex[col] = iDau;
1236  else acolVertex.erase(col);
1237  } else if (col < 0) {
1238  if (colVertex.find(-col) == colVertex.end() ) acolVertex[-col] = iDau;
1239  else colVertex.erase(-col);
1240  }
1241  if (acol > 0) {
1242  if (colVertex.find(acol) == colVertex.end()) acolVertex[acol] = iDau;
1243  else colVertex.erase(acol);
1244  } else if (acol < 0) {
1245  if (acolVertex.find(-acol) == acolVertex.end())
1246  colVertex[-acol] = iDau;
1247  else acolVertex.erase(-acol);
1248  }
1249 
1250  }
1251 
1252  // Skip if baryon number conserved in this vertex.
1253  if (barSum == 0) continue;
1254 
1255  // Check and skip any junctions that have already been added.
1256  for (int iJun = 0; iJun < junEvent.sizeJunction(); ++iJun) {
1257  // Remove the tags corresponding to each of the 3 existing junction legs.
1258  for (int j = 0; j < 3; ++j) {
1259  int colNow = junEvent.colJunction(iJun, j);
1260  if (junEvent.kindJunction(iJun) % 2 == 1) colVertex.erase(colNow);
1261  else acolVertex.erase(colNow);
1262  }
1263  }
1264 
1265  // Skip if no junction colors remain.
1266  if (colVertex.size() == 0 && acolVertex.size() == 0) continue;
1267 
1268  // If baryon number violated, is B = +1 or -1 (larger values not handled).
1269  int kindJun = 0;
1270  if (colVertex.size() == 3 && acolVertex.size() == 0) kindJun = 1;
1271  else if (colVertex.size() == 0 && acolVertex.size() == 3) kindJun = 2;
1272  else {
1273  infoPtr->errorMsg("Error in ProcessLevel::findJunctions: "
1274  "N(unmatched (anti)colour tags) != 3");
1275  return;
1276  }
1277 
1278  // From now on, use colJun as shorthand for colVertex or acolVertex.
1279  map<int,int> colJun = (kindJun == 1) ? colVertex : acolVertex;
1280 
1281  // Order so incoming tags appear first in colVec, outgoing tags last.
1282  vector<int> colVec;
1283  for (map<int,int>::iterator it = colJun.begin();
1284  it != colJun.end(); it++) {
1285  int col = it->first;
1286  int iCol = it->second;
1287  // Step across final-state gluons (if they come from ISR => kindJun += 2)
1288  int iColNow = iCol;
1289  int colNow = col;
1290  int nLoop = 0;
1291  while (junEvent[iColNow].isFinal() && junEvent[iColNow].id() == 21) {
1292  colNow = (kindJun % 2 == 1) ? junEvent[iColNow].acol()
1293  : junEvent[iColNow].col();
1294  ++nLoop;
1295  for (int j=0; j<(int)junEvent.size(); ++j) {
1296  // Check for matching initial-state (anti)colour
1297  if ( !junEvent[j].isFinal() ) {
1298  if ( (kindJun%2 == 1 && junEvent[j].acol() == colNow)
1299  || (kindJun%2 == 0 && junEvent[j].col() == colNow) ) {
1300  iColNow = j;
1301  break;
1302  }
1303  }
1304  // Step across final-state gluon
1305  else if ( (kindJun%2 == 1 && junEvent[j].col() == colNow)
1306  || (kindJun%2 == 0 && junEvent[j].acol() == colNow) ) {
1307  iColNow = j;
1308  break;
1309  }
1310  }
1311  // Check for infinite loop
1312  if (nLoop > (int)junEvent.size()) {
1313  infoPtr->errorMsg("Error in ProcessLevel::findJunctions: "
1314  "failed to trace across final-state gluons");
1315  iColNow = iCol;
1316  break;
1317  }
1318  }
1319  for (unsigned int indx = 0; indx < motherList.size(); indx++) {
1320  if (iColNow == motherList[indx]) {
1321  kindJun += 2;
1322  colVec.insert(colVec.begin(),col);
1323  }
1324  }
1325  if (colVec.size() == 0 || colVec[0] != col) colVec.push_back(col);
1326  }
1327 
1328  // Add junction with these tags.
1329  junEvent.appendJunction( kindJun, colVec[0], colVec[1], colVec[2]);
1330 
1331  }
1332 
1333  // Check if any junction colour lines appear both as incoming and outgoing
1334  // E.g. MadGraph writes out 501 + 502 -> -503 -> 501 + 502. Repaint such
1335  // cases so that the outgoing tags are different from the incoming ones.
1336  bool foundMatch = true;
1337  while (foundMatch) {
1338  foundMatch = false;
1339  for (int iJun=0; iJun<junEvent.sizeJunction(); ++iJun) {
1340  int kindJunA = junEvent.kindJunction(iJun);
1341  for (int jJun=iJun+1; jJun<junEvent.sizeJunction(); ++jJun) {
1342  int kindJunB = junEvent.kindJunction(jJun);
1343  // Only consider junction-antijunction combinations
1344  if ( kindJunA % 2 == kindJunB % 2 ) continue;
1345  // Check if all tags same
1346  int nMatch = 0;
1347  for (int iLeg=0; iLeg<3; ++iLeg)
1348  for (int jLeg=0; jLeg<3; ++jLeg)
1349  if (junEvent.colJunction(iJun, iLeg) ==
1350  junEvent.colJunction(jJun, jLeg)) ++nMatch;
1351  if (nMatch == 3) {
1352  foundMatch = true;
1353  // Decide which junction to repaint the final-state legs of
1354  // (If both are types 3-4, arbitrarily decide to repaint iJun)
1355  int kJun = 0;
1356  if (kindJunA >= 5 || kindJunA <= 2) kJun = jJun;
1357  else kJun = iJun;
1358  int kindJun = junEvent.kindJunction(kJun);
1359  int col = junEvent.colJunction(kJun,0);
1360  // Find the corresponding decay vertex: repaint daughters recursively
1361  for (int i=0; i<junEvent.size(); ++i) {
1362  // Find a resonance with the right colour
1363  if ( kindJun % 2 == 0 && junEvent[i].col() != col ) continue;
1364  else if ( kindJun % 2 == 1 && junEvent[i].acol() != col ) continue;
1365  else if ( junEvent[i].status() != -22 ) continue;
1366  // Check if colour is conserved in decay
1367  int iDau1 = junEvent[i].daughter1();
1368  int iDau2 = junEvent[i].daughter2();
1369  bool isBNV = true;
1370  for (int iDau = iDau1; iDau <= iDau2; ++iDau)
1371  if ( (kindJun % 2 == 0 && junEvent[iDau].col() == col)
1372  || (kindJun % 2 == 1 && junEvent[iDau].acol() == col) )
1373  isBNV = false;
1374  if ( !isBNV ) continue;
1375  vector<int> daughters = junEvent[i].daughterListRecursive();
1376  int lastColTag = junEvent.lastColTag();
1377  for (int iLeg = 1; iLeg <= 2; ++iLeg) {
1378  // Encode new colour tag so last digit remains the same
1379  // (That way, new CR type models would still allow reconnection)
1380  int colOld = junEvent.colJunction(kJun, iLeg);
1381  int colNew = (lastColTag/10) * 10 + 10 + colOld % 10 ;
1382  // Count up used colour tags until we reach colNew
1383  while (junEvent.lastColTag() < colNew) junEvent.nextColTag();
1384  junEvent.colJunction(kJun,iLeg,colNew);
1385  for (int jDau = 0; jDau < (int)daughters.size(); ++jDau) {
1386  int iDau = daughters[jDau];
1387  if ( kindJun % 2 == 1 && junEvent[iDau].col() == colOld)
1388  junEvent[iDau].col(colNew);
1389  else if ( kindJun % 2 == 0 && junEvent[iDau].acol() == colOld)
1390  junEvent[iDau].acol(colNew);
1391  }
1392  }
1393  // Done (we found the right BNV vertex and acted recursively)
1394  break;
1395  }
1396  }
1397  }
1398  }
1399  }
1400 }
1401 //--------------------------------------------------------------------------
1402 
1403 // Check that colours match up.
1404 
1405 bool ProcessLevel::checkColours( Event& process) {
1406 
1407  // Variables and arrays for common usage.
1408  bool physical = true;
1409  bool match;
1410  int colType, col, acol, iPos, iNow, iNowA;
1411  vector<int> colTags, colPos, acolPos;
1412 
1413  // Check that each particle has the kind of colours expected of it.
1414  for (int i = 0; i < process.size(); ++i) {
1415  colType = process[i].colType();
1416  col = process[i].col();
1417  acol = process[i].acol();
1418  if (colType == 0 && (col != 0 || acol != 0)) physical = false;
1419  else if (colType == 1 && (col <= 0 || acol != 0)) physical = false;
1420  else if (colType == -1 && (col != 0 || acol <= 0)) physical = false;
1421  else if (colType == 2 && (col <= 0 || acol <= 0)) physical = false;
1422  // Colour-sextet assignments (colType == 3 for sextet, -3 for antisextet).
1423  // Sextet (two colours) represented by (colour, negative anticolour) tags.
1424  // Antisextet (two anticolours) by (negative colour, anticolour) tags.
1425  else if (colType == 3 && (col <= 0 || acol >= 0)) physical = false;
1426  else if (colType == -3 && (col >= 0 || acol <= 0)) physical = false;
1427  // All other cases
1428  else if (colType == -2 || colType < -3 || colType > 3) physical = false;
1429 
1430  // Add to the list of colour tags.
1431  if (col > 0) {
1432  match = false;
1433  for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1434  if (col == colTags[ic]) match = true;
1435  if (!match) colTags.push_back(col);
1436  } else if (acol > 0) {
1437  match = false;
1438  for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1439  if (acol == colTags[ic]) match = true;
1440  if (!match) colTags.push_back(acol);
1441  }
1442  // Colour sextets : map negative colour -> anticolour and vice versa
1443  if (col < 0) {
1444  match = false;
1445  for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1446  if (-col == colTags[ic]) match = true;
1447  if (!match) colTags.push_back(-col);
1448  } else if (acol < 0) {
1449  match = false;
1450  for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1451  if (-acol == colTags[ic]) match = true;
1452  if (!match) colTags.push_back(-acol);
1453  }
1454  }
1455 
1456  // Warn and give up if particles did not have the expected colours.
1457  if (!physical) {
1458  infoPtr->errorMsg("Error in ProcessLevel::checkColours: "
1459  "incorrect colour assignment");
1460  return false;
1461  }
1462 
1463  // Remove (anti)colours coming from an (anti)junction.
1464  for (int iJun = 0; iJun < process.sizeJunction(); ++iJun) {
1465  for (int j = 0; j < 3; ++j) {
1466  int colJun = process.colJunction(iJun, j);
1467  for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1468  if (colJun == colTags[ic]) {
1469  colTags[ic] = colTags[colTags.size() - 1];
1470  colTags.pop_back();
1471  break;
1472  }
1473  }
1474  }
1475 
1476  // Loop through all colour tags and find their positions (by sign).
1477  for (int ic = 0; ic < int(colTags.size()); ++ic) {
1478  col = colTags[ic];
1479  colPos.resize(0);
1480  acolPos.resize(0);
1481  for (int i = 0; i < process.size(); ++i) {
1482  if (process[i].col() == col || process[i].acol() == -col)
1483  colPos.push_back(i);
1484  if (process[i].acol() == col || process[i].col() == -col)
1485  acolPos.push_back(i);
1486  }
1487 
1488  // Trace colours back through decays; remove daughters.
1489  while (colPos.size() > 1) {
1490  iPos = colPos.size() - 1;
1491  iNow = colPos[iPos];
1492  if ( process[iNow].mother1() == colPos[iPos - 1]
1493  && process[iNow].mother2() == 0) colPos.pop_back();
1494  else break;
1495  }
1496  while (acolPos.size() > 1) {
1497  iPos = acolPos.size() - 1;
1498  iNow = acolPos[iPos];
1499  if ( process[iNow].mother1() == acolPos[iPos - 1]
1500  && process[iNow].mother2() == 0) acolPos.pop_back();
1501  else break;
1502  }
1503 
1504  // Now colour should exist in only 2 copies.
1505  if (colPos.size() + acolPos.size() != 2) physical = false;
1506 
1507  // If both colours or both anticolours then one mother of the other.
1508  else if (colPos.size() == 2) {
1509  iNow = colPos[1];
1510  if ( process[iNow].mother1() != colPos[0]
1511  && process[iNow].mother2() != colPos[0] ) physical = false;
1512  }
1513  else if (acolPos.size() == 2) {
1514  iNowA = acolPos[1];
1515  if ( process[iNowA].mother1() != acolPos[0]
1516  && process[iNowA].mother2() != acolPos[0] ) physical = false;
1517  }
1518 
1519  // If one of each then should have same mother(s), or point to beams.
1520  else {
1521  iNow = colPos[0];
1522  iNowA = acolPos[0];
1523  if ( process[iNow].status() == -21 && process[iNowA].status() == -21 );
1524  else if ( (process[iNow].mother1() != process[iNowA].mother1())
1525  || (process[iNow].mother2() != process[iNowA].mother2()) )
1526  physical = false;
1527  }
1528 
1529  }
1530 
1531  // Error message if problem found. Done.
1532  if (!physical) infoPtr->errorMsg("Error in ProcessLevel::checkColours: "
1533  "unphysical colour flow");
1534  return physical;
1535 
1536 }
1537 
1538 //--------------------------------------------------------------------------
1539 
1540 // Print statistics when two hard processes allowed.
1541 
1542 void ProcessLevel::statistics2(bool reset) {
1543 
1544  // Average impact-parameter factor.
1545  double impactFac = max( 1., infoPtr->enhanceMPIavg() );
1546 
1547  // Derive scaling factor to be applied to first set of processes.
1548  double sigma2SelSum = 0.;
1549  int n2SelSum = 0;
1550  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
1551  sigma2SelSum += container2Ptrs[i2]->sigmaSelMC();
1552  n2SelSum += container2Ptrs[i2]->nSelected();
1553  }
1554  double factor1 = impactFac * maxPDFreweight * sigma2SelSum / sigmaND;
1555  double rel1Err = sqrt(1. / max(1, n2SelSum));
1556  if (allHardSame) factor1 *= 0.5;
1557 
1558  // Derive scaling factor to be applied to second set of processes.
1559  double sigma1SelSum = 0.;
1560  int n1SelSum = 0;
1561  for (int i = 0; i < int(containerPtrs.size()); ++i) {
1562  sigma1SelSum += containerPtrs[i]->sigmaSelMC();
1563  n1SelSum += containerPtrs[i]->nSelected();
1564  }
1565  double factor2 = impactFac * maxPDFreweight * sigma1SelSum / sigmaND;
1566  if (allHardSame) factor2 *= 0.5;
1567  double rel2Err = sqrt(1. / max(1, n1SelSum));
1568 
1569  // Header.
1570  cout << "\n *------- PYTHIA Event and Cross Section Statistics ------"
1571  << "--------------------------------------------------*\n"
1572  << " | "
1573  << " |\n"
1574  << " | Subprocess Code | "
1575  << "Number of events | sigma +- delta |\n"
1576  << " | | Tried"
1577  << " Selected Accepted | (estimated) (mb) |\n"
1578  << " | | "
1579  << " | |\n"
1580  << " |------------------------------------------------------------"
1581  << "------------------------------------------------|\n"
1582  << " | | "
1583  << " | |\n"
1584  << " | First hard process: | "
1585  << " | |\n"
1586  << " | | "
1587  << " | |\n";
1588 
1589  // Reset sum counters.
1590  long nTrySum = 0;
1591  long nSelSum = 0;
1592  long nAccSum = 0;
1593  double sigmaSum = 0.;
1594  double delta2Sum = 0.;
1595 
1596  // Reset process maps.
1597  map<int, string> nameM;
1598  map<int, long> nTryM, nSelM, nAccM;
1599  map<int, double> sigmaM, delta2M;
1600 
1601  // Loop over existing first processes.
1602  for (int i = 0; i < int(containerPtrs.size()); ++i)
1603  if (containerPtrs[i]->sigmaMax() != 0.) {
1604 
1605  // Read info for process. Sum counters.
1606  int code = containerPtrs[i]->code();
1607  nTrySum += containerPtrs[i]->nTried();
1608  nSelSum += containerPtrs[i]->nSelected();
1609  nAccSum += containerPtrs[i]->nAccepted();
1610  sigmaSum += containerPtrs[i]->sigmaMC() * factor1;
1611  delta2Sum += pow2(containerPtrs[i]->deltaMC() * factor1);
1612  nameM[code] = containerPtrs[i]->name();
1613  nTryM[code] += containerPtrs[i]->nTried();
1614  nSelM[code] += containerPtrs[i]->nSelected();
1615  nAccM[code] += containerPtrs[i]->nAccepted();
1616  sigmaM[code] += containerPtrs[i]->sigmaMC() * factor1;
1617  delta2M[code] += pow2(containerPtrs[i]->deltaMC() * factor1);
1618  delta2M[code] += pow2(containerPtrs[i]->sigmaMC() * factor1 * rel1Err);
1619  }
1620 
1621  // Print first process info.
1622  for (map<int, string>::iterator i = nameM.begin(); i != nameM.end(); ++i) {
1623  int code = i->first;
1624  cout << " | " << left << setw(40) << i->second
1625  << right << setw(5) << code << " | "
1626  << setw(11) << nTryM[code] << " " << setw(10) << nSelM[code] << " "
1627  << setw(10) << nAccM[code] << " | " << scientific << setprecision(3)
1628  << setw(11) << sigmaM[code]
1629  << setw(11) << sqrtpos(delta2M[code]) << " |\n";
1630  }
1631 
1632  // Print summed info for first processes.
1633  delta2Sum += pow2( sigmaSum * rel1Err );
1634  cout << " | | "
1635  << " | |\n"
1636  << " | " << left << setw(45) << "sum" << right << " | " << setw(11)
1637  << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
1638  << nAccSum << " | " << scientific << setprecision(3) << setw(11)
1639  << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
1640 
1641  // Separation lines to second hard processes.
1642  cout << " | | "
1643  << " | |\n"
1644  << " |------------------------------------------------------------"
1645  << "------------------------------------------------|\n"
1646  << " | | "
1647  << " | |\n"
1648  << " | Second hard process: | "
1649  << " | |\n"
1650  << " | | "
1651  << " | |\n";
1652 
1653  // Reset sum counters.
1654  nTrySum = 0;
1655  nSelSum = 0;
1656  nAccSum = 0;
1657  sigmaSum = 0.;
1658  delta2Sum = 0.;
1659 
1660  // Reset process maps.
1661  nameM.clear();
1662  nTryM.clear();
1663  nSelM.clear();
1664  nAccM.clear();
1665  sigmaM.clear();
1666  delta2M.clear();
1667 
1668  // Loop over existing second processes.
1669  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
1670  if (container2Ptrs[i2]->sigmaMax() != 0.) {
1671 
1672  // Read info for process. Sum counters.
1673  int code = container2Ptrs[i2]->code();
1674  nTrySum += container2Ptrs[i2]->nTried();
1675  nSelSum += container2Ptrs[i2]->nSelected();
1676  nAccSum += container2Ptrs[i2]->nAccepted();
1677  sigmaSum += container2Ptrs[i2]->sigmaMC() * factor2;
1678  delta2Sum += pow2(container2Ptrs[i2]->deltaMC() * factor2);
1679  nameM[code] = container2Ptrs[i2]->name();
1680  nTryM[code] += container2Ptrs[i2]->nTried();
1681  nSelM[code] += container2Ptrs[i2]->nSelected();
1682  nAccM[code] += container2Ptrs[i2]->nAccepted();
1683  sigmaM[code] += container2Ptrs[i2]->sigmaMC() * factor2;
1684  delta2M[code] += pow2(container2Ptrs[i2]->deltaMC() * factor2);
1685  delta2M[code] += pow2(container2Ptrs[i2]->sigmaMC() * factor2 * rel2Err);
1686  }
1687 
1688  // Print second process info.
1689  for (map<int, string>::iterator i2 = nameM.begin(); i2 != nameM.end();
1690  ++i2) {
1691  int code = i2->first;
1692  cout << " | " << left << setw(40) << i2->second
1693  << right << setw(5) << code << " | "
1694  << setw(11) << nTryM[code] << " " << setw(10) << nSelM[code] << " "
1695  << setw(10) << nAccM[code] << " | " << scientific << setprecision(3)
1696  << setw(11) << sigmaM[code]
1697  << setw(11) << sqrtpos(delta2M[code]) << " |\n";
1698  }
1699 
1700  // Print summed info for second processes.
1701  delta2Sum += pow2( sigmaSum * rel2Err );
1702  cout << " | | "
1703  << " | |\n"
1704  << " | " << left << setw(45) << "sum" << right << " | " << setw(11)
1705  << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
1706  << nAccSum << " | " << scientific << setprecision(3) << setw(11)
1707  << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
1708 
1709  // Print information on how the two processes were combined.
1710  cout << " | | "
1711  << " | |\n"
1712  << " |------------------------------------------------------------"
1713  << "------------------------------------------------|\n"
1714  << " | "
1715  << " |\n"
1716  << " | Uncombined cross sections for the two event sets were "
1717  << setw(10) << sigma1SelSum << " and " << sigma2SelSum << " mb, "
1718  << "respectively, combined |\n"
1719  << " | using a sigma(nonDiffractive) of " << setw(10) << sigmaND
1720  << " mb and an impact-parameter enhancement factor of "
1721  << setw(10) << impactFac << ". |\n";
1722 
1723  // Listing finished.
1724  cout << " | "
1725  << " |\n"
1726  << " *------- End PYTHIA Event and Cross Section Statistics -----"
1727  << "------------------------------------------------*" << endl;
1728 
1729  // Optionally reset statistics contants.
1730  if (reset) resetStatistics();
1731 
1732 }
1733 
1734 //==========================================================================
1735 
1736 } // end namespace Pythia8
Definition: AgUStep.h:26