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) 2012 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // Function definitions (not found in the header) for the ProcessLevel class.
7 
8 #include "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( Info* infoPtrIn, Settings& settings,
45  ParticleData* particleDataPtrIn, Rndm* rndmPtrIn,
46  BeamParticle* beamAPtrIn, BeamParticle* beamBPtrIn,
47  Couplings* couplingsPtrIn, SigmaTotal* sigmaTotPtrIn, bool doLHA,
48  SusyLesHouches* slhaPtrIn, UserHooks* userHooksPtrIn,
49  vector<SigmaProcess*>& sigmaPtrs, ostream& os) {
50 
51  // Store input pointers for future use.
52  infoPtr = infoPtrIn;
53  particleDataPtr = particleDataPtrIn;
54  rndmPtr = rndmPtrIn;
55  beamAPtr = beamAPtrIn;
56  beamBPtr = beamBPtrIn;
57  couplingsPtr = couplingsPtrIn;
58  sigmaTotPtr = sigmaTotPtrIn;
59  userHooksPtr = userHooksPtrIn;
60  slhaPtr = slhaPtrIn;
61 
62  // Send on some input pointers.
63  resonanceDecays.init( infoPtr, particleDataPtr, rndmPtr);
64 
65  // Set up SigmaTotal. Store sigma_nondiffractive for future use.
66  sigmaTotPtr->init( infoPtr, settings, particleDataPtr);
67  int idA = infoPtr->idA();
68  int idB = infoPtr->idB();
69  double eCM = infoPtr->eCM();
70  sigmaTotPtr->calc( idA, idB, eCM);
71  sigmaND = sigmaTotPtr->sigmaND();
72 
73  // Options to allow second hard interaction and resonance decays.
74  doSecondHard = settings.flag("SecondHard:generate");
75  doSameCuts = settings.flag("PhaseSpace:sameForSecond");
76  doResDecays = settings.flag("ProcessLevel:resonanceDecays");
77  startColTag = settings.mode("Event:startColTag");
78 
79  // Second interaction not to be combined with biased phase space.
80  if (doSecondHard && userHooksPtr != 0
81  && userHooksPtr->canBiasSelection()) {
82  infoPtr->errorMsg("Error in ProcessLevel::init: "
83  "cannot combine second interaction with biased phase space");
84  return false;
85  }
86 
87  // Mass and pT cuts for two hard processes.
88  mHatMin1 = settings.parm("PhaseSpace:mHatMin");
89  mHatMax1 = settings.parm("PhaseSpace:mHatMax");
90  if (mHatMax1 < mHatMin1) mHatMax1 = eCM;
91  pTHatMin1 = settings.parm("PhaseSpace:pTHatMin");
92  pTHatMax1 = settings.parm("PhaseSpace:pTHatMax");
93  if (pTHatMax1 < pTHatMin1) pTHatMax1 = eCM;
94  mHatMin2 = settings.parm("PhaseSpace:mHatMinSecond");
95  mHatMax2 = settings.parm("PhaseSpace:mHatMaxSecond");
96  if (mHatMax2 < mHatMin2) mHatMax2 = eCM;
97  pTHatMin2 = settings.parm("PhaseSpace:pTHatMinSecond");
98  pTHatMax2 = settings.parm("PhaseSpace:pTHatMaxSecond");
99  if (pTHatMax2 < pTHatMin2) pTHatMax2 = eCM;
100 
101  // Check whether mass and pT ranges agree or overlap.
102  cutsAgree = doSameCuts;
103  if (mHatMin2 == mHatMin1 && mHatMax2 == mHatMax1 && pTHatMin2 == pTHatMin1
104  && pTHatMax2 == pTHatMax1) cutsAgree = true;
105  cutsOverlap = cutsAgree;
106  if (!cutsAgree) {
107  bool mHatOverlap = (max( mHatMin1, mHatMin2)
108  < min( mHatMax1, mHatMax2));
109  bool pTHatOverlap = (max( pTHatMin1, pTHatMin2)
110  < min( pTHatMax1, pTHatMax2));
111  if (mHatOverlap && pTHatOverlap) cutsOverlap = true;
112  }
113 
114  // Set up containers for all the internal hard processes.
115  SetupContainers setupContainers;
116  setupContainers.init(containerPtrs, settings, particleDataPtr, couplingsPtr);
117 
118  // Append containers for external hard processes, if any.
119  if (sigmaPtrs.size() > 0) {
120  for (int iSig = 0; iSig < int(sigmaPtrs.size()); ++iSig)
121  containerPtrs.push_back( new ProcessContainer(sigmaPtrs[iSig],
122  true) );
123  }
124 
125  // Append single container for Les Houches processes, if any.
126  if (doLHA) {
127  SigmaProcess* sigmaPtr = new SigmaLHAProcess();
128  containerPtrs.push_back( new ProcessContainer(sigmaPtr) );
129 
130  // Store location of this container, and send in LHA pointer.
131  iLHACont = containerPtrs.size() - 1;
132  containerPtrs[iLHACont]->setLHAPtr(lhaUpPtr);
133  }
134 
135  // If no processes found then refuse to do anything.
136  if ( int(containerPtrs.size()) == 0) {
137  infoPtr->errorMsg("Error in ProcessLevel::init: "
138  "no process switched on");
139  return false;
140  }
141 
142  // Check that SUSY couplings were indeed initialized where necessary.
143  bool hasSUSY = false;
144  for (int i = 0; i < int(containerPtrs.size()); ++i)
145  if (containerPtrs[i]->isSUSY()) hasSUSY = true;
146 
147  // If SUSY processes requested but no SUSY couplings present
148  if(hasSUSY && !couplingsPtr->isSUSY) {
149  infoPtr->errorMsg("Error in ProcessLevel::init: "
150  "SUSY process switched on but no SUSY couplings found");
151  return false;
152  }
153 
154  // Initialize SLHA blocks SMINPUTS and MASS from PYTHIA SM parameter values.
155  initSLHA();
156 
157  // Initialize each process.
158  int numberOn = 0;
159  for (int i = 0; i < int(containerPtrs.size()); ++i)
160  if (containerPtrs[i]->init(true, infoPtr, settings, particleDataPtr,
161  rndmPtr, beamAPtr, beamBPtr, couplingsPtr, sigmaTotPtr,
162  &resonanceDecays, slhaPtr, userHooksPtr)) ++numberOn;
163 
164  // Sum maxima for Monte Carlo choice.
165  sigmaMaxSum = 0.;
166  for (int i = 0; i < int(containerPtrs.size()); ++i)
167  sigmaMaxSum += containerPtrs[i]->sigmaMax();
168 
169  // Option to pick a second hard interaction: repeat as above.
170  int number2On = 0;
171  if (doSecondHard) {
172  setupContainers.init2(container2Ptrs, settings);
173  if ( int(container2Ptrs.size()) == 0) {
174  infoPtr->errorMsg("Error in ProcessLevel::init: "
175  "no second hard process switched on");
176  return false;
177  }
178  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
179  if (container2Ptrs[i2]->init(false, infoPtr, settings, particleDataPtr,
180  rndmPtr, beamAPtr, beamBPtr, couplingsPtr, sigmaTotPtr,
181  &resonanceDecays, slhaPtr, userHooksPtr)) ++number2On;
182  sigma2MaxSum = 0.;
183  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
184  sigma2MaxSum += container2Ptrs[i2]->sigmaMax();
185  }
186 
187  // Printout during initialization is optional.
188  if (settings.flag("Init:showProcesses")) {
189 
190  // Construct string with incoming beams and for cm energy.
191  string collision = "We collide " + particleDataPtr->name(idA)
192  + " with " + particleDataPtr->name(idB) + " at a CM energy of ";
193  string pad( 51 - collision.length(), ' ');
194 
195  // Print initialization information: header.
196  os << "\n *------- PYTHIA Process Initialization ---------"
197  << "-----------------*\n"
198  << " | "
199  << " |\n"
200  << " | " << collision << scientific << setprecision(3)
201  << setw(9) << eCM << " GeV" << pad << " |\n"
202  << " | "
203  << " |\n"
204  << " |---------------------------------------------------"
205  << "---------------|\n"
206  << " | "
207  << " | |\n"
208  << " | Subprocess Code"
209  << " | Estimated |\n"
210  << " | "
211  << " | max (mb) |\n"
212  << " | "
213  << " | |\n"
214  << " |---------------------------------------------------"
215  << "---------------|\n"
216  << " | "
217  << " | |\n";
218 
219 
220  // Loop over existing processes: print individual process info.
221  for (int i = 0; i < int(containerPtrs.size()); ++i)
222  os << " | " << left << setw(45) << containerPtrs[i]->name()
223  << right << setw(5) << containerPtrs[i]->code() << " | "
224  << scientific << setprecision(3) << setw(11)
225  << containerPtrs[i]->sigmaMax() << " |\n";
226 
227  // Loop over second hard processes, if any, and repeat as above.
228  if (doSecondHard) {
229  os << " | "
230  << " | |\n"
231  << " |---------------------------------------------------"
232  <<"---------------|\n"
233  << " | "
234  <<" | |\n";
235  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
236  os << " | " << left << setw(45) << container2Ptrs[i2]->name()
237  << right << setw(5) << container2Ptrs[i2]->code() << " | "
238  << scientific << setprecision(3) << setw(11)
239  << container2Ptrs[i2]->sigmaMax() << " |\n";
240  }
241 
242  // Listing finished.
243  os << " | "
244  << " |\n"
245  << " *------- End PYTHIA Process Initialization ----------"
246  <<"-------------*" << endl;
247  }
248 
249  // If sum of maxima vanishes then refuse to do anything.
250  if ( numberOn == 0 || sigmaMaxSum <= 0.) {
251  infoPtr->errorMsg("Error in ProcessLevel::init: "
252  "all processes have vanishing cross sections");
253  return false;
254  }
255  if ( doSecondHard && (number2On == 0 || sigma2MaxSum <= 0.) ) {
256  infoPtr->errorMsg("Error in ProcessLevel::init: "
257  "all second hard processes have vanishing cross sections");
258  return false;
259  }
260 
261  // If two hard processes then check whether some (but not all) agree.
262  allHardSame = true;
263  noneHardSame = true;
264  if (doSecondHard) {
265  bool foundMatch = false;
266 
267  // Check for each first process if matched in second.
268  for (int i = 0; i < int(containerPtrs.size()); ++i) {
269  foundMatch = false;
270  if (cutsOverlap)
271  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
272  if (container2Ptrs[i2]->code() == containerPtrs[i]->code())
273  foundMatch = true;
274  containerPtrs[i]->isSame( foundMatch );
275  if (!foundMatch) allHardSame = false;
276  if ( foundMatch) noneHardSame = false;
277  }
278 
279  // Check for each second process if matched in first.
280  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
281  foundMatch = false;
282  if (cutsOverlap)
283  for (int i = 0; i < int(containerPtrs.size()); ++i)
284  if (containerPtrs[i]->code() == container2Ptrs[i2]->code())
285  foundMatch = true;
286  container2Ptrs[i2]->isSame( foundMatch );
287  if (!foundMatch) allHardSame = false;
288  if ( foundMatch) noneHardSame = false;
289  }
290  }
291 
292  // Concluding classification, including cuts.
293  if (!cutsAgree) allHardSame = false;
294  someHardSame = !allHardSame && !noneHardSame;
295 
296  // Reset counters for average impact-parameter enhancement.
297  nImpact = 0;
298  sumImpactFac = 0.;
299  sum2ImpactFac = 0.;
300 
301  // Statistics for LHA events.
302  codeLHA.resize(0);
303  nEvtLHA.resize(0);
304 
305  // Done.
306  return true;
307 }
308 
309 //--------------------------------------------------------------------------
310 
311 // Main routine to generate the hard process.
312 
313 bool ProcessLevel::next( Event& process) {
314 
315  // Generate the next event with two or one hard interactions.
316  bool physical = (doSecondHard) ? nextTwo( process) : nextOne( process);
317 
318  // Check that colour assignments make sense.
319  if (physical) physical = checkColours( process);
320 
321  // Done.
322  return physical;
323 }
324 
325 //--------------------------------------------------------------------------
326 
327 // Accumulate and update statistics (after possible user veto).
328 
329 void ProcessLevel::accumulate() {
330 
331  // Increase number of accepted events.
332  containerPtrs[iContainer]->accumulate();
333 
334  // Provide current generated cross section estimate.
335  long nTrySum = 0;
336  long nSelSum = 0;
337  long nAccSum = 0;
338  double sigmaSum = 0.;
339  double delta2Sum = 0.;
340  double sigSelSum = 0.;
341  double weightSum = 0.;
342  for (int i = 0; i < int(containerPtrs.size()); ++i)
343  if (containerPtrs[i]->sigmaMax() != 0.) {
344  nTrySum += containerPtrs[i]->nTried();
345  nSelSum += containerPtrs[i]->nSelected();
346  nAccSum += containerPtrs[i]->nAccepted();
347  sigmaSum += containerPtrs[i]->sigmaMC();
348  delta2Sum += pow2(containerPtrs[i]->deltaMC());
349  sigSelSum += containerPtrs[i]->sigmaSelMC();
350  weightSum += containerPtrs[i]->weightSum();
351  }
352 
353  // For Les Houches events find subprocess type and update counter.
354  if (infoPtr->isLHA()) {
355  int codeLHANow = infoPtr->codeSub();
356  int iFill = -1;
357  for (int i = 0; i < int(codeLHA.size()); ++i)
358  if (codeLHANow == codeLHA[i]) iFill = i;
359  if (iFill >= 0) ++nEvtLHA[iFill];
360 
361  // Add new process when new code and then arrange in order.
362  else {
363  codeLHA.push_back(codeLHANow);
364  nEvtLHA.push_back(1);
365  for (int i = int(codeLHA.size()) - 1; i > 0; --i) {
366  if (codeLHA[i] < codeLHA[i - 1]) {
367  swap(codeLHA[i], codeLHA[i - 1]);
368  swap(nEvtLHA[i], nEvtLHA[i - 1]);
369  }
370  else break;
371  }
372  }
373  }
374 
375  // Normally only one hard interaction. Then store info and done.
376  if (!doSecondHard) {
377  double deltaSum = sqrtpos(delta2Sum);
378  infoPtr->setSigma( nTrySum, nSelSum, nAccSum, sigmaSum, deltaSum,
379  weightSum);
380  return;
381  }
382 
383  // Increase counter for a second hard interaction.
384  container2Ptrs[i2Container]->accumulate();
385 
386  // Update statistics on average impact factor.
387  ++nImpact;
388  sumImpactFac += infoPtr->enhanceMPI();
389  sum2ImpactFac += pow2(infoPtr->enhanceMPI());
390 
391  // Cross section estimate for second hard process.
392  double sigma2Sum = 0.;
393  double sig2SelSum = 0.;
394  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
395  if (container2Ptrs[i2]->sigmaMax() != 0.) {
396  nTrySum += container2Ptrs[i2]->nTried();
397  sigma2Sum += container2Ptrs[i2]->sigmaMC();
398  sig2SelSum += container2Ptrs[i2]->sigmaSelMC();
399  }
400 
401  // Average impact-parameter factor and error.
402  double invN = 1. / max(1, nImpact);
403  double impactFac = max( 1., sumImpactFac * invN);
404  double impactErr2 = ( sum2ImpactFac * invN / pow2(impactFac) - 1.) * invN;
405 
406  // Cross section estimate for combination of first and second process.
407  // Combine two possible ways and take average.
408  double sigmaComb = 0.5 * (sigmaSum * sig2SelSum + sigSelSum * sigma2Sum);
409  sigmaComb *= impactFac / sigmaND;
410  if (allHardSame) sigmaComb *= 0.5;
411  double deltaComb = sqrtpos(2. / nAccSum + impactErr2) * sigmaComb;
412 
413  // Store info and done.
414  infoPtr->setSigma( nTrySum, nSelSum, nAccSum, sigmaComb, deltaComb,
415  weightSum);
416 
417 }
418 
419 //--------------------------------------------------------------------------
420 
421 // Print statistics on cross sections and number of events.
422 
423 void ProcessLevel::statistics(bool reset, ostream& os) {
424 
425  // Special processing if two hard interactions selected.
426  if (doSecondHard) {
427  statistics2(reset, os);
428  return;
429  }
430 
431  // Header.
432  os << "\n *------- PYTHIA Event and Cross Section Statistics ------"
433  << "-------------------------------------------------------*\n"
434  << " | "
435  << " |\n"
436  << " | Subprocess Code | "
437  << " Number of events | sigma +- delta |\n"
438  << " | | "
439  << "Tried Selected Accepted | (estimated) (mb) |\n"
440  << " | | "
441  << " | |\n"
442  << " |------------------------------------------------------------"
443  << "-----------------------------------------------------|\n"
444  << " | | "
445  << " | |\n";
446 
447  // Reset sum counters.
448  long nTrySum = 0;
449  long nSelSum = 0;
450  long nAccSum = 0;
451  double sigmaSum = 0.;
452  double delta2Sum = 0.;
453 
454  // Loop over existing processes.
455  for (int i = 0; i < int(containerPtrs.size()); ++i)
456  if (containerPtrs[i]->sigmaMax() != 0.) {
457 
458  // Read info for process. Sum counters.
459  long nTry = containerPtrs[i]->nTried();
460  long nSel = containerPtrs[i]->nSelected();
461  long nAcc = containerPtrs[i]->nAccepted();
462  double sigma = containerPtrs[i]->sigmaMC();
463  double delta = containerPtrs[i]->deltaMC();
464  nTrySum += nTry;
465  nSelSum += nSel;
466  nAccSum += nAcc;
467  sigmaSum += sigma;
468  delta2Sum += pow2(delta);
469 
470  // Print individual process info.
471  os << " | " << left << setw(45) << containerPtrs[i]->name()
472  << right << setw(5) << containerPtrs[i]->code() << " | "
473  << setw(11) << nTry << " " << setw(10) << nSel << " "
474  << setw(10) << nAcc << " | " << scientific << setprecision(3)
475  << setw(11) << sigma << setw(11) << delta << " |\n";
476 
477  // Print subdivision by user code for Les Houches process.
478  if (containerPtrs[i]->code() == 9999)
479  for (int j = 0; j < int(codeLHA.size()); ++j)
480  os << " | ... whereof user classification code " << setw(10)
481  << codeLHA[j] << " | " << setw(10)
482  << nEvtLHA[j] << " | | \n";
483  }
484 
485  // Print summed process info.
486  os << " | | "
487  << " | |\n"
488  << " | " << left << setw(50) << "sum" << right << " | " << setw(11)
489  << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
490  << nAccSum << " | " << scientific << setprecision(3) << setw(11)
491  << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
492 
493  // Listing finished.
494  os << " | "
495  << " |\n"
496  << " *------- End PYTHIA Event and Cross Section Statistics -----"
497  << "-----------------------------------------------------*" << endl;
498 
499  // Optionally reset statistics contants.
500  if (reset) resetStatistics();
501 
502 }
503 
504 //--------------------------------------------------------------------------
505 
506 // Reset statistics on cross sections and number of events.
507 
508 void ProcessLevel::resetStatistics() {
509 
510  for (int i = 0; i < int(containerPtrs.size()); ++i)
511  containerPtrs[i]->reset();
512  if (doSecondHard)
513  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
514  container2Ptrs[i2]->reset();
515 
516 }
517 
518 //--------------------------------------------------------------------------
519 
520 // Initialize SLHA blocks SMINPUTS and MASS from PYTHIA SM parameter values.
521 
522 void ProcessLevel::initSLHA() {
523 
524  // Initialize block SMINPUTS.
525  string blockName = "sminputs";
526  double mZ = particleDataPtr->m0(23);
527  slhaPtr->set(blockName,1,1.0/couplingsPtr->alphaEM(pow2(mZ)));
528  slhaPtr->set(blockName,2,couplingsPtr->GF());
529  slhaPtr->set(blockName,3,couplingsPtr->alphaS(pow2(mZ)));
530  slhaPtr->set(blockName,4,mZ);
531  // b mass (should be running mass, here pole for time being)
532  slhaPtr->set(blockName,5,particleDataPtr->m0(5));
533  slhaPtr->set(blockName,6,particleDataPtr->m0(6));
534  slhaPtr->set(blockName,7,particleDataPtr->m0(15));
535  slhaPtr->set(blockName,8,particleDataPtr->m0(16));
536  slhaPtr->set(blockName,11,particleDataPtr->m0(11));
537  slhaPtr->set(blockName,12,particleDataPtr->m0(12));
538  slhaPtr->set(blockName,13,particleDataPtr->m0(13));
539  slhaPtr->set(blockName,14,particleDataPtr->m0(14));
540  // Force 3 lightest quarks massless
541  slhaPtr->set(blockName,21,double(0.0));
542  slhaPtr->set(blockName,22,double(0.0));
543  slhaPtr->set(blockName,23,double(0.0));
544  // c mass (should be running mass, here pole for time being)
545  slhaPtr->set(blockName,24,particleDataPtr->m0(4));
546 
547  // Initialize block MASS.
548  blockName = "mass";
549  int id = 1;
550  int count = 0;
551  while (particleDataPtr->nextId(id) > id) {
552  slhaPtr->set(blockName,id,particleDataPtr->m0(id));
553  id = particleDataPtr->nextId(id);
554  ++count;
555  if (count > 10000) {
556  infoPtr->errorMsg("Error in ProcessLevel::initSLHA: "
557  "encountered infinite loop when saving mass block");
558  break;
559  }
560  }
561 
562 }
563 
564 //--------------------------------------------------------------------------
565 
566 // Generate the next event with one interaction.
567 
568 bool ProcessLevel::nextOne( Event& process) {
569 
570  // Update CM energy for phase space selection.
571  double eCM = infoPtr->eCM();
572  for (int i = 0; i < int(containerPtrs.size()); ++i)
573  containerPtrs[i]->newECM(eCM);
574 
575  // Outer loop in case of rare failures.
576  bool physical = true;
577  for (int loop = 0; loop < MAXLOOP; ++loop) {
578  if (!physical) process.clear();
579  physical = true;
580 
581  // Loop over tries until trial event succeeds.
582  for ( ; ; ) {
583 
584  // Pick one of the subprocesses.
585  double sigmaMaxNow = sigmaMaxSum * rndmPtr->flat();
586  int iMax = containerPtrs.size() - 1;
587  iContainer = -1;
588  do sigmaMaxNow -= containerPtrs[++iContainer]->sigmaMax();
589  while (sigmaMaxNow > 0. && iContainer < iMax);
590 
591  // Do a trial event of this subprocess; accept or not.
592  if (containerPtrs[iContainer]->trialProcess()) break;
593 
594  // Check for end-of-file condition for Les Houches events.
595  if (infoPtr->atEndOfFile()) return false;
596  }
597 
598  // Update sum of maxima if current maximum violated.
599  if (containerPtrs[iContainer]->newSigmaMax()) {
600  sigmaMaxSum = 0.;
601  for (int i = 0; i < int(containerPtrs.size()); ++i)
602  sigmaMaxSum += containerPtrs[i]->sigmaMax();
603  }
604 
605  // Construct kinematics of acceptable process.
606  if ( !containerPtrs[iContainer]->constructProcess( process) )
607  physical = false;
608 
609  // Do all resonance decays.
610  if ( physical && doResDecays
611  && !containerPtrs[iContainer]->decayResonances( process) )
612  physical = false;
613 
614  // Add any junctions to the process event record list.
615  if (physical) findJunctions( process);
616 
617  // Outer loop should normally work first time around.
618  if (physical) break;
619  }
620 
621  // Done.
622  return physical;
623 }
624 
625 //--------------------------------------------------------------------------
626 
627 // Generate the next event with two hard interactions.
628 
629 bool ProcessLevel::nextTwo( Event& process) {
630 
631  // Update CM energy for phase space selection.
632  double eCM = infoPtr->eCM();
633  for (int i = 0; i < int(containerPtrs.size()); ++i)
634  containerPtrs[i]->newECM(eCM);
635  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
636  container2Ptrs[i2]->newECM(eCM);
637 
638  // Outer loop in case of rare failures.
639  bool physical = true;
640  for (int loop = 0; loop < MAXLOOP; ++loop) {
641  if (!physical) process.clear();
642  physical = true;
643 
644  // Loop over both hard processes to find consistent common kinematics.
645  for ( ; ; ) {
646 
647  // Loop internally over tries for hardest process until succeeds.
648  for ( ; ; ) {
649 
650  // Pick one of the subprocesses.
651  double sigmaMaxNow = sigmaMaxSum * rndmPtr->flat();
652  int iMax = containerPtrs.size() - 1;
653  iContainer = -1;
654  do sigmaMaxNow -= containerPtrs[++iContainer]->sigmaMax();
655  while (sigmaMaxNow > 0. && iContainer < iMax);
656 
657  // Do a trial event of this subprocess; accept or not.
658  if (containerPtrs[iContainer]->trialProcess()) break;
659 
660  // Check for end-of-file condition for Les Houches events.
661  if (infoPtr->atEndOfFile()) return false;
662  }
663 
664  // Update sum of maxima if current maximum violated.
665  if (containerPtrs[iContainer]->newSigmaMax()) {
666  sigmaMaxSum = 0.;
667  for (int i = 0; i < int(containerPtrs.size()); ++i)
668  sigmaMaxSum += containerPtrs[i]->sigmaMax();
669  }
670 
671  // Loop internally over tries for second hardest process until succeeds.
672  for ( ; ; ) {
673 
674  // Pick one of the subprocesses.
675  double sigma2MaxNow = sigma2MaxSum * rndmPtr->flat();
676  int i2Max = container2Ptrs.size() - 1;
677  i2Container = -1;
678  do sigma2MaxNow -= container2Ptrs[++i2Container]->sigmaMax();
679  while (sigma2MaxNow > 0. && i2Container < i2Max);
680 
681  // Do a trial event of this subprocess; accept or not.
682  if (container2Ptrs[i2Container]->trialProcess()) break;
683  }
684 
685  // Update sum of maxima if current maximum violated.
686  if (container2Ptrs[i2Container]->newSigmaMax()) {
687  sigma2MaxSum = 0.;
688  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
689  sigma2MaxSum += container2Ptrs[i2]->sigmaMax();
690  }
691 
692  // Check whether common set of x values is kinematically possible.
693  double xA1 = containerPtrs[iContainer]->x1();
694  double xB1 = containerPtrs[iContainer]->x2();
695  double xA2 = container2Ptrs[i2Container]->x1();
696  double xB2 = container2Ptrs[i2Container]->x2();
697  if (xA1 + xA2 >= 1. || xB1 + xB2 >= 1.) continue;
698 
699  // Reset beam contents. Naive parton densities for second interaction.
700  // (Subsequent procedure could be symmetrized, but would be overkill.)
701  beamAPtr->clear();
702  beamBPtr->clear();
703  int idA1 = containerPtrs[iContainer]->id1();
704  int idB1 = containerPtrs[iContainer]->id2();
705  int idA2 = container2Ptrs[i2Container]->id1();
706  int idB2 = container2Ptrs[i2Container]->id2();
707  double Q2Fac1 = containerPtrs[iContainer]->Q2Fac();
708  double Q2Fac2 = container2Ptrs[i2Container]->Q2Fac();
709  double pdfA2Raw = beamAPtr->xf( idA2, xA2,Q2Fac2);
710  double pdfB2Raw = beamBPtr->xf( idB2, xB2,Q2Fac2);
711 
712  // Remove partons in first interaction from beams.
713  beamAPtr->append( 3, idA1, xA1);
714  beamAPtr->xfISR( 0, idA1, xA1, Q2Fac1);
715  beamAPtr->pickValSeaComp();
716  beamBPtr->append( 4, idB1, xB1);
717  beamBPtr->xfISR( 0, idB1, xB1, Q2Fac1);
718  beamBPtr->pickValSeaComp();
719 
720  // Reevaluate pdf's for second interaction and weight by reduction.
721  double pdfA2Mod = beamAPtr->xfMPI( idA2, xA2,Q2Fac2);
722  double pdfB2Mod = beamBPtr->xfMPI( idB2, xB2,Q2Fac2);
723  double wtPdfMod = (pdfA2Mod * pdfB2Mod) / (pdfA2Raw * pdfB2Raw);
724  if (wtPdfMod < rndmPtr->flat()) continue;
725 
726  // Reduce by a factor of 2 for identical processes when others not,
727  // and when in same phase space region.
728  bool toLoop = false;
729  if ( someHardSame && containerPtrs[iContainer]->isSame()
730  && container2Ptrs[i2Container]->isSame()) {
731  if (cutsAgree) {
732  if (rndmPtr->flat() > 0.5) toLoop = true;
733  } else {
734  double mHat1 = containerPtrs[iContainer]->mHat();
735  double pTHat1 = containerPtrs[iContainer]->pTHat();
736  double mHat2 = container2Ptrs[i2Container]->mHat();
737  double pTHat2 = container2Ptrs[i2Container]->pTHat();
738  if (mHat1 > mHatMin2 && mHat1 < mHatMax2
739  && pTHat1 > pTHatMin2 && pTHat1 < pTHatMax2
740  && mHat2 > mHatMin1 && mHat2 < mHatMax1
741  && pTHat2 > pTHatMin1 && pTHat2 < pTHatMax1
742  && rndmPtr->flat() > 0.5) toLoop = true;
743  }
744  }
745  if (toLoop) continue;
746 
747  // If come this far then acceptable event.
748  break;
749  }
750 
751  // Construct kinematics of acceptable processes.
752  Event process2;
753  process2.init( "(second hard)", particleDataPtr, startColTag);
754  process2.initColTag();
755  if ( !containerPtrs[iContainer]->constructProcess( process) )
756  physical = false;
757  if (physical && !container2Ptrs[i2Container]->constructProcess( process2,
758  false) ) physical = false;
759 
760  // Do all resonance decays.
761  if ( physical && doResDecays
762  && !containerPtrs[iContainer]->decayResonances( process) )
763  physical = false;
764  if ( physical && doResDecays
765  && !container2Ptrs[i2Container]->decayResonances( process2) )
766  physical = false;
767 
768  // Append second hard interaction to normal process object.
769  if (physical) combineProcessRecords( process, process2);
770 
771  // Add any junctions to the process event record list.
772  if (physical) findJunctions( process);
773 
774  // Outer loop should normally work first time around.
775  if (physical) break;
776  }
777 
778  // Done.
779  return physical;
780 }
781 
782 //--------------------------------------------------------------------------
783 
784 // Append second hard interaction to normal process object.
785 // Complication: all resonance decay chains must be put at the end.
786 
787 void ProcessLevel::combineProcessRecords( Event& process, Event& process2) {
788 
789  // Find first event record size, excluding resonances.
790  int nSize = process.size();
791  int nHard = 5;
792  while (nHard < nSize && process[nHard].mother1() == 3) ++nHard;
793 
794  // Save resonance products temporarily elsewhere.
795  vector<Particle> resProd;
796  if (nSize > nHard) {
797  for (int i = nHard; i < nSize; ++i) resProd.push_back( process[i] );
798  process.popBack(nSize - nHard);
799  }
800 
801  // Find second event record size, excluding resonances.
802  int nSize2 = process2.size();
803  int nHard2 = 5;
804  while (nHard2 < nSize2 && process2[nHard2].mother1() == 3) ++nHard2;
805 
806  // Find amount of necessary position and colour offset for second process.
807  int addPos = nHard - 3;
808  int addCol = process.lastColTag() - startColTag;
809 
810  // Loop over all particles (except beams) from second process.
811  for (int i = 3; i < nSize2; ++i) {
812 
813  // Offset mother and daughter pointers and colour tags of particle.
814  process2[i].offsetHistory( 2, addPos, 2, addPos);
815  process2[i].offsetCol( addCol);
816 
817  // Append hard-process particles from process2 to process.
818  if (i < nHard2) process.append( process2[i] );
819  }
820 
821  // Reinsert resonance decay chains of first hard process.
822  int addPos2 = nHard2 - 3;
823  if (nHard < nSize) {
824 
825  // Offset daughter pointers of unmoved mothers.
826  for (int i = 5; i < nHard; ++i)
827  process[i].offsetHistory( 0, 0, nHard - 1, addPos2);
828 
829  // Modify history of resonance products when restoring.
830  for (int i = 0; i < int(resProd.size()); ++i) {
831  resProd[i].offsetHistory( nHard - 1, addPos2, nHard - 1, addPos2);
832  process.append( resProd[i] );
833  }
834  }
835 
836  // Insert resonance decay chains of second hard process.
837  if (nHard2 < nSize2) {
838  int nHard3 = nHard + nHard2 - 3;
839  int addPos3 = nSize - nHard;
840 
841  // Offset daughter pointers of second-process mothers.
842  for (int i = nHard + 2; i < nHard3; ++i)
843  process[i].offsetHistory( 0, 0, nHard3 - 1, addPos3);
844 
845  // Modify history of second-process resonance products and insert.
846  for (int i = nHard2; i < nSize2; ++i) {
847  process2[i].offsetHistory( nHard3 - 1, addPos3, nHard3 - 1, addPos3);
848  process.append( process2[i] );
849  }
850  }
851 
852  // Store PDF scale for second interaction.
853  process.scaleSecond( process2.scale() );
854 
855 }
856 
857 //--------------------------------------------------------------------------
858 
859 // Add any junctions to the process event record list.
860 // Also check that do not doublebook if called repeatedly.
861 
862 void ProcessLevel::findJunctions( Event& junEvent) {
863 
864  // Check all hard vertices for BNV
865  for (int i = 1; i<junEvent.size(); i++) {
866 
867  // Ignore colorless particles and stages before hard-scattering
868  // final state.
869  if (abs(junEvent[i].status()) <= 21 || junEvent[i].colType() == 0) continue;
870  vector<int> motherList = junEvent.motherList(i);
871  int iMot1 = motherList[0];
872  vector<int> sisterList = junEvent.daughterList(iMot1);
873 
874  // Check baryon number of vertex.
875  int barSum = 0;
876  map<int,int> colVertex, acolVertex;
877 
878  // Loop over mothers (enter with crossed colors and negative sign).
879  for (unsigned int indx = 0; indx < motherList.size(); indx++) {
880  int iMot = motherList[indx];
881  if ( abs(junEvent[iMot].colType()) == 1 )
882  barSum -= junEvent[iMot].colType();
883  else if ( abs(junEvent[iMot].colType()) == 3)
884  barSum -= 2*junEvent[iMot].colType()/3;
885  int col = junEvent[iMot].acol();
886  int acol = junEvent[iMot].col();
887 
888  // If unmatched (so far), add end. Else erase matching parton.
889  if (col > 0) {
890  if (acolVertex.find(col) == acolVertex.end() ) colVertex[col] = iMot;
891  else acolVertex.erase(col);
892  } else if (col < 0) {
893  if (colVertex.find(-col) == colVertex.end() ) acolVertex[-col] = iMot;
894  else colVertex.erase(-col);
895  }
896  if (acol > 0) {
897  if (colVertex.find(acol) == colVertex.end()) acolVertex[acol] = iMot;
898  else colVertex.erase(acol);
899  } else if (acol < 0) {
900  if (acolVertex.find(-acol) == acolVertex.end()) colVertex[-acol] = iMot;
901  else acolVertex.erase(-acol);
902  }
903  }
904 
905  // Loop over sisters.
906  for (unsigned int indx = 0; indx < sisterList.size(); indx++) {
907  int iDau = sisterList[indx];
908  if ( abs(junEvent[iDau].colType()) == 1 )
909  barSum += junEvent[iDau].colType();
910  else if ( abs(junEvent[iDau].colType()) == 3)
911  barSum += 2*junEvent[iDau].colType()/3;
912  int col = junEvent[iDau].col();
913  int acol = junEvent[iDau].acol();
914 
915  // If unmatched (so far), add end. Else erase matching parton.
916  if (col > 0) {
917  if (acolVertex.find(col) == acolVertex.end() ) colVertex[col] = iDau;
918  else acolVertex.erase(col);
919  } else if (col < 0) {
920  if (colVertex.find(-col) == colVertex.end() ) acolVertex[-col] = iDau;
921  else colVertex.erase(-col);
922  }
923  if (acol > 0) {
924  if (colVertex.find(acol) == colVertex.end()) acolVertex[acol] = iDau;
925  else colVertex.erase(acol);
926  } else if (acol < 0) {
927  if (acolVertex.find(-acol) == acolVertex.end()) colVertex[-acol] = iDau;
928  else acolVertex.erase(-acol);
929  }
930 
931  }
932 
933  // Skip if baryon number conserved in this vertex.
934  if (barSum == 0) continue;
935 
936  // Check and skip any junctions that have already been added.
937  for (int iJun = 0; iJun < junEvent.sizeJunction(); ++iJun) {
938  // Remove the tags corresponding to each of the 3 existing junction legs.
939  for (int j = 0; j < 3; ++j) {
940  int colNow = junEvent.colJunction(iJun, j);
941  if (junEvent.kindJunction(iJun) % 2 == 1) colVertex.erase(colNow);
942  else acolVertex.erase(colNow);
943  }
944  }
945 
946  // Skip if no junction colors remain.
947  if (colVertex.size() == 0 && acolVertex.size() == 0) continue;
948 
949  // If baryon number violated, is B = +1 or -1 (larger values not handled).
950  int kindJun = 0;
951  if (colVertex.size() == 3 && acolVertex.size() == 0) kindJun = 1;
952  else if (colVertex.size() == 0 && acolVertex.size() == 3) kindJun = 2;
953  else {
954  infoPtr->errorMsg("Error in ProcessLevel::findJunctions: "
955  "N(unmatched (anti)colour tags) != 3");
956  return;
957  }
958 
959  // From now on, use colJun as shorthand for colVertex or acolVertex.
960  map<int,int> colJun = (kindJun == 1) ? colVertex : acolVertex;
961 
962  // Order so incoming tags appear first in colVec, outgoing tags last.
963  vector<int> colVec;
964  for (map<int,int>::iterator it = colJun.begin();
965  it != colJun.end(); it++) {
966  int col = it->first;
967  int iCol = it->second;
968  for (unsigned int indx = 0; indx < motherList.size(); indx++) {
969  if (iCol == motherList[indx]) {
970  kindJun += 2;
971  colVec.insert(colVec.begin(),col);
972  }
973  }
974  if (colVec.size() == 0 || colVec[0] != col) colVec.push_back(col);
975  }
976 
977  // Add junction with these tags.
978  junEvent.appendJunction( kindJun, colVec[0], colVec[1], colVec[2]);
979 
980  }
981 
982 }
983 //--------------------------------------------------------------------------
984 
985 // Check that colours match up.
986 
987 bool ProcessLevel::checkColours( Event& process) {
988 
989  // Variables and arrays for common usage.
990  bool physical = true;
991  bool match;
992  int colType, col, acol, iPos, iNow, iNowA;
993  vector<int> colTags, colPos, acolPos;
994 
995  // Check that each particle has the kind of colours expected of it.
996  for (int i = 0; i < process.size(); ++i) {
997  colType = process[i].colType();
998  col = process[i].col();
999  acol = process[i].acol();
1000  if (colType == 0 && (col != 0 || acol != 0)) physical = false;
1001  else if (colType == 1 && (col <= 0 || acol != 0)) physical = false;
1002  else if (colType == -1 && (col != 0 || acol <= 0)) physical = false;
1003  else if (colType == 2 && (col <= 0 || acol <= 0)) physical = false;
1004  // Preparations for colour-sextet assignments
1005  // (colour,colour) = (colour,negative anticolour)
1006  else if (colType == 3 && (col <= 0 || acol >= 0)) physical = false;
1007  else if (colType == -3 && (col >= 0 || acol <= 0)) physical = false;
1008  // All other cases
1009  else if (colType < -1 || colType > 3) physical = false;
1010 
1011  // Add to the list of colour tags.
1012  if (col > 0) {
1013  match = false;
1014  for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1015  if (col == colTags[ic]) match = true;
1016  if (!match) colTags.push_back(col);
1017  } else if (acol > 0) {
1018  match = false;
1019  for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1020  if (acol == colTags[ic]) match = true;
1021  if (!match) colTags.push_back(acol);
1022  }
1023  // Colour sextets : map negative colour -> anticolour and vice versa
1024  else if (col < 0) {
1025  match = false;
1026  for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1027  if (-col == colTags[ic]) match = true;
1028  if (!match) colTags.push_back(-col);
1029  } else if (acol < 0) {
1030  match = false;
1031  for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1032  if (-acol == colTags[ic]) match = true;
1033  if (!match) colTags.push_back(-acol);
1034  }
1035  }
1036 
1037  // Warn and give up if particles did not have the expected colours.
1038  if (!physical) {
1039  infoPtr->errorMsg("Error in ProcessLevel::checkColours: "
1040  "incorrect colour assignment");
1041  return false;
1042  }
1043 
1044  // Remove (anti)colours coming from an (anti)junction.
1045  for (int iJun = 0; iJun < process.sizeJunction(); ++iJun) {
1046  for (int j = 0; j < 3; ++j) {
1047  int colJun = process.colJunction(iJun, j);
1048  for (int ic = 0; ic < int(colTags.size()) ; ++ic)
1049  if (colJun == colTags[ic]) {
1050  colTags[ic] = colTags[colTags.size() - 1];
1051  colTags.pop_back();
1052  break;
1053  }
1054  }
1055  }
1056 
1057  // Loop through all colour tags and find their positions (by sign).
1058  for (int ic = 0; ic < int(colTags.size()); ++ic) {
1059  col = colTags[ic];
1060  colPos.resize(0);
1061  acolPos.resize(0);
1062  for (int i = 0; i < process.size(); ++i) {
1063  if (process[i].col() == col || process[i].acol() == -col)
1064  colPos.push_back(i);
1065  if (process[i].acol() == col || process[i].col() == -col)
1066  acolPos.push_back(i);
1067  }
1068 
1069  // Trace colours back through decays; remove daughters.
1070  while (colPos.size() > 1) {
1071  iPos = colPos.size() - 1;
1072  iNow = colPos[iPos];
1073  if ( process[iNow].mother1() == colPos[iPos - 1]
1074  && process[iNow].mother2() == 0) colPos.pop_back();
1075  else break;
1076  }
1077  while (acolPos.size() > 1) {
1078  iPos = acolPos.size() - 1;
1079  iNow = acolPos[iPos];
1080  if ( process[iNow].mother1() == acolPos[iPos - 1]
1081  && process[iNow].mother2() == 0) acolPos.pop_back();
1082  else break;
1083  }
1084 
1085  // Now colour should exist in only 2 copies.
1086  if (colPos.size() + acolPos.size() != 2) physical = false;
1087 
1088  // If both colours or both anticolours then one mother of the other.
1089  else if (colPos.size() == 2) {
1090  iNow = colPos[1];
1091  if ( process[iNow].mother1() != colPos[0]
1092  && process[iNow].mother2() != colPos[0] ) physical = false;
1093  }
1094  else if (acolPos.size() == 2) {
1095  iNowA = acolPos[1];
1096  if ( process[iNowA].mother1() != acolPos[0]
1097  && process[iNowA].mother2() != acolPos[0] ) physical = false;
1098  }
1099 
1100  // If one of each then should have same mother(s), or point to beams.
1101  else {
1102  iNow = colPos[0];
1103  iNowA = acolPos[0];
1104  if ( process[iNow].status() == -21 && process[iNowA].status() == -21 );
1105  else if ( (process[iNow].mother1() != process[iNowA].mother1())
1106  || (process[iNow].mother2() != process[iNowA].mother2()) )
1107  physical = false;
1108  }
1109 
1110  }
1111 
1112  // Error message if problem found. Done.
1113  if (!physical) infoPtr->errorMsg("Error in ProcessLevel::checkColours: "
1114  "unphysical colour flow");
1115  return physical;
1116 
1117 }
1118 
1119 //--------------------------------------------------------------------------
1120 
1121 // Print statistics when two hard processes allowed.
1122 
1123 void ProcessLevel::statistics2(bool reset, ostream& os) {
1124 
1125  // Average impact-parameter factor and error.
1126  double invN = 1. / max(1, nImpact);
1127  double impactFac = max( 1., sumImpactFac * invN);
1128  double impactErr2 = ( sum2ImpactFac * invN / pow2(impactFac) - 1.) * invN;
1129 
1130  // Derive scaling factor to be applied to first set of processes.
1131  double sigma2SelSum = 0.;
1132  int n2SelSum = 0;
1133  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2) {
1134  sigma2SelSum += container2Ptrs[i2]->sigmaSelMC();
1135  n2SelSum += container2Ptrs[i2]->nSelected();
1136  }
1137  double factor1 = impactFac * sigma2SelSum / sigmaND;
1138  double rel1Err = sqrt(1. / max(1, n2SelSum) + impactErr2);
1139  if (allHardSame) factor1 *= 0.5;
1140 
1141  // Derive scaling factor to be applied to second set of processes.
1142  double sigma1SelSum = 0.;
1143  int n1SelSum = 0;
1144  for (int i = 0; i < int(containerPtrs.size()); ++i) {
1145  sigma1SelSum += containerPtrs[i]->sigmaSelMC();
1146  n1SelSum += containerPtrs[i]->nSelected();
1147  }
1148  double factor2 = impactFac * sigma1SelSum / sigmaND;
1149  if (allHardSame) factor2 *= 0.5;
1150  double rel2Err = sqrt(1. / max(1, n1SelSum) + impactErr2);
1151 
1152  // Header.
1153  os << "\n *------- PYTHIA Event and Cross Section Statistics ------"
1154  << "--------------------------------------------------*\n"
1155  << " | "
1156  << " |\n"
1157  << " | Subprocess Code | "
1158  << "Number of events | sigma +- delta |\n"
1159  << " | | Tried"
1160  << " Selected Accepted | (estimated) (mb) |\n"
1161  << " | | "
1162  << " | |\n"
1163  << " |------------------------------------------------------------"
1164  << "------------------------------------------------|\n"
1165  << " | | "
1166  << " | |\n"
1167  << " | First hard process: | "
1168  << " | |\n"
1169  << " | | "
1170  << " | |\n";
1171 
1172  // Reset sum counters.
1173  long nTrySum = 0;
1174  long nSelSum = 0;
1175  long nAccSum = 0;
1176  double sigmaSum = 0.;
1177  double delta2Sum = 0.;
1178 
1179  // Loop over existing first processes.
1180  for (int i = 0; i < int(containerPtrs.size()); ++i)
1181  if (containerPtrs[i]->sigmaMax() != 0.) {
1182 
1183  // Read info for process. Sum counters.
1184  long nTry = containerPtrs[i]->nTried();
1185  long nSel = containerPtrs[i]->nSelected();
1186  long nAcc = containerPtrs[i]->nAccepted();
1187  double sigma = containerPtrs[i]->sigmaMC() * factor1;
1188  double delta2 = pow2( containerPtrs[i]->deltaMC() * factor1 );
1189  nTrySum += nTry;
1190  nSelSum += nSel;
1191  nAccSum += nAcc;
1192  sigmaSum += sigma;
1193  delta2Sum += delta2;
1194  delta2 += pow2( sigma * rel1Err );
1195 
1196  // Print individual process info.
1197  os << " | " << left << setw(40) << containerPtrs[i]->name()
1198  << right << setw(5) << containerPtrs[i]->code() << " | "
1199  << setw(11) << nTry << " " << setw(10) << nSel << " "
1200  << setw(10) << nAcc << " | " << scientific << setprecision(3)
1201  << setw(11) << sigma << setw(11) << sqrtpos(delta2) << " |\n";
1202  }
1203 
1204  // Print summed info for first processes.
1205  delta2Sum += pow2( sigmaSum * rel1Err );
1206  os << " | | "
1207  << " | |\n"
1208  << " | " << left << setw(45) << "sum" << right << " | " << setw(11)
1209  << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
1210  << nAccSum << " | " << scientific << setprecision(3) << setw(11)
1211  << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
1212 
1213 
1214  // Separation lines to second hard processes.
1215  os << " | | "
1216  << " | |\n"
1217  << " |------------------------------------------------------------"
1218  << "------------------------------------------------|\n"
1219  << " | | "
1220  << " | |\n"
1221  << " | Second hard process: | "
1222  << " | |\n"
1223  << " | | "
1224  << " | |\n";
1225 
1226  // Reset sum counters.
1227  nTrySum = 0;
1228  nSelSum = 0;
1229  nAccSum = 0;
1230  sigmaSum = 0.;
1231  delta2Sum = 0.;
1232 
1233  // Loop over existing second processes.
1234  for (int i2 = 0; i2 < int(container2Ptrs.size()); ++i2)
1235  if (container2Ptrs[i2]->sigmaMax() != 0.) {
1236 
1237  // Read info for process. Sum counters.
1238  long nTry = container2Ptrs[i2]->nTried();
1239  long nSel = container2Ptrs[i2]->nSelected();
1240  long nAcc = container2Ptrs[i2]->nAccepted();
1241  double sigma = container2Ptrs[i2]->sigmaMC() * factor2;
1242  double delta2 = pow2( container2Ptrs[i2]->deltaMC() * factor2 );
1243  nTrySum += nTry;
1244  nSelSum += nSel;
1245  nAccSum += nAcc;
1246  sigmaSum += sigma;
1247  delta2Sum += delta2;
1248  delta2 += pow2( sigma * rel2Err );
1249 
1250  // Print individual process info.
1251  os << " | " << left << setw(40) << container2Ptrs[i2]->name()
1252  << right << setw(5) << container2Ptrs[i2]->code() << " | "
1253  << setw(11) << nTry << " " << setw(10) << nSel << " "
1254  << setw(10) << nAcc << " | " << scientific << setprecision(3)
1255  << setw(11) << sigma << setw(11) << sqrtpos(delta2) << " |\n";
1256  }
1257 
1258  // Print summed info for second processes.
1259  delta2Sum += pow2( sigmaSum * rel2Err );
1260  os << " | | "
1261  << " | |\n"
1262  << " | " << left << setw(45) << "sum" << right << " | " << setw(11)
1263  << nTrySum << " " << setw(10) << nSelSum << " " << setw(10)
1264  << nAccSum << " | " << scientific << setprecision(3) << setw(11)
1265  << sigmaSum << setw(11) << sqrtpos(delta2Sum) << " |\n";
1266 
1267  // Print information on how the two processes were combined.
1268  os << " | | "
1269  << " | |\n"
1270  << " |------------------------------------------------------------"
1271  << "------------------------------------------------|\n"
1272  << " | "
1273  << " |\n"
1274  << " | Uncombined cross sections for the two event sets were "
1275  << setw(10) << sigma1SelSum << " and " << sigma2SelSum << " mb, "
1276  << "respectively, combined |\n"
1277  << " | using a sigma(nonDiffractive) of " << setw(10) << sigmaND
1278  << " mb and an impact-parameter enhancement factor of "
1279  << setw(10) << impactFac << ". |\n";
1280 
1281  // Listing finished.
1282  os << " | "
1283  << " |\n"
1284  << " *------- End PYTHIA Event and Cross Section Statistics -----"
1285  << "------------------------------------------------*" << endl;
1286 
1287  // Optionally reset statistics contants.
1288  if (reset) resetStatistics();
1289 
1290 }
1291 
1292 //==========================================================================
1293 
1294 } // end namespace Pythia8
1295 
Definition: AgUStep.h:26