StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
HIUserHooks.cc
1 // HIUserHooks.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 HIUserHooks.h header) for
7 // the heavy ion classes classes, and some related global functions.
8 
9 #include "Pythia8/Pythia.h"
10 #include "Pythia8/HIUserHooks.h"
11 
12 namespace Pythia8 {
13 
14 
15 //==========================================================================
16 
17 // NucleusModel base class.
18 
19 //--------------------------------------------------------------------------
20 
21 // Initialise base class, passing pointers to important objects.
22 
23 void NucleusModel::initPtr(int idIn, Settings & settingsIn,
24  ParticleData & particleDataIn, Rndm & rndIn) {
25  idSave = idIn;
26  settingsPtr = &settingsIn;
27  particleDataPtr = &particleDataIn;
28  rndPtr = &rndIn;
29  int decomp = abs(idSave);
30  ISave = decomp%10;
31  decomp /= 10;
32  ASave = decomp%1000;
33  decomp /= 1000;
34  ZSave = decomp%1000;
35  decomp /= 1000;
36  LSave = decomp%10;
37  decomp /= 10;
38 
39  if ( decomp != 10 ) {
40  LSave = 0;
41  ISave = 0;
42  ASave = 0;
43  ZSave = 0;
44  }
45 }
46 
47 //--------------------------------------------------------------------------
48 
49 // Initialise in a subclass. Only a dummy in this base class.
50 
51 bool NucleusModel::init() {
52  return true;
53 }
54 
55 //--------------------------------------------------------------------------
56 
57 // Produce a proper particle corresponding to the nucleus handled by
58 // this NucleusModel.
59 
60 Particle NucleusModel::produceIon(bool istarg) {
61  double e = max(A(), 1)*(istarg? settingsPtr->parm("Beams:eB"):
62  settingsPtr->parm("Beams:eA"));
63  double m = particleDataPtr->m0(id());
64  Particle p(id(), -12);
65  double pz = sqrt(max(e*e - m*m, 0.0));
66  int daughter = 3;
67  if ( istarg ) {
68  pz = -pz;
69  daughter = 4;
70  }
71  p.p(0.0, 0.0, pz, e);
72  p.m(m);
73  p.daughter1(daughter);
74  return p;
75 }
76 
77 //==========================================================================
78 
79 // WoodsSaxonModel is a subclass of NucleusModel and implements a
80 // general Wood-Saxon distributed nucleus.
81 
82 //--------------------------------------------------------------------------
83 
84 // Place a nucleon inside a nucleus.
85 
87 
88  while ( true ) {
89  double r = R();
90  double sel = rndPtr->flat()*(intlo + inthi0 + inthi1 + inthi2);
91  if ( sel > intlo ) r -= a()*log(rndPtr->flat());
92  if ( sel > intlo + inthi0 ) r -= a()*log(rndPtr->flat());
93  if ( sel > intlo + inthi0 + inthi1 ) r -= a()*log(rndPtr->flat());
94  if ( sel <= intlo ) {
95  r = R()*pow(rndPtr->flat(), 1.0/3.0);
96  if ( rndPtr->flat()*(1.0 + exp((r - R())/a())) > 1.0 ) continue;
97  } else
98  if ( rndPtr->flat()*(1.0 + exp((r - R())/a())) > exp((r - R())/a()) )
99  continue;
100 
101  double costhe = 2.0*rndPtr->flat() - 1.0;
102  double sinthe = sqrt(max(1.0 - costhe*costhe, 0.0));
103  double phi = 2.0*M_PI*rndPtr->flat();
104 
105  return Vec4(r*sinthe*cos(phi), r*sinthe*sin(phi), r*costhe);
106 
107  }
108 
109  return Vec4();
110 
111 }
112 
113 //==========================================================================
114 
115 // GLISSANDOModel is a subclass of NucleusModel and implements a
116 // general Wood-Saxon distributed nucleus with hard cores and specialy
117 // fitted parameters.
118 
119 //--------------------------------------------------------------------------
120 
121 // Initialize parameters.
122 
123 bool GLISSANDOModel::init() {
124  if ( A() == 0 ) return true;
125  gaussHardCore = settingsPtr->flag("HeavyIon:gaussHardCore");
126  if ( settingsPtr->isFlag("HI:hardCore") ) {
127  if ( settingsPtr->flag("HI:hardCore") ) {
128  RhSave = 0.9*femtometer;
129  RSave = (1.1*pow(double(A()),1.0/3.0) -
130  0.656*pow(double(A()),-1.0/3.0))*femtometer;
131  aSave = 0.459*femtometer;
132  } else {
133  RSave = (1.12*pow(double(A()),1.0/3.0) -
134  0.86*pow(double(A()),-1.0/3.0))*femtometer;
135  aSave = 0.54*femtometer;
136  }
137  return WoodsSaxonModel::init();
138  }
139  if ( settingsPtr->flag("HeavyIon:WSHardCore") ) {
140  RhSave = settingsPtr->parm("HeavyIon:WSRh");
141  RSave = (1.1*pow(double(A()),1.0/3.0) -
142  0.656*pow(double(A()),-1.0/3.0))*femtometer;
143  aSave = 0.459*femtometer;
144  } else {
145  RSave = (1.12*pow(double(A()),1.0/3.0) -
146  0.86*pow(double(A()),-1.0/3.0))*femtometer;
147  aSave = 0.54*femtometer;
148  }
149  if ( settingsPtr->parm("HeavyIon:WSR") > 0.0 )
150  RSave = settingsPtr->parm("HeavyIon:WSR");
151  if ( settingsPtr->parm("HeavyIon:WSa") > 0.0 )
152  aSave = settingsPtr->parm("HeavyIon:WSa");
153 
154  return WoodsSaxonModel::init();
155 
156 }
157 
158 //--------------------------------------------------------------------------
159 
160 // Place a nucleon inside a nucleus.
161 
162 vector<Nucleon> GLISSANDOModel::generate() const {
163  int sign = id() > 0? 1: -1;
164  int pid = sign*2212;
165  int nid = sign*2112;
166  vector<Nucleon> nucleons;
167  if ( A() == 0 ) {
168  nucleons.push_back(Nucleon(id(), 0, Vec4()));
169  return nucleons;
170  }
171  if ( A() == 1 ) {
172  if ( Z() == 1 ) nucleons.push_back(Nucleon(pid, 0, Vec4()));
173  else nucleons.push_back(Nucleon(nid, 0, Vec4()));
174  return nucleons;
175  }
176 
177  Vec4 cms;
178  vector<Vec4> positions;
179  while ( int(positions.size()) < A() ) {
180  while ( true ) {
181  Vec4 pos = generateNucleon();
182  bool overlap = false;
183  for ( int i = 0, N = positions.size(); i < N && !overlap; ++i )
184  if ( (positions[i] - pos).pAbs() < (gaussHardCore ? RhGauss() : Rh()) )
185  overlap = true;
186  if ( overlap ) continue;
187  positions.push_back(pos);
188  cms += pos;
189  break;
190  }
191  }
192 
193  cms /= A();
194  nucleons.resize(A());
195  int Np = Z();
196  int Nn = A() - Z();
197  for ( int i = 0, N= positions.size(); i < N; ++i ) {
198  Vec4 pos(positions[i].px() - cms.px(),
199  positions[i].py() - cms.py());
200  if ( int(rndPtr->flat()*(Np + Nn)) >= Np ) {
201  --Nn;
202  nucleons[i] = Nucleon(nid, i, pos);
203  } else {
204  --Np;
205  nucleons[i] = Nucleon(pid, i, pos);
206  }
207  }
208 
209  return nucleons;
210 
211 }
212 
213 //==========================================================================
214 
215 // ImpactParameterGenerator samples the impact parameter space.
216 
217 //--------------------------------------------------------------------------
218 
219 // Initialise base class, passing pointers to important objects.
220 
221 void ImpactParameterGenerator::initPtr(SubCollisionModel & collIn,
222  NucleusModel & projIn,
223  NucleusModel & targIn,
224  Settings & settingsIn,
225  Rndm & rndIn) {
226  collPtr = &collIn;
227  projPtr = &projIn;
228  targPtr = &targIn;
229  settingsPtr = &settingsIn;
230  rndPtr = &rndIn;
231 
232 }
233 
234 //--------------------------------------------------------------------------
235 
236 // Initialise base class, bay be overridden by subclasses.
237 
239  if ( settingsPtr->isParm("HI:bWidth") )
240  widthSave = settingsPtr->parm("HI:bWidth")*femtometer;
241  else
242  widthSave = settingsPtr->parm("HeavyIon:bWidth")*femtometer;
243 
244  if ( widthSave <= 0.0 ) {
245  double Rp = sqrt(collPtr->sigTot()/M_PI)/2.0;
246  double RA = max(Rp, projPtr->R());
247  double RB = max(Rp, targPtr->R());
248  widthSave = RA + RB + 2.0*Rp;
249  cout << " HeavyIon Info: Initializing impact parameter generator "
250  << "with width " << widthSave/femtometer << " fm." << endl;
251  }
252 
253  return true;
254 }
255 
256 //--------------------------------------------------------------------------
257 
258 // Generate an impact parameter according to a gaussian distribution.
259 
260 Vec4 ImpactParameterGenerator::generate(double & weight) const {
261  double b = sqrt(-2.0*log(rndPtr->flat()))*width();
262  double phi = 2.0*M_PI*rndPtr->flat();
263  weight = 2.0*M_PI*width()*width()*exp(0.5*b*b/(width()*width()));
264  return Vec4(b*sin(phi), b*cos(phi), 0.0, 0.0);
265 }
266 
267 //==========================================================================
268 
269 // The SubCollisionModel base class for modeling the collision between
270 // two nucleons to tell which type of collision has occurred. The
271 // model may manipulate the corresponing state of the nucleons.
272 
273 //--------------------------------------------------------------------------
274 
275 // Initialize the base class. Subclasses should consider calling this
276 // in overriding functions.
277 
279  sigTarg[0] = sigTotPtr->sigmaTot()*millibarn;
280  sigTarg[1] = sigTotPtr->sigmaND()*millibarn;
281  sigTarg[2] = sigTotPtr->sigmaXX()*millibarn;
282  sigTarg[3] = sigTotPtr->sigmaAX()*millibarn + sigTarg[1] + sigTarg[2];
283  sigTarg[4] = sigTotPtr->sigmaXB()*millibarn + sigTarg[1] + sigTarg[2];
284  sigTarg[5] = sigTotPtr->sigmaAXB()*millibarn;
285  sigTarg[6] = sigTotPtr->sigmaEl()*millibarn;
286  sigTarg[7] = sigTotPtr->bSlopeEl();
287  NInt = settingsPtr->mode("HeavyIon:SigFitNInt");
288  NGen = settingsPtr->mode("HeavyIon:SigFitNGen");
289  NPop = settingsPtr->mode("HeavyIon:SigFitNPop");
290  sigErr = settingsPtr->pvec("HeavyIon:SigFitErr");
291  sigFuzz = settingsPtr->parm("HeavyIon:SigFitFuzz");
292  fitPrint = settingsPtr->flag("HeavyIon:SigFitPrint");
293  // preliminarily set average non-diffractive impact parameter as if
294  // black disk.
295  avNDb = 2.0*sqrt(sigTarg[1]/M_PI)*
296  settingsPtr->parm("Angantyr:impactFudge")/3.0;
297  return evolve();
298 }
299 
300 //--------------------------------------------------------------------------
301 
302 // Calculate the Chi^2 for the cross section that model in a subclass
303 // tries to mdoel.
304 
305 double SubCollisionModel::Chi2(const SigEst & se, int npar) const {
306 
307  double chi2 = 0.0;
308  int nval = 0;
309  for ( int i = 0, Nval = se.sig.size(); i < Nval; ++i ) {
310  if ( sigErr[i] == 0.0 ) continue;
311  ++nval;
312  chi2 += pow2(se.sig[i] - sigTarg[i])/
313  (se.dsig2[i] + pow2(sigTarg[i]*sigErr[i]));
314  }
315  return chi2/double(max(nval - npar, 1));
316 }
317 
318 
319 //--------------------------------------------------------------------------
320 
321 // Anonymous helper function to print out stuff.
322 
323 namespace {
324 
325 void printTarget(string name, double sig, double sigerr,
326  string unit = "mb ") {
327  cout << fixed << setprecision(2);
328  cout << " |" << setw(25) << name << ": " << setw(8) << sig << " " << unit;
329  if ( sigerr > 0.0 )
330  cout <<" (+- " << setw(2) << int(100.0*sigerr)
331  << "%) | \n";
332  else
333  cout << " not used | \n";
334 }
335 
336 void printFit(string name, double fit, double sig, double sigerr,
337  string unit = "mb ") {
338  cout << " |" << setw(25) << name << ": "
339  << setw(8) << fit
340  << (sigerr > 0.0? " *(": " (")
341  << setw(6) << sig
342  << ") " << unit << " | " << endl;
343 }
344 
345 }
346 //--------------------------------------------------------------------------
347 
348 // A simple genetic algorithm for fitting the parameters in a subclass
349 // to reproduce desired cross sections.
350 
352  typedef vector<double> Parms;
353  Parms minp = minParm();
354  Parms maxp = maxParm();
355  int dim = minp.size();
356  if ( dim == 0 ) return true;
357 
358  if ( fitPrint ) {
359  cout << " *------ HeavyIon fitting of SubCollisionModel to "
360  << "cross sections ------* " << endl;
361  printTarget("Total", sigTarg[0]/millibarn, sigErr[0]);
362  printTarget("non-diffractive", sigTarg[1]/millibarn, sigErr[1]);
363  printTarget("XX diffractive", sigTarg[2]/millibarn, sigErr[2]);
364  printTarget("wounded target (B)", sigTarg[3]/millibarn, sigErr[3]);
365  printTarget("wounded projectile (A)", sigTarg[4]/millibarn, sigErr[4]);
366  printTarget("AXB diffractive", sigTarg[5]/millibarn, sigErr[5]);
367  printTarget("elastic", sigTarg[6]/millibarn, sigErr[6]);
368  printTarget("elastic b-slope", sigTarg[7], sigErr[7], "GeV^-2");
369  }
370  // We're going to use a home-made genetic algorithm. We start by
371  // creating a population of random parameter points.
372  vector<Parms> pop(NPop, Parms(dim));
373  vector<double> def = settingsPtr->pvec("HeavyIon:SigFitDefPar");
374  if ( settingsPtr->isPVec("HI:SigFitDefPar") )
375  def = settingsPtr->pvec("HI:SigFitDefPar");
376  for ( int j = 0; j < dim; ++j )
377  pop[0][j] = max(minp[j], min(def[j], maxp[j]));
378  for ( int i = 1; i < NPop; ++i )
379  for ( int j = 0; j < dim; ++j )
380  pop[i][j] = minp[j] + rndPtr->flat()*(maxp[j] - minp[j]);
381 
382  // Now we evolve our population for a number of generations.
383  for ( int igen = 0; igen < NGen; ++igen ) {
384  // Calculate Chi2 for each parameter set and order them.
385  multimap<double, Parms> chi2map;
386  double chi2max = 0.0;
387  double chi2sum = 0.0;
388  for ( int i = 0; i < NPop; ++i ) {
389  setParm(pop[i]);
390  double chi2 = Chi2(getSig(), dim);
391  chi2map.insert(make_pair(chi2, pop[i]));
392  chi2max = max(chi2max, chi2);
393  chi2sum += chi2;
394  }
395 
396  // Keep the best one, and move the other closer to a better one or
397  // kill them if they are too bad.
398  multimap<double, Parms>::iterator it = chi2map.begin();
399  pop[0] = it->second;
400  if ( fitPrint ) {
401  if ( igen == 0 )
402  cout << " | "
403  << " | \n"
404  << " | Using a genetic algorithm "
405  << " | \n"
406  << " | Generation best Chi2/Ndf "
407  << " | \n";
408  cout << " |" << setw(25) << igen << ":" << fixed << setprecision(2)
409  << setw(9) << it->first
410  << " | " << endl;
411  }
412 
413  for ( int i = 1; i < NPop; ++i ) {
414  pop[i] = (++it)->second;
415  if ( it->first > rndPtr->flat()*chi2max ) {
416  // Kill this individual and create a new one.
417  for ( int j = 0; j < dim; ++j )
418  pop[i][j] = minp[j] + rndPtr->flat()*(maxp[j] - minp[j]);
419  } else {
420  // Pick one of the better parameter sets and move this closer.
421  int ii = int(rndPtr->flat()*i);
422  for ( int j = 0; j < dim; ++j ) {
423  double d = pop[ii][j] - it->second[j];
424  double pl = max(minp[j], min(it->second[j] - sigFuzz*d, maxp[j]));
425  double pu = max(minp[j], min(it->second[j] +
426  (1.0 + sigFuzz)*d, maxp[j]));
427  pop[i][j] = pl + rndPtr->flat()*(pu - pl);
428  }
429  }
430  }
431  }
432  setParm(pop[0]);
433  SigEst se = getSig();
434  double chi2 = Chi2(se, dim);
435  avNDb = se.avNDb*settingsPtr->parm("Angantyr:impactFudge");
436  if ( chi2 > 2.0 )
437  infoPtr->errorMsg("HeavyIon Warning: Chi^2 in fitting sub-collision "
438  "model to cross sections was high.");
439  if ( fitPrint ) {
440  cout << fixed << setprecision(2);
441  cout << " | "
442  << " | "
443  << endl;
444  cout << " | Resulting cross sections (target value) "
445  << " | "
446  << endl;
447  printFit("Total", se.sig[0]/millibarn,
448  sigTarg[0]/millibarn, sigErr[0]);
449  printFit("non-diffractive", se.sig[1]/millibarn,
450  sigTarg[1]/millibarn, sigErr[1]);
451  printFit("XX diffractive", se.sig[2]/millibarn,
452  sigTarg[2]/millibarn, sigErr[2]);
453  printFit("wounded target (B)", se.sig[3]/millibarn,
454  sigTarg[3]/millibarn, sigErr[3]);
455  printFit("wounded projectile (A)", se.sig[4]/millibarn,
456  sigTarg[4]/millibarn, sigErr[4]);
457  printFit("AXB diffractive", se.sig[5]/millibarn,
458  sigTarg[5]/millibarn, sigErr[5]);
459  printFit("elastic", se.sig[6]/millibarn,
460  sigTarg[6]/millibarn, sigErr[6]);
461  printFit("elastic b-slope", se.sig[7], sigTarg[7], sigErr[7], "GeV^-2");
462  cout << " | Chi2/Ndf: "
463  << setw(8) << chi2
464  << " | " << endl;
465  cout << " | "
466  << " | "
467  << endl;
468  cout << " | Resulting parameters: "
469  << " | "
470  << endl;
471  for ( int j = 0; j < dim; ++j )
472  cout << " |" << setw(25) << j << ":" << setw(9) << pop[0][j]
473  << " | " << endl;
474  cout << " | "
475  << " | "
476  << endl;
477  cout << " | Resulting non-diffractive average impact parameter: "
478  << " | "
479  << endl;
480  cout << " | <b>:" << setw(9) << se.avNDb << " +- "
481  << setw(4) << sqrt(se.davNDb2) << " fm | "
482  << endl;
483 
484  cout << " | "
485  << " | "
486  << endl;
487  cout << " *--- End HeavyIon fitting of parameters in "
488  << "nucleon collision model ---* "
489  << endl << endl;
490  if ( NGen > 0 ) {
491  cout << "HeavyIon Info: To avoid refitting, use the following settings "
492  << "for next run:\n HeavyIon:SigFitNGen = 0\n "
493  << "HeavyIon:SigFitDefPar = "
494  << pop[0][0];
495  for ( int j = 1; j < dim; ++j ) cout << "," << pop[0][j];
496  for ( int j = dim; j < 8; ++j ) cout << ",0.0";
497  cout << endl;
498  }
499  }
500 
501  return true;
502 
503 }
504 
505 //--------------------------------------------------------------------------
506 
507 // For a given impact parameter and vectors of nucleons in the
508 // colliding nuclei, return a list of possible nucleon-nucleon
509 // SubCollisions ordered in nucleon-nucleon impact parameter
510 // distance. Should be called in overriding function in subclasses to
511 // reset all Nucleon objects.
512 
513 multiset<SubCollision> SubCollisionModel::
514 getCollisions(vector<Nucleon> & proj, vector<Nucleon> & targ,
515  const Vec4 & bvec, double & T) {
516  multiset<SubCollision> ret;
517  T = 0.0;
518  // Reset all states.
519  for ( int i = 0, N = proj.size(); i < N; ++i ) {
520  proj[i].reset();
521  proj[i].bShift(bvec/2.0);
522  }
523  for ( int i = 0, N = targ.size(); i < N; ++i ) {
524  targ[i].reset();
525  targ[i].bShift(-bvec/2.0);
526  }
527 
528  // Empty return.
529  return ret;
530 }
531 
532 
533 //==========================================================================
534 
535 // The BlackSubCollisionModel uses fixed size, black-disk
536 // nucleon-nucleon cross section, equal to the total inelastic pp cross
537 // section. Everything else is elastic -- Diffraction not included.
538 
539 //--------------------------------------------------------------------------
540 
541 multiset<SubCollision> BlackSubCollisionModel::
542 getCollisions(vector<Nucleon> & proj, vector<Nucleon> & targ,
543  const Vec4 & bvec, double & T) {
544  // Always call base class to reset nucleons and shift them into
545  // position.
546  multiset<SubCollision> ret =
547  SubCollisionModel::getCollisions(proj, targ, bvec, T);
548 
549  T = 0.0;
550  // Go through all pairs of nucleons
551  for ( int ip = 0, Np = proj.size(); ip < Np; ++ip )
552  for ( int it = 0, Nt = targ.size(); it < Nt; ++it ) {
553  Nucleon & p = proj[ip];
554  Nucleon & t = targ[it];
555  double b = (p.bPos() - t.bPos()).pT();
556  if ( b > sqrt(sigTot()/M_PI) ) continue;
557  T = 0.5; // The naive cross section only gets the total xsec correct.
558  if ( b < sqrt((sigTot() - sigEl())/M_PI) ) {
559  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::ABS));
560  }
561  else {
562  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::ELASTIC));
563  }
564  }
565 
566  return ret;
567 }
568 
569 //==========================================================================
570 
571 // The NaiveSubCollisionModel uses a fixed size, black-disk-like
572 // nucleon-nucleon cross section where. Central collisions will always
573 // be absorptive, less central will be doubly diffractive, more
574 // peripheral will be single diffractive and the most peripheral will
575 // be elastic.
576 
577 //--------------------------------------------------------------------------
578 
579 multiset<SubCollision> NaiveSubCollisionModel::
580 getCollisions(vector<Nucleon> & proj, vector<Nucleon> & targ,
581  const Vec4 & bvec, double & T) {
582  // Always call base class to reset nucleons and shift them into
583  // position.
584  multiset<SubCollision> ret =
585  SubCollisionModel::getCollisions(proj, targ, bvec, T);
586 
587  T = 0.0;
588  // Go through all pairs of nucleons
589  for ( int ip = 0, Np = proj.size(); ip < Np; ++ip )
590  for ( int it = 0, Nt = targ.size(); it < Nt; ++it ) {
591  Nucleon & p = proj[ip];
592  Nucleon & t = targ[it];
593  double b = (p.bPos() - t.bPos()).pT();
594  if ( b > sqrt(sigTot()/M_PI) ) continue;
595  T = 0.5; // The naive cross section only gets the total xsec correct.
596  if ( b < sqrt(sigND()/M_PI) ) {
597  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::ABS));
598  }
599  else if ( b < sqrt((sigND() + sigDDE())/M_PI) ) {
600  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::DDE));
601  }
602  else if ( b < sqrt((sigND() + sigSDE() + sigDDE())/M_PI) ) {
603  if ( sigSDEP() > rndPtr->flat()*sigSDE() ) {
604  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::SDEP));
605  } else {
606  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::SDET));
607  }
608  }
609  else if ( b < sqrt((sigND() + sigSDE() + sigDDE() + sigCDE())/M_PI) ) {
610  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::CDE));
611  }
612  else {
613  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::ELASTIC));
614  }
615  }
616 
617  return ret;
618 }
619 
620 //==========================================================================
621 
622 // DoubleStrikman uses a fluctuating and semi-transparent disk for
623 // each Nucleon in a sub-collision resulting in a fluctuating
624 // interaction probability. To assess the fluctuation each Nucleon has
625 // two random states in each collision, one main state and one helper
626 // state to assess the frlutuations.
627 
628 //--------------------------------------------------------------------------
629 
630 // Anonymous helper functions to simplify calculating elastic
631 // amplitudes.
632 
633 namespace {
634 inline double el(double s1, double s2, double u1, double u2) {
635  return s1/u1 > s2/u2? s2*u1: s1*u2;
636 }
637 
638 }
639 
640 //--------------------------------------------------------------------------
641 
642 // Numerically estimate the cross sections corresponding to the
643 // current parameter setting.
644 
645 SubCollisionModel::SigEst DoubleStrikman::getSig() const {
646 
647  SigEst s;
648  for ( int n = 0; n < NInt; ++n ) {
649  double rp1 = gamma();
650  double rp2 = gamma();
651  double rt1 = gamma();
652  double rt2 = gamma();
653  double s11 = pow2(rp1 + rt1)*M_PI;
654  double s12 = pow2(rp1 + rt2)*M_PI;
655  double s21 = pow2(rp2 + rt1)*M_PI;
656  double s22 = pow2(rp2 + rt2)*M_PI;
657 
658  double stot = (s11 + s12 + s21 + s22)/4.0;
659  s.sig[0] += stot;
660  s.dsig2[0] += pow2(stot);
661 
662  double u11 = opacity(s11)/2.0;
663  double u12 = opacity(s12)/2.0;
664  double u21 = opacity(s21)/2.0;
665  double u22 = opacity(s22)/2.0;
666 
667  double avb = sqrt(2.0/M_PI)*(s11*sqrt(s11/(2.0*u11))*(1.0 - u11) +
668  s12*sqrt(s12/(2.0*u12))*(1.0 - u12) +
669  s21*sqrt(s21/(2.0*u21))*(1.0 - u21) +
670  s22*sqrt(s22/(2.0*u22))*(1.0 - u22))/12.0;
671  s.avNDb += avb;
672  s.davNDb2 += pow2(avb);
673 
674  double snd = (s11 - s11*u11 + s12 - s12*u12 +
675  s21 - s21*u21 + s22 - s22*u22)/4.0;
676  s.sig[1] += snd;
677  s.dsig2[1] += pow2(snd);
678 
679  double sel = (el(s11, s22, u11, u22) + el(s12, s21, u12, u21))/2.0;
680  s.sig[6] += sel;
681  s.dsig2[6] += pow2(sel);
682 
683  double swt = stot - (el(s11, s12, u11, u12) + el(s21, s22, u21, u22))/2.0;
684  double swp = stot - (el(s11, s21, u11, u21) + el(s12, s22, u12, u22))/2.0;
685  s.sig[4] += swp;
686  s.dsig2[4] += pow2(swp);
687  s.sig[3] += swt;
688  s.dsig2[3] += pow2(swt);
689 
690  s.sig[2] += swt + swp - snd + sel - stot;
691  s.dsig2[2] += pow2(swt + swp - snd + sel - stot);
692 
693  s.sig[5] += s11;
694  s.dsig2[5] += pow2(s11);
695 
696  s.sig[7] += pow2(s11)/u11;
697  s.dsig2[7] += pow2(pow2(s11)/u11);
698 
699 
700 
701  }
702 
703  s.sig[0] /= double(NInt);
704  s.dsig2[0] = (s.dsig2[0]/double(NInt) - pow2(s.sig[0]))/double(NInt);
705 
706  s.sig[1] /= double(NInt);
707  s.dsig2[1] = (s.dsig2[1]/double(NInt) - pow2(s.sig[1]))/double(NInt);
708 
709  s.sig[2] /= double(NInt);
710  s.dsig2[2] = (s.dsig2[2]/double(NInt) - pow2(s.sig[2]))/double(NInt);
711 
712  s.sig[3] /= double(NInt);
713  s.dsig2[3] = (s.dsig2[3]/double(NInt) - pow2(s.sig[3]))/double(NInt);
714 
715  s.sig[4] /= double(NInt);
716  s.dsig2[4] = (s.dsig2[4]/double(NInt) - pow2(s.sig[4]))/double(NInt);
717 
718  s.sig[6] /= double(NInt);
719  s.dsig2[6] = (s.dsig2[6]/double(NInt) - pow2(s.sig[6]))/double(NInt);
720 
721  s.sig[5] /= double(NInt);
722  s.dsig2[5] /= double(NInt);
723 
724  s.sig[7] /= double(NInt);
725  s.dsig2[7] /= double(NInt);
726  double bS = (s.sig[7]/s.sig[5])/(16.0*M_PI*pow2(0.19732697));
727  double b2S = pow2(bS)*(s.dsig2[7]/pow2(s.sig[7]) - 1.0 +
728  s.dsig2[5]/pow2(s.sig[5]) - 1.0)/double(NInt);
729  s.sig[5] = 0.0;
730  s.dsig2[5] = 0.0;
731  s.sig[7] = bS;
732  s.dsig2[7] = b2S;
733 
734  s.avNDb /= double(NInt);
735  s.davNDb2 = (s.davNDb2/double(NInt) - pow2(s.avNDb))/double(NInt);
736  s.avNDb /= s.sig[1];
737  s.davNDb2 /= pow2(s.sig[1]);
738 
739  return s;
740 
741 }
742 
743 //--------------------------------------------------------------------------
744 
745 // Access funtions to parameters in the DoubleStrikman model.
746 
747 void DoubleStrikman::setParm(const vector<double> & p) {
748  if ( p.size() > 0 ) sigd = p[0];
749  if ( p.size() > 1 ) k0 = p[1];
750  if ( p.size() > 2 ) alpha = p[2];
751  r0 = sqrt(sigTot()/(M_PI*(2.0*k0 + 4.0*k0*k0)));
752 }
753 
754 vector<double> DoubleStrikman::getParm() const {
755  vector<double> ret(3);
756  ret[0] = sigd;
757  ret[1] = k0;
758  ret[2] = alpha;
759  return ret;
760 }
761 
762 vector<double> DoubleStrikman::minParm() const {
763  vector<double> ret(3);
764  ret[0] = 1.0;
765  ret[1] = 0.01;
766  ret[2] = 0.0;
767  return ret;
768 }
769 
770 vector<double> DoubleStrikman::maxParm() const {
771  vector<double> ret(3);
772  ret[0] = 20.0;
773  ret[1] = 20.0;
774  ret[2] = 2.0;
775  return ret;
776 }
777 
778 //--------------------------------------------------------------------------
779 
780 // Generate the radii in DoubleStrikman according to a gamma
781 // distribution.
782 
783 double DoubleStrikman::gamma() const {
784  static const double e = exp(1);
785  int k = int(k0);
786  double del = k0 - k;
787  double x = 0.0;
788  for ( int i = 0; i < k; ++i ) x += -log(rndPtr->flat());
789 
790  if ( del == 0.0 ) return x*r0;
791 
792  while ( true ) {
793  double U = rndPtr->flat();
794  double V = rndPtr->flat();
795  double W = rndPtr->flat();
796 
797  double xi = 0.0;
798  if ( U <= e/(e+del) ) {
799  xi = pow(V, 1.0/del);
800  if ( W <= exp(-xi) ) return r0*(x + xi);
801  } else {
802  xi = 1.0 - log(V);
803  if ( W <= pow(xi, del - 1.0) ) return r0*(x + xi);
804  }
805  }
806  return 0.0;
807 }
808 
809 //--------------------------------------------------------------------------
810 
811 // Helper functions to get the correct average elastic and wounded
812 // cross sections.
813 
814 void DoubleStrikman::shuffle(double PND1, double PND2,
815  double & PW1, double & PW2) {
816  if ( PND1 > PW1 ) {
817  PW2 += PW1 - PND1;
818  PW1 = PND1;
819  return;
820  }
821  if ( PND2 > PW2 ) {
822  PW1 += PW2 - PND2;
823  PW2 = PND2;
824  return;
825  }
826 }
827 
828 void DoubleStrikman::shuffel(double & PEL11, double P11,
829  double P12, double P21, double P22) {
830  double PEL12 = PEL11, PEL21 = PEL11, PEL22 = PEL11;
831  map<double, double *> ord;
832  ord[P11] = &PEL11;
833  ord[P12] = &PEL12;
834  ord[P21] = &PEL21;
835  ord[P22] = &PEL22;
836  map<double, double *>::iterator next = ord.begin();
837  map<double, double *>::iterator prev = next++;
838  while ( next != ord.end() ) {
839  if ( *prev->second > prev->first ) {
840  *next->second += *prev->second - prev->first;
841  *prev->second = prev->first;
842  }
843  prev = next++;
844  }
845 }
846 
847 //--------------------------------------------------------------------------
848 
849 // Main function returning the possible sub-collisions.
850 
851 multiset<SubCollision> DoubleStrikman::
852 getCollisions(vector<Nucleon> & proj, vector<Nucleon> & targ,
853  const Vec4 & bvec, double & T) {
854  // Always call base class to reset nucleons and shift them into
855  // position.
856  multiset<SubCollision> ret =
857  SubCollisionModel::getCollisions(proj, targ, bvec, T);
858 
860  for ( int ip = 0, Np = proj.size(); ip < Np; ++ip ) {
861  proj[ip].state(Nucleon::State(1, gamma()));
862  proj[ip].addAltState(Nucleon::State(1, gamma()));
863  }
864  for ( int it = 0, Nt = targ.size(); it < Nt; ++it ) {
865  targ[it].state(Nucleon::State(1, gamma()));
866  targ[it].addAltState(Nucleon::State(1, gamma()));
867  }
868 
869  // The factorising S-matrix.
870  double S = 1.0;
871 
872  // Go through all pairs of nucleons
873  for ( int ip = 0, Np = proj.size(); ip < Np; ++ip )
874  for ( int it = 0, Nt = targ.size(); it < Nt; ++it ) {
875  Nucleon & p = proj[ip];
876  Nucleon & t = targ[it];
877  double b = (p.bPos() - t.bPos()).pT();
878 
879  double T11 = Tpt(p.state(), t.state(), b);
880  double T12 = Tpt(p.state(), t.altState(), b);
881  double T21 = Tpt(p.altState(), t.state(), b);
882  double T22 = Tpt(p.altState(), t.altState(), b);
883  double S11 = 1.0 - T11;
884  double S12 = 1.0 - T12;
885  double S21 = 1.0 - T21;
886  double S22 = 1.0 - T22;
887  S *= S11;
888  double PND11 = 1.0 - pow2(S11);
889  // First and most important, check if this is an absorptive
890  // scattering.
891  if ( PND11 > rndPtr->flat() ) {
892  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::ABS));
893  continue;
894  }
895 
896  // Now set up calculation for probability of diffractively
897  // wounded nucleons.
898  double PND12 = 1.0 - pow2(S12);
899  double PND21 = 1.0 - pow2(S21);
900  double PWp11 = 1.0 - S11*S21;
901  double PWp21 = 1.0 - S11*S21;
902  shuffle(PND11, PND21, PWp11, PWp21);
903  double PWt11 = 1.0 - S11*S12;
904  double PWt12 = 1.0 - S11*S12;
905  shuffle(PND11, PND12, PWt11, PWt12);
906 
907  bool wt = ( PWt11 - PND11 > (1.0 - PND11)*rndPtr->flat() );
908  bool wp = ( PWp11 - PND11 > (1.0 - PND11)*rndPtr->flat() );
909  if ( wt && wp ) {
910  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::DDE));
911  continue;
912  }
913  if ( wt ) {
914  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::SDET));
915  continue;
916  }
917  if ( wp ) {
918  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::SDEP));
919  continue;
920  }
921 
922  // Finally set up calculation for elastic scattering. This can
923  // never be exact, but let's do as well as we can.
924 
925  double PND22 = 1.0 - pow2(S22);
926  double PWp12 = 1.0 - S12*S22;
927  double PWp22 = 1.0 - S12*S22;
928  shuffle(PND12, PND22, PWp12, PWp22);
929  double PWt21 = 1.0 - S21*S22;
930  double PWt22 = 1.0 - S21*S22;
931  shuffle(PND21, PND22, PWt21, PWt22);
932 
933  double PNW11 = PNW(PWp11, PWt11, PND11);
934  double PNW12 = PNW(PWp12, PWt12, PND12);
935  double PNW21 = PNW(PWp21, PWt21, PND21);
936  double PNW22 = PNW(PWp22, PWt22, PND22);
937 
938  double PEL = (T12*T21 + T11*T22)/2.0;
939  shuffel(PEL, PNW11, PNW12, PNW21, PNW22);
940  if ( PEL > PNW11*rndPtr->flat() ) {
941  if ( sigCDE() > rndPtr->flat()*(sigCDE() + sigEl()) )
942  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::CDE));
943  else
944  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::ELASTIC));
945  }
946  }
947 
948 
949  T = 1.0 - S;
950 
951  return ret;
952 }
953 
954 //==========================================================================
955 
956 // MultiRadial uses a number of different disk sizes with different
957 // opacities. Like a discrete version of DoubleStrikman.
958 
959 //--------------------------------------------------------------------------
960 
961 // Numerically estimate the cross sections corresponding to the
962 // current parameter setting.
963 
964 SubCollisionModel::SigEst MultiRadial::getSig() const {
965 
966  SigEst s;
967 
968  double sTpt = 0.0;
969  double sT2pt = 0.0;
970  // double sTpt2 = 0.0;
971  double sTp2t = 0.0;
972  // double sTt2p = 0.0;
973  double Rp = 0.0;
974  for ( int ip = 0; ip < Nr; ++ip ) {
975  Rp += dR[ip];
976  double Rt = 0.0;
977  for ( int it = 0; it < Nr; ++it ) {
978  Rt += dR[it];
979  sTpt += c[ip]*T0[ip]*c[it]*T0[it]*pow2(Rp + Rt)*sigTot();
980  sT2pt += c[ip]*pow2(T0[ip])*c[it]*pow2(T0[it])*pow2(Rp + Rt)*sigTot();
981  double rp = 0.0;
982  for ( int jp = 0; jp < Nr; ++jp ) {
983  rp += dR[jp];
984  double rt = 0.0;
985  for ( int jt = 0; jt < Nr; ++jt ) {
986  rt += dR[jt];
987  double fac = T0[ip]*T0[jp]*T0[it]*T0[jt]*pow2(min(Rp + Rt, rp + rt))
988  * sigTot();
989  if ( ip == jp ) sTp2t += c[ip]*c[it]*c[jt]*fac;
990  }
991  }
992  }
993 
994  }
995 
996  s.sig[0] /= double(NInt);
997  s.dsig2[0] = (s.dsig2[0]/double(NInt) - pow2(s.sig[0]))/double(NInt);
998 
999  s.sig[1] /= double(NInt);
1000  s.dsig2[1] = (s.dsig2[1]/double(NInt) - pow2(s.sig[1]))/double(NInt);
1001 
1002  s.sig[2] /= double(NInt);
1003  s.dsig2[2] = (s.dsig2[2]/double(NInt) - pow2(s.sig[2]))/double(NInt);
1004 
1005  s.sig[3] /= double(NInt);
1006  s.dsig2[3] = (s.dsig2[3]/double(NInt) - pow2(s.sig[3]))/double(NInt);
1007 
1008  s.sig[4] /= double(NInt);
1009  s.dsig2[4] = (s.dsig2[4]/double(NInt) - pow2(s.sig[4]))/double(NInt);
1010 
1011  s.sig[6] /= double(NInt);
1012  s.dsig2[6] = (s.dsig2[6]/double(NInt) - pow2(s.sig[6]))/double(NInt);
1013 
1014  s.sig[5] /= double(NInt);
1015  s.dsig2[5] /= double(NInt);
1016 
1017  s.sig[7] /= double(NInt);
1018  s.dsig2[7] /= double(NInt);
1019  double bS = (s.sig[7]/s.sig[5])/(16.0*M_PI*pow2(0.19732697));
1020  double b2S = pow2(bS)*(s.dsig2[7]/pow2(s.sig[7]) - 1.0 +
1021  s.dsig2[5]/pow2(s.sig[5]) - 1.0)/double(NInt);
1022  s.sig[5] = 0.0;
1023  s.dsig2[5] = 0.0;
1024  s.sig[7] = bS;
1025  s.dsig2[7] = b2S;
1026 
1027  return s;
1028 
1029 }
1030 
1031 //--------------------------------------------------------------------------
1032 
1033 // Access funtions to parameters in the MultiRadial model.
1034 
1035 void MultiRadial::setParm(const vector<double> & p) {
1036  unsigned int ip = 0;
1037  for ( int i = 0; i < Nr; ++i ) {
1038  if ( ip < p.size() ) dR[i] = p[ip++];
1039  if ( ip < p.size() ) T0[i] = p[ip++];
1040  if ( ip < p.size() ) phi[i] = p[ip++];
1041  }
1042 }
1043 
1044 vector<double> MultiRadial::getParm() const {
1045  vector<double> ret;
1046  for ( int i = 0; i < Nr; ++i ) {
1047  ret.push_back(dR[i]);
1048  ret.push_back(T0[i]);
1049  if ( i < Nr -1 ) ret.push_back(phi[i]);
1050  }
1051  return ret;
1052 }
1053 
1054 vector<double> MultiRadial::minParm() const {
1055  return vector<double>(Nr*Nr*(Nr - 1), 0.0);
1056 }
1057 
1058 vector<double> MultiRadial::maxParm() const {
1059  return vector<double>(Nr*Nr*(Nr - 1), 1.0);
1060 }
1061 
1062 void MultiRadial::setProbs() {
1063  double rProj = 1.0;
1064  for ( int i = 0; i < Nr - 1; ++i ) {
1065  c[i] = rProj*cos(phi[i]*M_PI/2.0);
1066  rProj *= sin(phi[i]*M_PI/2.0);
1067  }
1068  c[Nr - 1] = rProj;
1069 }
1070 
1071 int MultiRadial::choose() const {
1072  double sum = 0.0;
1073  double sel = rndPtr->flat();
1074  for ( int i = 0; i < Nr - 1; ++i )
1075  if ( sel < ( sum += c[i] ) ) return i;
1076  return Nr - 1;
1077 }
1078 
1079 
1080 
1081 
1082 //--------------------------------------------------------------------------
1083 
1084 // Main function returning the possible sub-collisions.
1085 
1086 multiset<SubCollision> MultiRadial::
1087 getCollisions(vector<Nucleon> & proj, vector<Nucleon> & targ,
1088  const Vec4 & bvec, double & T) {
1089  // Always call base class to reset nucleons and shift them into
1090  // position.
1091  multiset<SubCollision> ret =
1092  SubCollisionModel::getCollisions(proj, targ, bvec, T);
1093 
1094  return ret;
1095 }
1096 
1097 //==========================================================================
1098 
1099 // HIInfo functions to collect statistics in an event and in a run.
1100 
1101 //--------------------------------------------------------------------------
1102 
1103 // Collect statistics for each SubCollision in an event.
1104 
1105 int HIInfo::addSubCollision(const SubCollision & c) {
1106  ++nCollSave[0];
1107  switch ( c.type ) {
1108  case SubCollision::ABS:
1109  return ++nCollSave[1];
1110  case SubCollision::SDEP:
1111  return ++nCollSave[2];
1112  case SubCollision::SDET:
1113  return ++nCollSave[3];
1114  case SubCollision::DDE:
1115  return ++nCollSave[4];
1116  case SubCollision::CDE:
1117  return ++nCollSave[5];
1118  case SubCollision::ELASTIC:
1119  return ++nCollSave[6];
1120  default:
1121  return 0;
1122  }
1123 }
1124 
1125 //--------------------------------------------------------------------------
1126 
1127 // Collect statistics for each participating Nucleon in an event.
1128 
1129 int HIInfo::addProjectileNucleon(const Nucleon & n) {
1130  ++nProjSave[0];
1131  switch ( n.status() ) {
1132  case Nucleon::ABS:
1133  return ++nProjSave[1];
1134  case Nucleon::DIFF:
1135  return ++nProjSave[2];
1136  case Nucleon::ELASTIC:
1137  return ++nProjSave[3];
1138  default:
1139  return 0;
1140  }
1141 }
1142 
1143 int HIInfo::addTargetNucleon(const Nucleon & n) {
1144  ++nTargSave[0];
1145  switch ( n.status() ) {
1146  case Nucleon::ABS:
1147  return ++nTargSave[1];
1148  case Nucleon::DIFF:
1149  return ++nTargSave[2];
1150  case Nucleon::ELASTIC:
1151  return ++nTargSave[3];
1152  default:
1153  return 0;
1154  }
1155 }
1156 
1157 //--------------------------------------------------------------------------
1158 
1159 // Collect statistics for attemted and accepted impact paramet point
1160 // in an event.
1161 
1162 void HIInfo::addAttempt(double T, double bin, double bweight) {
1163  bSave = bin;
1164  nCollSave = nProjSave = nTargSave = vector<int>(10, 0);
1165  nFailSave = 0;
1166  weightSave = bweight;
1167  weightSumSave += weightSave;
1168  ++NSave;
1169  double w = 2.0*T*bweight;
1170  double delta = w - sigmaTotSave;
1171  sigmaTotSave += delta/double(NSave);
1172  sigErr2TotSave += (delta*(w - sigmaTotSave) - sigErr2TotSave)/double(NSave);
1173  w = (2*T - T*T)*bweight;
1174  delta = w - sigmaNDSave;
1175  sigmaNDSave += delta/double(NSave);
1176  sigErr2NDSave += (delta*(w - sigmaNDSave) - sigErr2NDSave)/double(NSave);
1177 }
1178 
1179 
1180 void HIInfo::accept() {
1181  int pc = primInfo.code();
1182  weightSumSave += weightSave;
1183  ++NAccSave;
1184  sumPrimW[pc] += weightSave;
1185  sumPrimW2[pc] += weightSave*weightSave;
1186  ++NPrim[pc];
1187  NamePrim[pc] = primInfo.nameProc(pc);
1188 }
1189 
1190 //==========================================================================
1191 
1192 // The Nucleon class describing a Nucleon in a Nucleus.
1193 
1194 //--------------------------------------------------------------------------
1195 
1196 // Print out information about a Nuclean. To be called from inside a
1197 // debugger.
1198 
1199 void Nucleon::debug() {
1200  cout << "Nucleon id: " << id() << endl;
1201  cout << "index: " << index() << endl;
1202  cout << "b(rel): " << nPos().px() << " " << nPos().py() << endl;
1203  cout << "b(abs): " << bPos().px() << " " << bPos().py() << endl;
1204  cout << "status: " << status() << (done()? " done": " ") << endl;
1205  cout << "state: ";
1206  for ( int i = 0, N = state().size(); i < N; ++i )
1207  cout << state()[i] << " ";
1208  cout << endl;
1209  for ( int j = 0, M = altStatesSave.size(); j < M; ++j ) {
1210  cout << "state " << j+1 << ": ";
1211  for ( int i = 0, N = altStatesSave[j].size(); i < N; ++i )
1212  cout << altStatesSave[j][i] << " ";
1213  cout << endl;
1214  }
1215 }
1216 
1217 //==========================================================================
1218 
1219 } // end namespace Pythia8
The nucleon is absorptively wounded.
Definition: HIUserHooks.h:73
This is an absorptive (non-diffractive) collision.
Definition: HIUserHooks.h:202
Both excited but with central diffraction.
Definition: HIUserHooks.h:201
void debug()
Print out debugging information.
double sigd
Saturation scale of the nucleus.
Definition: HIUserHooks.h:703
double r0
The average radius of the nucleon.
Definition: HIUserHooks.h:697
Settings * settingsPtr
Pointers to useful objects.
Definition: HIUserHooks.h:289
virtual SigEst getSig() const
Calculate the cross sections for the given set of parameters.
Definition: HIUserHooks.h:543
bool done() const
Check if nucleon has been assigned.
Definition: HIUserHooks.h:106
const Vec4 & bPos() const
The absolute position in impact parameter space.
Definition: HIUserHooks.h:97
virtual bool init()
Virtual init method.
Definition: HIUserHooks.cc:238
vector< double > c
The probability distribution.
Definition: HIUserHooks.h:772
double opacity(double sig) const
The opacity of the collision at a given sigma.
Definition: HIUserHooks.h:655
int id() const
Accessor functions:
Definition: HIUserHooks.h:88
int Nr
The number of radii.
Definition: HIUserHooks.h:768
virtual bool evolve()
Use a simlified genetic algorithm to fit the parameters.
Definition: HIUserHooks.cc:351
Both projectile and target are diffractively excited.
Definition: HIUserHooks.h:200
vector< double > State
The state of a nucleon is a general vector of doubles.
Definition: HIUserHooks.h:77
SigEst getSig() const
Calculate the cross sections for the given set of parameters.
Definition: HIUserHooks.cc:927
double sigDDE() const
The double diffractive excitation cross section.
Definition: HIUserHooks.h:534
void initPtr(int idIn, Settings &settingsIn, ParticleData &particleDataIn, Rndm &rndIn)
Init method.
Definition: HIUserHooks.cc:23
int idSave
The nucleus.
Definition: HIUserHooks.h:280
vector< double > T0
The opacity for different radii.
Definition: HIUserHooks.h:778
bool init()
Initialize.
Definition: HIUserHooks.cc:123
double width() const
Get the width.
Definition: HIUserHooks.h:424
virtual multiset< SubCollision > getCollisions(vector< Nucleon > &proj, vector< Nucleon > &targ, const Vec4 &bvec, double &T)
Definition: HIUserHooks.cc:542
virtual vector< Nucleon > generate() const
Definition: HIUserHooks.cc:162
virtual void setParm(const vector< double > &)
Set the parameters of this model.
Definition: HIUserHooks.cc:710
double sigND() const
The non-diffractive (absorptive) cross section.
Definition: HIUserHooks.h:537
virtual multiset< SubCollision > getCollisions(vector< Nucleon > &proj, vector< Nucleon > &targ, const Vec4 &bvec, double &T)=0
Definition: HIUserHooks.cc:514
double Chi2(const SigEst &sigs, int npar) const
Calculate the Chi2 for the given cross section estimates.
Definition: HIUserHooks.cc:305
const Vec4 & nPos() const
The position of this nucleon relative to the nucleus center.
Definition: HIUserHooks.h:94
double sigEl() const
The total cross section.
Definition: HIUserHooks.h:519
virtual multiset< SubCollision > getCollisions(vector< Nucleon > &proj, vector< Nucleon > &targ, const Vec4 &bvec, double &T)
This is an elastic scattering.
Definition: HIUserHooks.h:197
The projectile is diffractively excited.
Definition: HIUserHooks.h:198
virtual vector< double > getParm() const
double Rh() const
Accessor functions.
Definition: HIUserHooks.h:370
double sigSDEP() const
The single diffractive excitation cross section (excited projectile).
Definition: HIUserHooks.h:528
The nucleon is elastically scattered.
Definition: HIUserHooks.h:71
int ISave
Cache information about the nucleus.
Definition: HIUserHooks.h:283
double k0
The power in the Gamma distribution.
Definition: HIUserHooks.h:700
double RSave
The estimate of the nucleus radius.
Definition: HIUserHooks.h:286
virtual vector< double > getParm() const
Definition: HIUserHooks.cc:717
virtual void setParm(const vector< double > &)
Set the parameters of this model.
Definition: HIUserHooks.h:559
virtual void setParm(const vector< double > &)
Set the parameters of this model.
Definition: HIUserHooks.cc:998
double sigSDE() const
The single diffractive excitation cross section (both sides summed).
Definition: HIUserHooks.h:525
SigEst getSig() const
Calculate the cross sections for the given set of parameters.
Definition: HIUserHooks.cc:608
SubCollisionModel * collPtr
Info from the controlling HeavyIons object.
Definition: HIUserHooks.h:434
The target is diffractively excited.
Definition: HIUserHooks.h:199
int id() const
Accessor functions.
Definition: HIUserHooks.h:270
double Tpt(const Nucleon::State &p, const Nucleon::State &t, double b) const
Definition: HIUserHooks.h:665
Vec4 generateNucleon() const
Definition: HIUserHooks.cc:86
The nucleon is diffractively wounded.
Definition: HIUserHooks.h:72
int choose() const
Choose a radius.
double a() const
Accessor functions:
Definition: HIUserHooks.h:309
Status status() const
The status.
Definition: HIUserHooks.h:103
int index() const
The nucleon type.
Definition: HIUserHooks.h:91
double gamma() const
Generate a random number according to a Gamma-distribution.
Definition: HIUserHooks.cc:746
virtual Vec4 generate(double &weight) const
Definition: HIUserHooks.cc:260
virtual multiset< SubCollision > getCollisions(vector< Nucleon > &proj, vector< Nucleon > &targ, const Vec4 &bvec, double &T)
Definition: HIUserHooks.cc:543
double sigCDE() const
The central diffractive excitation cross section.
Definition: HIUserHooks.h:522
Definition: Nucleon.h:9
double alpha
Power of the saturation scale.
Definition: HIUserHooks.h:706
virtual multiset< SubCollision > getCollisions(vector< Nucleon > &proj, vector< Nucleon > &targ, const Vec4 &bvec, double &T)
Definition: HIUserHooks.cc:815
double sigTot() const
The total cross section.
Definition: HIUserHooks.h:514
virtual bool init()
Virtual init method.
Definition: HIUserHooks.cc:278
const State & state() const
The physical state of the incoming nucleon.
Definition: HIUserHooks.h:112
vector< double > dR
The difference between radii.
Definition: HIUserHooks.h:775