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) 2018 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 
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 // The NaiveSubCollisionModel uses a fixed size, black-disk-like
535 // nucleon-nucleon cross section where. Central collisions will always
536 // be absorptive, less central will be doubly diffractive, more
537 // peripheral will be single diffractive and the most peripheral will
538 // be elastic.
539 
540 //--------------------------------------------------------------------------
541 
542 multiset<SubCollision> NaiveSubCollisionModel::
543 getCollisions(vector<Nucleon> & proj, vector<Nucleon> & targ,
544  const Vec4 & bvec, double & T) {
545  // Always call base class to reset nucleons and shift them into
546  // position.
547  multiset<SubCollision> ret =
548  SubCollisionModel::getCollisions(proj, targ, bvec, T);
549 
550  T = 0.0;
551  // Go through all pairs of nucleons
552  for ( int ip = 0, Np = proj.size(); ip < Np; ++ip )
553  for ( int it = 0, Nt = targ.size(); it < Nt; ++it ) {
554  Nucleon & p = proj[ip];
555  Nucleon & t = targ[it];
556  double b = (p.bPos() - t.bPos()).pT();
557  if ( b > sqrt(sigTot()/M_PI) ) continue;
558  T = 0.5; // The naive cross section only gets the total xsec correct.
559  if ( b < sqrt(sigND()/M_PI) ) {
560  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::ABS));
561  }
562  else if ( b < sqrt((sigND() + sigDDE())/M_PI) ) {
563  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::DDE));
564  }
565  else if ( b < sqrt((sigND() + sigSDE() + sigDDE())/M_PI) ) {
566  if ( sigSDEP() > rndPtr->flat()*sigSDE() ) {
567  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::SDEP));
568  } else {
569  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::SDET));
570  }
571  }
572  else if ( b < sqrt((sigND() + sigSDE() + sigDDE() + sigCDE())/M_PI) ) {
573  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::CDE));
574  }
575  else {
576  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::ELASTIC));
577  }
578  }
579 
580  return ret;
581 }
582 
583 //==========================================================================
584 
585 // DoubleStrikman uses a fluctuating and semi-transparent disk for
586 // each Nucleon in a sub-collision resulting in a fluctuating
587 // interaction probability. To assess the fluctuation each Nucleon has
588 // two random states in each collision, one main state and one helper
589 // state to assess the frlutuations.
590 
591 //--------------------------------------------------------------------------
592 
593 // Anonymous helper functions to simplify calculating elastic
594 // amplitudes.
595 
596 namespace {
597 inline double el(double s1, double s2, double u1, double u2) {
598  return s1/u1 > s2/u2? s2*u1: s1*u2;
599 }
600 
601 }
602 
603 //--------------------------------------------------------------------------
604 
605 // Numerically estimate the cross sections corresponding to the
606 // current parameter setting.
607 
609 
610  SigEst s;
611  for ( int n = 0; n < NInt; ++n ) {
612  double rp1 = gamma();
613  double rp2 = gamma();
614  double rt1 = gamma();
615  double rt2 = gamma();
616  double s11 = pow2(rp1 + rt1)*M_PI;
617  double s12 = pow2(rp1 + rt2)*M_PI;
618  double s21 = pow2(rp2 + rt1)*M_PI;
619  double s22 = pow2(rp2 + rt2)*M_PI;
620 
621  double stot = (s11 + s12 + s21 + s22)/4.0;
622  s.sig[0] += stot;
623  s.dsig2[0] += pow2(stot);
624 
625  double u11 = opacity(s11)/2.0;
626  double u12 = opacity(s12)/2.0;
627  double u21 = opacity(s21)/2.0;
628  double u22 = opacity(s22)/2.0;
629 
630  double avb = sqrt(2.0/M_PI)*(s11*sqrt(s11/(2.0*u11))*(1.0 - u11) +
631  s12*sqrt(s12/(2.0*u12))*(1.0 - u12) +
632  s21*sqrt(s21/(2.0*u21))*(1.0 - u21) +
633  s22*sqrt(s22/(2.0*u22))*(1.0 - u22))/12.0;
634  s.avNDb += avb;
635  s.davNDb2 += pow2(avb);
636 
637  double snd = (s11 - s11*u11 + s12 - s12*u12 +
638  s21 - s21*u21 + s22 - s22*u22)/4.0;
639  s.sig[1] += snd;
640  s.dsig2[1] += pow2(snd);
641 
642  double sel = (el(s11, s22, u11, u22) + el(s12, s21, u12, u21))/2.0;
643  s.sig[6] += sel;
644  s.dsig2[6] += pow2(sel);
645 
646  double swt = stot - (el(s11, s12, u11, u12) + el(s21, s22, u21, u22))/2.0;
647  double swp = stot - (el(s11, s21, u11, u21) + el(s12, s22, u12, u22))/2.0;
648  s.sig[4] += swp;
649  s.dsig2[4] += pow2(swp);
650  s.sig[3] += swt;
651  s.dsig2[3] += pow2(swt);
652 
653  s.sig[2] += swt + swp - snd + sel - stot;
654  s.dsig2[2] += pow2(swt + swp - snd + sel - stot);
655 
656  s.sig[5] += s11;
657  s.dsig2[5] += pow2(s11);
658 
659  s.sig[7] += pow2(s11)/u11;
660  s.dsig2[7] += pow2(pow2(s11)/u11);
661 
662 
663 
664  }
665 
666  s.sig[0] /= double(NInt);
667  s.dsig2[0] = (s.dsig2[0]/double(NInt) - pow2(s.sig[0]))/double(NInt);
668 
669  s.sig[1] /= double(NInt);
670  s.dsig2[1] = (s.dsig2[1]/double(NInt) - pow2(s.sig[1]))/double(NInt);
671 
672  s.sig[2] /= double(NInt);
673  s.dsig2[2] = (s.dsig2[2]/double(NInt) - pow2(s.sig[2]))/double(NInt);
674 
675  s.sig[3] /= double(NInt);
676  s.dsig2[3] = (s.dsig2[3]/double(NInt) - pow2(s.sig[3]))/double(NInt);
677 
678  s.sig[4] /= double(NInt);
679  s.dsig2[4] = (s.dsig2[4]/double(NInt) - pow2(s.sig[4]))/double(NInt);
680 
681  s.sig[6] /= double(NInt);
682  s.dsig2[6] = (s.dsig2[6]/double(NInt) - pow2(s.sig[6]))/double(NInt);
683 
684  s.sig[5] /= double(NInt);
685  s.dsig2[5] /= double(NInt);
686 
687  s.sig[7] /= double(NInt);
688  s.dsig2[7] /= double(NInt);
689  double bS = (s.sig[7]/s.sig[5])/(16.0*M_PI*pow2(0.19732697));
690  double b2S = pow2(bS)*(s.dsig2[7]/pow2(s.sig[7]) - 1.0 +
691  s.dsig2[5]/pow2(s.sig[5]) - 1.0)/double(NInt);
692  s.sig[5] = 0.0;
693  s.dsig2[5] = 0.0;
694  s.sig[7] = bS;
695  s.dsig2[7] = b2S;
696 
697  s.avNDb /= double(NInt);
698  s.davNDb2 = (s.davNDb2/double(NInt) - pow2(s.avNDb))/double(NInt);
699  s.avNDb /= s.sig[1];
700  s.davNDb2 /= pow2(s.sig[1]);
701 
702  return s;
703 
704 }
705 
706 //--------------------------------------------------------------------------
707 
708 // Access funtions to parameters in the DoubleStrikman model.
709 
710 void DoubleStrikman::setParm(const vector<double> & p) {
711  if ( p.size() > 0 ) sigd = p[0];
712  if ( p.size() > 1 ) k0 = p[1];
713  if ( p.size() > 2 ) alpha = p[2];
714  r0 = sqrt(sigTot()/(M_PI*(2.0*k0 + 4.0*k0*k0)));
715 }
716 
717 vector<double> DoubleStrikman::getParm() const {
718  vector<double> ret(3);
719  ret[0] = sigd;
720  ret[1] = k0;
721  ret[2] = alpha;
722  return ret;
723 }
724 
725 vector<double> DoubleStrikman::minParm() const {
726  vector<double> ret(3);
727  ret[0] = 1.0;
728  ret[1] = 0.01;
729  ret[2] = 0.0;
730  return ret;
731 }
732 
733 vector<double> DoubleStrikman::maxParm() const {
734  vector<double> ret(3);
735  ret[0] = 20.0;
736  ret[1] = 20.0;
737  ret[2] = 2.0;
738  return ret;
739 }
740 
741 //--------------------------------------------------------------------------
742 
743 // Generate the radii in DoubleStrikman according to a gamma
744 // distribution.
745 
746 double DoubleStrikman::gamma() const {
747  static const double e = exp(1);
748  int k = int(k0);
749  double del = k0 - k;
750  double x = 0.0;
751  for ( int i = 0; i < k; ++i ) x += -log(rndPtr->flat());
752 
753  if ( del == 0.0 ) return x*r0;
754 
755  while ( true ) {
756  double U = rndPtr->flat();
757  double V = rndPtr->flat();
758  double W = rndPtr->flat();
759 
760  double xi = 0.0;
761  if ( U <= e/(e+del) ) {
762  xi = pow(V, 1.0/del);
763  if ( W <= exp(-xi) ) return r0*(x + xi);
764  } else {
765  xi = 1.0 - log(V);
766  if ( W <= pow(xi, del - 1.0) ) return r0*(x + xi);
767  }
768  }
769  return 0.0;
770 }
771 
772 //--------------------------------------------------------------------------
773 
774 // Helper functions to get the correct average elastic and wounded
775 // cross sections.
776 
777 void DoubleStrikman::shuffle(double PND1, double PND2,
778  double & PW1, double & PW2) {
779  if ( PND1 > PW1 ) {
780  PW2 += PW1 - PND1;
781  PW1 = PND1;
782  return;
783  }
784  if ( PND2 > PW2 ) {
785  PW1 += PW2 - PND2;
786  PW2 = PND2;
787  return;
788  }
789 }
790 
791 void DoubleStrikman::shuffel(double & PEL11, double P11,
792  double P12, double P21, double P22) {
793  double PEL12 = PEL11, PEL21 = PEL11, PEL22 = PEL11;
794  map<double, double *> ord;
795  ord[P11] = &PEL11;
796  ord[P12] = &PEL12;
797  ord[P21] = &PEL21;
798  ord[P22] = &PEL22;
799  map<double, double *>::iterator next = ord.begin();
800  map<double, double *>::iterator prev = next++;
801  while ( next != ord.end() ) {
802  if ( *prev->second > prev->first ) {
803  *next->second += *prev->second - prev->first;
804  *prev->second = prev->first;
805  }
806  prev = next++;
807  }
808 }
809 
810 //--------------------------------------------------------------------------
811 
812 // Main function returning the possible sub-collisions.
813 
814 multiset<SubCollision> DoubleStrikman::
815 getCollisions(vector<Nucleon> & proj, vector<Nucleon> & targ,
816  const Vec4 & bvec, double & T) {
817  // Always call base class to reset nucleons and shift them into
818  // position.
819  multiset<SubCollision> ret =
820  SubCollisionModel::getCollisions(proj, targ, bvec, T);
821 
823  for ( int ip = 0, Np = proj.size(); ip < Np; ++ip ) {
824  proj[ip].state(Nucleon::State(1, gamma()));
825  proj[ip].addAltState(Nucleon::State(1, gamma()));
826  }
827  for ( int it = 0, Nt = targ.size(); it < Nt; ++it ) {
828  targ[it].state(Nucleon::State(1, gamma()));
829  targ[it].addAltState(Nucleon::State(1, gamma()));
830  }
831 
832  // The factorising S-matrix.
833  double S = 1.0;
834 
835  // Go through all pairs of nucleons
836  for ( int ip = 0, Np = proj.size(); ip < Np; ++ip )
837  for ( int it = 0, Nt = targ.size(); it < Nt; ++it ) {
838  Nucleon & p = proj[ip];
839  Nucleon & t = targ[it];
840  double b = (p.bPos() - t.bPos()).pT();
841 
842  double T11 = Tpt(p.state(), t.state(), b);
843  double T12 = Tpt(p.state(), t.altState(), b);
844  double T21 = Tpt(p.altState(), t.state(), b);
845  double T22 = Tpt(p.altState(), t.altState(), b);
846  double S11 = 1.0 - T11;
847  double S12 = 1.0 - T12;
848  double S21 = 1.0 - T21;
849  double S22 = 1.0 - T22;
850  S *= S11;
851  double PND11 = 1.0 - pow2(S11);
852  // First and most important, check if this is an absorptive
853  // scattering.
854  if ( PND11 > rndPtr->flat() ) {
855  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::ABS));
856  continue;
857  }
858 
859  // Now set up calculation for probability of diffractively
860  // wounded nucleons.
861  double PND12 = 1.0 - pow2(S12);
862  double PND21 = 1.0 - pow2(S21);
863  double PWp11 = 1.0 - S11*S21;
864  double PWp21 = 1.0 - S11*S21;
865  shuffle(PND11, PND21, PWp11, PWp21);
866  double PWt11 = 1.0 - S11*S12;
867  double PWt12 = 1.0 - S11*S12;
868  shuffle(PND11, PND12, PWt11, PWt12);
869 
870  bool wt = ( PWt11 - PND11 > (1.0 - PND11)*rndPtr->flat() );
871  bool wp = ( PWp11 - PND11 > (1.0 - PND11)*rndPtr->flat() );
872  if ( wt && wp ) {
873  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::DDE));
874  continue;
875  }
876  if ( wt ) {
877  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::SDET));
878  continue;
879  }
880  if ( wp ) {
881  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::SDEP));
882  continue;
883  }
884 
885  // Finally set up calculation for elastic scattering. This can
886  // never be exact, but let's do as well as we can.
887 
888  double PND22 = 1.0 - pow2(S22);
889  double PWp12 = 1.0 - S12*S22;
890  double PWp22 = 1.0 - S12*S22;
891  shuffle(PND12, PND22, PWp12, PWp22);
892  double PWt21 = 1.0 - S21*S22;
893  double PWt22 = 1.0 - S21*S22;
894  shuffle(PND21, PND22, PWt21, PWt22);
895 
896  double PNW11 = PNW(PWp11, PWt11, PND11);
897  double PNW12 = PNW(PWp12, PWt12, PND12);
898  double PNW21 = PNW(PWp21, PWt21, PND21);
899  double PNW22 = PNW(PWp22, PWt22, PND22);
900 
901  double PEL = (T12*T21 + T11*T22)/2.0;
902  shuffel(PEL, PNW11, PNW12, PNW21, PNW22);
903  if ( PEL > PNW11*rndPtr->flat() ) {
904  if ( sigCDE() > rndPtr->flat()*(sigCDE() + sigEl()) )
905  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::CDE));
906  else
907  ret.insert(SubCollision(p, t, b, b/avNDb, SubCollision::ELASTIC));
908  }
909  }
910 
911 
912  T = 1.0 - S;
913 
914  return ret;
915 }
916 
917 //==========================================================================
918 
919 // MultiRadial uses a number of different disk sizes with different
920 // opacities. Like a discrete version of DoubleStrikman.
921 
922 //--------------------------------------------------------------------------
923 
924 // Numerically estimate the cross sections corresponding to the
925 // current parameter setting.
926 
928 
929  SigEst s;
930 
931  double sTpt = 0.0;
932  double sT2pt = 0.0;
933  // double sTpt2 = 0.0;
934  double sTp2t = 0.0;
935  // double sTt2p = 0.0;
936  double Rp = 0.0;
937  for ( int ip = 0; ip < Nr; ++ip ) {
938  Rp += dR[ip];
939  double Rt = 0.0;
940  for ( int it = 0; it < Nr; ++it ) {
941  Rt += dR[it];
942  sTpt += c[ip]*T0[ip]*c[it]*T0[it]*pow2(Rp + Rt)*sigTot();
943  sT2pt += c[ip]*pow2(T0[ip])*c[it]*pow2(T0[it])*pow2(Rp + Rt)*sigTot();
944  double rp = 0.0;
945  for ( int jp = 0; jp < Nr; ++jp ) {
946  rp += dR[jp];
947  double rt = 0.0;
948  for ( int jt = 0; jt < Nr; ++jt ) {
949  rt += dR[jt];
950  double fac = T0[ip]*T0[jp]*T0[it]*T0[jt]*pow2(min(Rp + Rt, rp + rt))
951  * sigTot();
952  if ( ip == jp ) sTp2t += c[ip]*c[it]*c[jt]*fac;
953  }
954  }
955  }
956 
957  }
958 
959  s.sig[0] /= double(NInt);
960  s.dsig2[0] = (s.dsig2[0]/double(NInt) - pow2(s.sig[0]))/double(NInt);
961 
962  s.sig[1] /= double(NInt);
963  s.dsig2[1] = (s.dsig2[1]/double(NInt) - pow2(s.sig[1]))/double(NInt);
964 
965  s.sig[2] /= double(NInt);
966  s.dsig2[2] = (s.dsig2[2]/double(NInt) - pow2(s.sig[2]))/double(NInt);
967 
968  s.sig[3] /= double(NInt);
969  s.dsig2[3] = (s.dsig2[3]/double(NInt) - pow2(s.sig[3]))/double(NInt);
970 
971  s.sig[4] /= double(NInt);
972  s.dsig2[4] = (s.dsig2[4]/double(NInt) - pow2(s.sig[4]))/double(NInt);
973 
974  s.sig[6] /= double(NInt);
975  s.dsig2[6] = (s.dsig2[6]/double(NInt) - pow2(s.sig[6]))/double(NInt);
976 
977  s.sig[5] /= double(NInt);
978  s.dsig2[5] /= double(NInt);
979 
980  s.sig[7] /= double(NInt);
981  s.dsig2[7] /= double(NInt);
982  double bS = (s.sig[7]/s.sig[5])/(16.0*M_PI*pow2(0.19732697));
983  double b2S = pow2(bS)*(s.dsig2[7]/pow2(s.sig[7]) - 1.0 +
984  s.dsig2[5]/pow2(s.sig[5]) - 1.0)/double(NInt);
985  s.sig[5] = 0.0;
986  s.dsig2[5] = 0.0;
987  s.sig[7] = bS;
988  s.dsig2[7] = b2S;
989 
990  return s;
991 
992 }
993 
994 //--------------------------------------------------------------------------
995 
996 // Access funtions to parameters in the MultiRadial model.
997 
998 void MultiRadial::setParm(const vector<double> & p) {
999  unsigned int ip = 0;
1000  for ( int i = 0; i < Nr; ++i ) {
1001  if ( ip < p.size() ) dR[i] = p[ip++];
1002  if ( ip < p.size() ) T0[i] = p[ip++];
1003  if ( ip < p.size() ) phi[i] = p[ip++];
1004  }
1005 }
1006 
1007 vector<double> MultiRadial::getParm() const {
1008  vector<double> ret;
1009  for ( int i = 0; i < Nr; ++i ) {
1010  ret.push_back(dR[i]);
1011  ret.push_back(T0[i]);
1012  if ( i < Nr -1 ) ret.push_back(phi[i]);
1013  }
1014  return ret;
1015 }
1016 
1017 vector<double> MultiRadial::minParm() const {
1018  return vector<double>(Nr*Nr*(Nr - 1), 0.0);
1019 }
1020 
1021 vector<double> MultiRadial::maxParm() const {
1022  return vector<double>(Nr*Nr*(Nr - 1), 1.0);
1023 }
1024 
1025 void MultiRadial::setProbs() {
1026  double rProj = 1.0;
1027  for ( int i = 0; i < Nr - 1; ++i ) {
1028  c[i] = rProj*cos(phi[i]*M_PI/2.0);
1029  rProj *= sin(phi[i]*M_PI/2.0);
1030  }
1031  c[Nr - 1] = rProj;
1032 }
1033 
1034 int MultiRadial::choose() const {
1035  double sum = 0.0;
1036  double sel = rndPtr->flat();
1037  for ( int i = 0; i < Nr - 1; ++i )
1038  if ( sel < ( sum += c[i] ) ) return i;
1039  return Nr - 1;
1040 }
1041 
1042 
1043 
1044 
1045 //--------------------------------------------------------------------------
1046 
1047 // Main function returning the possible sub-collisions.
1048 
1049 multiset<SubCollision> MultiRadial::
1050 getCollisions(vector<Nucleon> & proj, vector<Nucleon> & targ,
1051  const Vec4 & bvec, double & T) {
1052  // Always call base class to reset nucleons and shift them into
1053  // position.
1054  multiset<SubCollision> ret =
1055  SubCollisionModel::getCollisions(proj, targ, bvec, T);
1056 
1057  return ret;
1058 }
1059 
1060 //==========================================================================
1061 
1062 // HIInfo functions to collect statistics in an event and in a run.
1063 
1064 //--------------------------------------------------------------------------
1065 
1066 // Collect statistics for each SubCollision in an event.
1067 
1068 int HIInfo::addSubCollision(const SubCollision & c) {
1069  ++nCollSave[0];
1070  switch ( c.type ) {
1071  case SubCollision::ABS:
1072  return ++nCollSave[1];
1073  case SubCollision::SDEP:
1074  return ++nCollSave[2];
1075  case SubCollision::SDET:
1076  return ++nCollSave[3];
1077  case SubCollision::DDE:
1078  return ++nCollSave[4];
1079  case SubCollision::CDE:
1080  return ++nCollSave[5];
1081  case SubCollision::ELASTIC:
1082  return ++nCollSave[6];
1083  default:
1084  return 0;
1085  }
1086 }
1087 
1088 //--------------------------------------------------------------------------
1089 
1090 // Collect statistics for each participating Nucleon in an event.
1091 
1092 int HIInfo::addProjectileNucleon(const Nucleon & n) {
1093  ++nProjSave[0];
1094  switch ( n.status() ) {
1095  case Nucleon::ABS:
1096  return ++nProjSave[1];
1097  case Nucleon::DIFF:
1098  return ++nProjSave[2];
1099  case Nucleon::ELASTIC:
1100  return ++nProjSave[3];
1101  default:
1102  return 0;
1103  }
1104 }
1105 
1106 int HIInfo::addTargetNucleon(const Nucleon & n) {
1107  ++nTargSave[0];
1108  switch ( n.status() ) {
1109  case Nucleon::ABS:
1110  return ++nTargSave[1];
1111  case Nucleon::DIFF:
1112  return ++nTargSave[2];
1113  case Nucleon::ELASTIC:
1114  return ++nTargSave[3];
1115  default:
1116  return 0;
1117  }
1118 }
1119 
1120 //--------------------------------------------------------------------------
1121 
1122 // Collect statistics for attemted and accepted impact paramet point
1123 // in an event.
1124 
1125 void HIInfo::addAttempt(double T, double bin, double bweight) {
1126  bSave = bin;
1127  nCollSave = nProjSave = nTargSave = vector<int>(10, 0);
1128  nFailSave = 0;
1129  weightSave = bweight;
1130  weightSumSave += weightSave;
1131  ++NSave;
1132  double w = 2.0*T*bweight;
1133  double delta = w - sigmaTotSave;
1134  sigmaTotSave += delta/double(NSave);
1135  sigErr2TotSave += (delta*(w - sigmaTotSave) - sigErr2TotSave)/double(NSave);
1136  w = (2*T - T*T)*bweight;
1137  delta = w - sigmaNDSave;
1138  sigmaNDSave += delta/double(NSave);
1139  sigErr2NDSave += (delta*(w - sigmaNDSave) - sigErr2NDSave)/double(NSave);
1140 }
1141 
1142 
1143 void HIInfo::accept() {
1144  int pc = primInfo.code();
1145  weightSumSave += weightSave;
1146  ++NAccSave;
1147  sumPrimW[pc] += weightSave;
1148  sumPrimW2[pc] += weightSave*weightSave;
1149  ++NPrim[pc];
1150  NamePrim[pc] = primInfo.nameProc(pc);
1151 }
1152 
1153 //==========================================================================
1154 
1155 // The Nucleon class describing a Nucleon in a Nucleus.
1156 
1157 //--------------------------------------------------------------------------
1158 
1159 // Print out information about a Nuclean. To be called from inside a
1160 // debugger.
1161 
1163  cout << "Nucleon id: " << id() << endl;
1164  cout << "index: " << index() << endl;
1165  cout << "b(rel): " << nPos().px() << " " << nPos().py() << endl;
1166  cout << "b(abs): " << bPos().px() << " " << bPos().py() << endl;
1167  cout << "status: " << status() << (done()? " done": " ") << endl;
1168  cout << "state: ";
1169  for ( int i = 0, N = state().size(); i < N; ++i )
1170  cout << state()[i] << " ";
1171  cout << endl;
1172  for ( int j = 0, M = altStatesSave.size(); j < M; ++j ) {
1173  cout << "state " << j+1 << ": ";
1174  for ( int i = 0, N = altStatesSave[j].size(); i < N; ++i )
1175  cout << altStatesSave[j][i] << " ";
1176  cout << endl;
1177  }
1178 }
1179 
1180 //==========================================================================
1181 
1182 } // 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
vector< double > dsig2
The extimated error (squared)
Definition: HIUserHooks.h:459
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 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
vector< double > phi
The angles defining the probability distribution for the radii.
Definition: HIUserHooks.h:781
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
Internal class to report cross section estimates.
Definition: HIUserHooks.h:454
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
const State & altState(int i=0)
Return an alternative state.
Definition: HIUserHooks.h:115
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
vector< double > sig
The cross sections (tot, nd, dd, sdp, sdt, cd, el, bslope).
Definition: HIUserHooks.h:456
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
Type type
The type of collison.
Definition: HIUserHooks.h:236
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