Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
nucleon.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file nucleon.cxx
1 // TRENTO: Reduced Thickness Event-by-event Nuclear Topology
2 // Copyright 2015 Jonah E. Bernhard, J. Scott Moreland
3 // TRENTO3D: Three-dimensional extension of TRENTO by Weiyao Ke
4 // MIT License
5 
6 #include "nucleon.h"
7 
8 #include <cmath>
9 #include <limits>
10 #include <random>
11 #include <stdexcept>
12 
13 #include <boost/math/constants/constants.hpp>
14 #include <boost/math/special_functions/expint.hpp>
15 #include <boost/math/tools/roots.hpp>
16 #include <boost/program_options/variables_map.hpp>
17 
18 #include "fwd_decl.h"
19 
20 namespace trento {
21 
22 namespace {
23 
24 // Create ctor parameters for unit mean std::gamma_distribution.
25 // mean = alpha*beta == 1 -> beta = 1/alpha
26 // Used below in NucleonProfile ctor initializer list.
27 
28 template <typename RealType> using param_type =
29  typename std::gamma_distribution<RealType>::param_type;
30 
31 template <typename RealType>
32 param_type<RealType> gamma_param_unit_mean(RealType alpha = 1.) {
33  return param_type<RealType>{alpha, 1./alpha};
34 }
35 
36 // These constants define distances in terms of the width of the nucleon profile
37 // Gaussian thickness function.
38 
39 // Truncation radius of the thickness function.
40 constexpr double trunc_radius_widths = 5.;
41 
42 // Maximum impact parameter for participation.
43 constexpr double max_impact_widths = 6.;
44 
45 // Trivial helper function.
46 template <typename T>
47 constexpr T sqr(T value) {
48  return value * value;
49 }
50 
51 // Inelastic nucleon-nucleon cross section as function of beam energy sqrt(s)
52 // Fit coefficients explained in the docs.
53 double cross_sec_from_energy(double sqrts) {
54  auto a = 3.1253;
55  auto b = 0.1280;
56  auto c = 2.0412;
57  auto d = 1.8231;
58  return a + b * pow(std::log(sqrts) - c, d);
59 }
60 
61 // Determine the cross section parameter for sampling participants.
62 // See section "Fitting the cross section" in the online docs.
63 double compute_cross_sec_param(const VarMap& var_map) {
64  // Read parameters from the configuration.
65 
66  // Use manual inelastic nucleon-nucleon cross section if specified.
67  // Otherwise default to extrapolated cross section.
68  auto sigma_nn = var_map["cross-section"].as<double>();
69  if (sigma_nn < 0) {
70  sigma_nn = cross_sec_from_energy(var_map["beam-energy"].as<double>());
71  }
72  auto width = var_map["nucleon-width"].as<double>();
73 
74  // Initialize arguments for boost root finding function.
75 
76  // Bracket min and max.
77  auto a = -10.;
78  auto b = 20.;
79 
80  // Tolerance function.
81  // Require 3/4 of double precision.
82  math::tools::eps_tolerance<double> tol{
83  (std::numeric_limits<double>::digits * 3) / 4};
84 
85  // Maximum iterations.
86  // This is overkill -- in testing only 10-20 iterations were required
87  // (but no harm in overestimating).
88  boost::uintmax_t max_iter = 1000;
89 
90  // The right-hand side of the equation.
91  auto rhs = sigma_nn / (4 * math::double_constants::pi * sqr(width));
92 
93  // This quantity appears a couple times in the equation.
94  auto c = sqr(max_impact_widths) / 4;
95 
96  try {
97  auto result = math::tools::toms748_solve(
98  [&rhs, &c](double x) {
99  using std::exp;
100  using math::expint;
101  return c - expint(-exp(x)) + expint(-exp(x-c)) - rhs;
102  },
103  a, b, tol, max_iter);
104 
105  return .5*(result.first + result.second);
106  }
107  catch (const std::domain_error&) {
108  // Root finding fails for very small nucleon widths, w^2/sigma_nn < ~0.01.
109  throw std::domain_error{
110  "unable to fit cross section -- nucleon width too small?"};
111  }
112 }
113 
114 } // unnamed namespace
115 
117  : width_sqr_(sqr(var_map["nucleon-width"].as<double>())),
118  trunc_radius_sqr_(sqr(trunc_radius_widths)*width_sqr_),
119  max_impact_sqr_(sqr(max_impact_widths)*width_sqr_),
120  neg_one_div_two_width_sqr_(-.5/width_sqr_),
121  neg_one_div_four_width_sqr_(-.25/width_sqr_),
122  one_div_four_pi_(0.5*math::double_constants::one_div_two_pi),
123  cross_sec_param_(compute_cross_sec_param(var_map)),
124  fast_exp_(-.5*sqr(trunc_radius_widths), 0., 1000),
125  fluct_dist_(gamma_param_unit_mean(var_map["fluctuation"].as<double>())),
126  prefactor_(math::double_constants::one_div_two_pi/width_sqr_),
127  with_ncoll_(var_map["ncoll"].as<bool>())
128 {}
129 
130 } // namespace trento