Version: SMASH-3.3
deformednucleus.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2022,2024-2025
3  * SMASH Team
4  *
5  * GNU General Public License (GPLv3 or later)
6  */
8 
9 #include <cmath>
10 #include <map>
11 #include <stdexcept>
12 
13 #include "smash/configuration.h"
14 #include "smash/constants.h"
15 #include "smash/fourvector.h"
16 #include "smash/input_keys.h"
17 #include "smash/random.h"
18 #include "smash/threevector.h"
19 
20 namespace smash {
21 
22 DeformedNucleus::DeformedNucleus(const std::map<PdgCode, int> &particle_list,
23  int nTest,
24  SpinInteractionType spin_interaction_type)
25  : Nucleus(particle_list, nTest, spin_interaction_type) {}
26 
28  bool auto_deformation)
29  : Nucleus(config, nTest) {
30  if (auto_deformation) {
33  } else {
35  }
36  /* If the config does not contain (anymore) a target or a projectile
37  sub-section, this code should not be executed, because e.g. the
38  is_about_projectile function would fail. */
39  if (has_projectile_or_target(config)) {
40  const auto &orientation_section = [&config]() {
43  }();
44  if (config.has_section(orientation_section)) {
45  Configuration sub_conf =
46  config.extract_complete_sub_configuration(orientation_section);
48  }
49  }
50 }
51 
53  double a_radius;
54  Angles a_direction;
55  // Set a sensible maximum bound for radial sampling.
56  double radius_max =
59 
60  // Sample the distribution.
61  do {
62  a_direction.distribute_isotropically();
63  // sample r**2 dr
64  a_radius = radius_max * std::cbrt(random::canonical());
65  } while (random::canonical() > nucleon_density(a_radius,
66  a_direction.costheta(),
67  a_direction.phi()) /
69 
70  // Update (x, y, z) positions.
71  return a_direction.threevec() * a_radius;
72 }
73 
75  // Set the deformation parameters
76  // reference for U, Pb, Au, Cu: \iref{Moller:1993ed}
77  // reference for Zr and Ru: \iref{Schenke:2019ruo}
78  // reference for Xe: \iref{Moller:2015fba}
79  bool listed = 0;
80  const std::map<int, std::string> A_map = {{238, "Uranium"},
81  {208, "Lead"},
82  {197, "Gold"},
83  {63, "Copper"},
84  {129, "Xenon"}};
85  const std::map<std::string, std::string> Z_map = {{"Uranium", "92"},
86  {"Lead", "82"},
87  {"Gold", "79"},
88  {"Copper", "29"},
89  {"Xenon", "54"}};
92  switch (A) {
93  case 238: // Uranium
94  if (Z == 92) {
95  set_beta_2(0.28);
96  set_beta_4(0.093);
97  } else {
98  listed = true;
99  }
100  break;
101  case 208: // Lead
102  if (Z == 82) {
103  set_beta_2(0.0);
104  set_beta_4(0.0);
105  } else {
106  listed = true;
107  }
108  break;
109  case 197: // Gold
110  if (Z == 79) {
111  set_beta_2(-0.131);
112  set_beta_4(-0.031);
113  } else {
114  listed = true;
115  }
116  break;
117  case 129: // Xenon
118  if (Z == 54) {
119  set_beta_2(0.162);
120  set_beta_4(-0.003);
121  } else {
122  listed = true;
123  }
124  break;
125  case 63: // Copper
126  if (Z == 29) {
127  set_beta_2(0.162);
128  set_beta_4(-0.006);
129  } else {
130  listed = true;
131  }
132  break;
133  case 96:
134  if (Z == 40) { // Zirconium
135  set_beta_2(0.0);
136  set_beta_4(0.0);
137  } else if (Z == 44) { // Ruthenium
138  set_beta_2(0.158);
139  set_beta_4(0.0);
140  } else {
141  throw std::domain_error(
142  "Number of protons for nuclei with mass number A = 96 does not "
143  "match that of Zirconium or Ruthenium. The deformation parameters "
144  "for additional isobars are currently not implemented."
145  " Please specify at least \"Beta_2\" and \"Beta_4\" "
146  "manually and set \"Automatic: False.\" ");
147  }
148  break;
149  default:
150  throw std::domain_error(
151  "Mass number not listed for automatically setting deformation "
152  "parameters. Please specify at least \"Beta_2\" and \"Beta_4\" "
153  "manually and set \"Automatic: False.\" ");
154  }
155  if (listed) {
156  throw std::domain_error("Mass number is listed under " + A_map.at(A) +
157  " but the proton "
158  "number of " +
159  std::to_string(Z) +
160  " does not match "
161  "its " +
162  Z_map.at(A_map.at(A)) +
163  " protons."
164  "Please specify at least \"Beta_2\" and \"Beta_4\" "
165  "manually and set \"Automatic: False.\" ");
166  }
167 }
168 
170  Configuration &config) {
171  if (has_projectile_or_target(config)) {
172  const bool is_projectile = is_about_projectile(config);
173  const auto &[beta2_key, beta3_key, beta4_key,
174  gamma_key] = [&is_projectile]() {
175  return is_projectile
176  ? std::make_tuple(
181  : std::make_tuple(
186  }();
187  // Deformation parameters
188  if (config.has_value(beta2_key)) {
189  beta2_ = config.take(beta2_key);
190  }
191  if (config.has_value(gamma_key)) {
192  gamma_ = config.take(gamma_key);
193  }
194  if (config.has_value(beta3_key)) {
195  beta3_ = config.take(beta3_key);
196  }
197  if (config.has_value(beta4_key)) {
198  beta4_ = config.take(beta4_key);
199  }
200  }
201 }
202 
203 double y_l_m(int l, int m, double cosx, double phi) {
204  if (l == 2 && m == 0) {
205  return (1. / 4) * std::sqrt(5 / M_PI) * (3. * (cosx * cosx) - 1);
206  } else if (l == 2 && m == 2) {
207  double sinx2 = 1. - cosx * cosx;
208  return (1. / 4) * std::sqrt(15 / (2. * M_PI)) * sinx2 * std::cos(2. * phi);
209  } else if (l == 3 && m == 0) {
210  return (1. / 4) * std::sqrt(7 / M_PI) *
211  (5. * cosx * (cosx * cosx) - 3. * cosx);
212  } else if (l == 4 && m == 0) {
213  return (3. / 16) * std::sqrt(1 / M_PI) *
214  (35. * (cosx * cosx) * (cosx * cosx) - 30. * (cosx * cosx) + 3);
215  } else {
216  throw std::domain_error(
217  "Not a valid angular momentum quantum number in y_l_m.");
218  }
219 }
220 
221 double DeformedNucleus::nucleon_density(double r, double cosx,
222  double phi) const {
224  (1 + std::exp((r - Nucleus::get_nuclear_radius() *
225  (1 +
226  beta2_ * (std::cos(gamma_) *
227  y_l_m(2, 0, cosx, phi) +
228  std::sqrt(2) * std::sin(gamma_) *
229  y_l_m(2, 2, cosx, phi)) +
230  beta3_ * y_l_m(3, 0, cosx, phi) +
231  beta4_ * y_l_m(4, 0, cosx, phi))) /
233 }
234 
236  double phi) const {
237  return 1.0 /
238  (1 + std::exp((r - Nucleus::get_nuclear_radius() *
239  (1 +
240  beta2_ * (std::cos(gamma_) *
241  y_l_m(2, 0, cosx, phi) +
242  std::sqrt(2) * std::sin(gamma_) *
243  y_l_m(2, 2, cosx, phi)) +
244  beta3_ * y_l_m(3, 0, cosx, phi) +
245  beta4_ * y_l_m(4, 0, cosx, phi))) /
247 }
248 
250  double cosx) const {
252  // Perform the phi integration. This is needed if the triaxiality coefficient
253  // gamma is included, which includes a dependency around the phi axis.
254  // Unfortunately the Integrator class does not support 3d integration which is
255  // why this intermediate integral is needed. It has been checked that the
256  // integral factorizes.
257  const auto result = integrate(0.0, 2.0 * M_PI, [&](double phi) {
258  return nucleon_density_unnormalized(r, cosx, phi);
259  });
260  return result.value();
261 }
262 
265  // Transform integral from (0, oo) to (0, 1) via r = (1 - t) / t.
266  // To prevent overflow, the integration is only performed to t = 0.01 which
267  // corresponds to r = 99fm. Additionally the precision settings in the
268  // Integrator2d scheme are equally important. However both these point affect
269  // the result only after the seventh digit which should not be relevant here.
270  if (gamma_ == 0.0) {
271  const auto result = integrate(0.01, 1, -1, 1, [&](double t, double cosx) {
272  const double r = (1 - t) / t;
273  return twopi * std::pow(r, 2.0) *
274  nucleon_density_unnormalized(r, cosx, 0.0) / std::pow(t, 2.0);
275  });
276  const auto rho0 = number_of_particles() / result.value();
277  return rho0;
278  } else {
279  const auto result = integrate(0.01, 1, -1, 1, [&](double t, double cosx) {
280  const double r = (1 - t) / t;
281  return std::pow(r, 2.0) * integrant_nucleon_density_phi(r, cosx) /
282  std::pow(t, 2.0);
283  });
284  const auto rho0 = number_of_particles() / result.value();
285  return rho0;
286  }
287 }
288 
289 } // namespace smash
Angles provides a common interface for generating directions: i.e., two angles that should be interpr...
Definition: angles.h:59
ThreeVector threevec() const
Definition: angles.h:288
void distribute_isotropically()
Populate the object with a new direction.
Definition: angles.h:199
double phi() const
Definition: angles.h:279
double costheta() const
Definition: angles.h:278
Interface to the SMASH configuration files.
bool has_value(const Key< T > &key) const
Return whether there is a non-empty value behind the requested key (which is supposed not to refer to...
bool has_section(const KeyLabels &labels) const
Return whether there is a (possibly empty) section with the given labels.
Configuration extract_complete_sub_configuration(KeyLabels section, Configuration::GetEmpty empty_if_not_existing=Configuration::GetEmpty::No)
Alternative method to extract a sub-configuration, which retains the labels from the top-level in the...
T take(const Key< T > &key)
The default interface for SMASH to read configuration values.
ThreeVector distribute_nucleon() override
Deformed Woods-Saxon sampling routine.
double nucleon_density_unnormalized(double r, double cosx, double phi) const override
Return the unnormalized deformed Woods-Saxon distribution for the given position.
double integrant_nucleon_density_phi(double r, double cosx) const
Return the integral over the azimuthal angle phi.
double beta4_
Deformation parameter for angular momentum l=4.
double gamma_
Triaxiality parameter for angular momentum l=2.
void set_deformation_parameters_from_config(Configuration &config)
Set parameters for spherical deformation of the nucleus from the values specified in the configuratio...
void set_beta_2(double b2)
Set deformation coefficient for Y_2_0.
double beta3_
Deformation parameter for angular momentum l=3.
DeformedNucleus(const std::map< PdgCode, int > &particle_list, int nTest, SpinInteractionType spin_interaction_type=SpinInteractionType::Off)
Constructor for DeformedNucles which takes a particle list and the number of testparticles.
double nucleon_density(double r, double cosx, double phi) const override
Return the deformed Woods-Saxon probability density for the given position.
void set_beta_4(double b4)
Set deformation coefficient for Y_4_0.
double beta2_
Deformation parameter for angular momentum l=2.
double calculate_saturation_density() const override
void set_deformation_parameters_automatic()
Sets the deformation parameters of the radius according to the current mass number.
A C++ interface for numerical integration in two dimensions with the Cuba Cuhre integration function.
Definition: integrate.h:219
A C++ interface for numerical integration in one dimension with the GSL CQUAD integration functions.
Definition: integrate.h:106
A nucleus is a collection of particles that are initialized, before the beginning of the simulation a...
Definition: nucleus.h:27
double get_diffusiveness() const
Definition: nucleus.h:338
double get_saturation_density() const
Definition: nucleus.h:343
double get_nuclear_radius() const
Definition: nucleus.h:371
virtual void set_saturation_density(double density)
Sets the saturation density of the nucleus.
Definition: nucleus.h:255
size_t number_of_protons() const
Number of physical protons in the nucleus:
Definition: nucleus.h:178
size_t number_of_particles() const
Number of physical particles in the nucleus:
Definition: nucleus.h:159
void set_orientation_from_config(Configuration &orientation_config)
Set angles for rotation of the nucleus from config file.
Definition: nucleus.cc:364
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
Collection of useful constants that are known at compile time.
SpinInteractionType
Possible spin interaction types.
T canonical()
Definition: random.h:113
Definition: action.h:24
static Integrator integrate
Definition: decaytype.cc:143
double y_l_m(int l, int m, double cosx, double phi)
Spherical harmonics Y_2_0, Y_2_2, Y_3_0 and Y_4_0.
constexpr double twopi
.
Definition: constants.h:49
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
Definition: stringify.cc:26
bool has_projectile_or_target(const Configuration &config)
Find out whether a configuration has a projectile or a target sub-section.
Definition: nucleus.cc:588
bool is_about_projectile(const Configuration &config)
Find out whether a configuration is about projectile or target.
Definition: nucleus.cc:594
static const Key< double > modi_collider_projectile_deformed_beta3
See user guide description for more information.
Definition: input_keys.h:3597
static const Key< double > modi_collider_projectile_deformed_beta4
See user guide description for more information.
Definition: input_keys.h:3617
static const Key< double > modi_collider_target_deformed_beta2
See user guide description for more information.
Definition: input_keys.h:3582
static const Key< double > modi_collider_target_deformed_beta4
See user guide description for more information.
Definition: input_keys.h:3622
static const Key< double > modi_collider_projectile_deformed_beta2
See user guide description for more information.
Definition: input_keys.h:3577
static const Key< double > modi_collider_projectile_deformed_gamma
See user guide description for more information.
Definition: input_keys.h:3637
static const Key< double > modi_collider_target_deformed_gamma
See user guide description for more information.
Definition: input_keys.h:3642
static const Key< double > modi_collider_target_deformed_beta3
See user guide description for more information.
Definition: input_keys.h:3602
static const Section m_c_p_orientation
Subsection for the projectile orientation in collider modus.
Definition: input_keys.h:114
static const Section m_c_t_orientation
Subsection for the target orientation in collider modus.
Definition: input_keys.h:128