Version: SMASH-2.2
deformednucleus.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2022
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/random.h"
17 #include "smash/threevector.h"
18 
19 namespace smash {
20 
93 DeformedNucleus::DeformedNucleus(const std::map<PdgCode, int> &particle_list,
94  int nTest)
95  : Nucleus(particle_list, nTest) {}
96 
98  bool auto_deformation)
99  : Nucleus(config, nTest) {
100  if (auto_deformation) {
103  } else {
105  }
106  if (config.has_value({"Deformed", "Orientation"})) {
107  Configuration subconfig = config["Deformed"]["Orientation"];
108  set_orientation_from_config(subconfig);
109  }
110 }
111 
113  double a_radius;
114  Angles a_direction;
115  // Set a sensible maximum bound for radial sampling.
116  double radius_max =
119 
120  // Sample the distribution.
121  do {
122  a_direction.distribute_isotropically();
123  // sample r**2 dr
124  a_radius = radius_max * std::cbrt(random::canonical());
125  } while (random::canonical() >
126  nucleon_density(a_radius, a_direction.costheta()) /
128 
129  // Update (x, y, z) positions.
130  return a_direction.threevec() * a_radius;
131 }
132 
134  // Set the deformation parameters
135  // reference for U, Pb, Au, Cu: \iref{Moller:1993ed}
136  // reference for Zr and Ru: \iref{Schenke:2019ruo}
137  // reference for Xe: \iref{Moller:2015fba}
138  bool listed = 0;
139  const std::map<int, std::string> A_map = {{238, "Uranium"},
140  {208, "Lead"},
141  {197, "Gold"},
142  {63, "Copper"},
143  {129, "Xenon"}};
144  const std::map<std::string, std::string> Z_map = {{"Uranium", "92"},
145  {"Lead", "82"},
146  {"Gold", "79"},
147  {"Copper", "29"},
148  {"Xenon", "54"}};
150  int Z = Nucleus::number_of_protons();
151  switch (A) {
152  case 238: // Uranium
153  if (Z == 92) {
154  set_beta_2(0.28);
155  set_beta_4(0.093);
156  } else {
157  listed = true;
158  }
159  break;
160  case 208: // Lead
161  if (Z == 82) {
162  set_beta_2(0.0);
163  set_beta_4(0.0);
164  } else {
165  listed = true;
166  }
167  break;
168  case 197: // Gold
169  if (Z == 79) {
170  set_beta_2(-0.131);
171  set_beta_4(-0.031);
172  } else {
173  listed = true;
174  }
175  break;
176  case 129: // Xenon
177  if (Z == 54) {
178  set_beta_2(0.162);
179  set_beta_4(-0.003);
180  } else {
181  listed = true;
182  }
183  break;
184  case 63: // Copper
185  if (Z == 29) {
186  set_beta_2(0.162);
187  set_beta_4(-0.006);
188  } else {
189  listed = true;
190  }
191  break;
192  case 96:
193  if (Z == 40) { // Zirconium
194  set_beta_2(0.0);
195  set_beta_4(0.0);
196  } else if (Z == 44) { // Ruthenium
197  set_beta_2(0.158);
198  set_beta_4(0.0);
199  } else {
200  throw std::domain_error(
201  "Number of protons for nuclei with mass number A = 96 does not "
202  "match that of Zirconium or Ruthenium. The deformation parameters "
203  "for additional isobars are currently not implemented."
204  " Please specify at least \"Beta_2\" and \"Beta_4\" "
205  "manually and set \"Automatic: False.\" ");
206  }
207  break;
208  default:
209  throw std::domain_error(
210  "Mass number not listed for automatically setting deformation "
211  "parameters. Please specify at least \"Beta_2\" and \"Beta_4\" "
212  "manually and set \"Automatic: False.\" ");
213  }
214  if (listed) {
215  throw std::domain_error("Mass number is listed under " + A_map.at(A) +
216  " but the proton "
217  "number of " +
218  std::to_string(Z) +
219  " does not match "
220  "its " +
221  Z_map.at(A_map.at(A)) +
222  " protons."
223  "Please specify at least \"Beta_2\" and \"Beta_4\" "
224  "manually and set \"Automatic: False.\" ");
225  }
226 }
227 
229  Configuration &config) {
230  // Deformation parameters.
231  if (config.has_value({"Deformed", "Beta_2"})) {
232  set_beta_2(static_cast<double>(config.take({"Deformed", "Beta_2"})));
233  }
234  if (config.has_value({"Deformed", "Beta_4"})) {
235  set_beta_4(static_cast<double>(config.take({"Deformed", "Beta_4"})));
236  }
237 }
238 
240  Configuration &orientation_config) {
241  // Read in orientation if provided, otherwise, the defaults are
242  // theta = pi/2, phi = 0, as declared in the angles class
243 
244  if (orientation_config.has_value({"Theta"})) {
245  if (orientation_config.has_value({"Random_Rotation"}) &&
246  orientation_config.take({"Random_Rotation"})) {
247  throw std::domain_error(
248  "Random rotation of nuclei is activated although"
249  " theta is provided. Please specify only either of them. ");
250  } else {
251  set_polar_angle(static_cast<double>(orientation_config.take({"Theta"})));
252  }
253  }
254 
255  if (orientation_config.has_value({"Phi"})) {
256  if (orientation_config.has_value({"Random_Rotation"}) &&
257  orientation_config.take({"Random_Rotation"})) {
258  throw std::domain_error(
259  "Random rotation of nuclei is activated although"
260  " phi is provided. Please specify only either of them. ");
261  } else {
263  static_cast<double>(orientation_config.take({"Phi"})));
264  }
265  }
266 
267  if (orientation_config.take({"Random_Rotation"}, false)) {
268  random_rotation_ = true;
269  }
270 }
271 
273  if (random_rotation_) {
274  // Randomly generate euler angles for theta and phi. Psi needs not be
275  // assigned, as the nucleus objects are symmetric with respect to psi.
279  }
280  for (auto &particle : *this) {
281  /* Rotate every vector by the nuclear azimuth phi and polar angle
282  * theta (the Euler angles). This means applying the matrix for a
283  * rotation of phi about z, followed by the matrix for a rotation
284  * theta about the rotated x axis. The third angle psi is 0 by symmetry.*/
285  ThreeVector three_pos = particle.position().threevec();
287  0.);
288  particle.set_3position(three_pos);
289  }
290 }
291 
292 double y_l_0(int l, double cosx) {
293  if (l == 2) {
294  return (1. / 4) * std::sqrt(5 / M_PI) * (3. * (cosx * cosx) - 1);
295  } else if (l == 4) {
296  return (3. / 16) * std::sqrt(1 / M_PI) *
297  (35. * (cosx * cosx) * (cosx * cosx) - 30. * (cosx * cosx) + 3);
298  } else {
299  throw std::domain_error(
300  "Not a valid angular momentum quantum number in y_l_0.");
301  }
302 }
303 
304 double DeformedNucleus::nucleon_density(double r, double cosx) const {
306  (1 + std::exp((r - Nucleus::get_nuclear_radius() *
307  (1 + beta2_ * y_l_0(2, cosx) +
308  beta4_ * y_l_0(4, cosx))) /
310 }
311 
313  double cosx) const {
314  return 1.0 / (1 + std::exp((r - Nucleus::get_nuclear_radius() *
315  (1 + beta2_ * y_l_0(2, cosx) +
316  beta4_ * y_l_0(4, cosx))) /
318 }
319 
320 } // 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:268
void distribute_isotropically()
Populate the object with a new direction.
Definition: angles.h:188
double theta() const
Definition: angles.h:272
double phi() const
Definition: angles.h:260
double costheta() const
Definition: angles.h:259
Interface to the SMASH configuration files.
bool has_value(std::initializer_list< const char * > keys) const
Returns whether there is a non-empty value behind the requested keys.
Value take(std::initializer_list< const char * > keys)
The default interface for SMASH to read configuration values.
void set_orientation_from_config(Configuration &orientation_config)
Set angles for orientation of nucleus from config file.
bool random_rotation_
Whether the nuclei should be rotated randomly.
double nucleon_density(double r, double cosx) const override
Return the deformed Woods-Saxon probability density for the given position.
ThreeVector distribute_nucleon() override
Deformed Woods-Saxon sampling routine.
double nucleon_density_unnormalized(double r, double cosx) const override
Return the unnormalized deformed Woods-Saxon distribution for the given position.
void set_polar_angle(double theta)
Set the nucleus polar angle.
void rotate() override
Rotates the nucleus according to members nucleus_polar_angle_ and nucleus_azimuthal_angle_ and update...
double beta4_
Deformation parameter for angular momentum l=4.
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.
Angles nuclear_orientation_
Nucleus orientation (initial profile in xz plane) in terms of a pair of angles (theta,...
DeformedNucleus(const std::map< PdgCode, int > &particle_list, int nTest)
Constructor for DeformedNucles which takes a particle list and the number of testparticles.
void set_beta_4(double b4)
Set deformation coefficient for Y_4_0.
void set_azimuthal_angle(double phi)
Set the nucleus azimuthal angle.
double beta2_
Deformation parameter for angular momentum l=2.
void set_deformation_parameters_automatic()
Sets the deformation parameters of the radius according to the current mass number.
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:331
double euler_theta_
Euler angel theta.
Definition: nucleus.h:303
double get_saturation_density() const
Definition: nucleus.h:336
void random_euler_angles()
Randomly generate Euler angles.
Definition: nucleus.cc:479
virtual double calculate_saturation_density() const
Definition: nucleus.cc:495
double get_nuclear_radius() const
Definition: nucleus.h:364
double euler_phi_
Euler angel phi.
Definition: nucleus.h:301
virtual void set_saturation_density(double density)
Sets the saturation density of the nucleus.
Definition: nucleus.h:261
size_t number_of_protons() const
Number of physical protons in the nucleus:
Definition: nucleus.h:184
size_t number_of_particles() const
Number of physical particles in the nucleus:
Definition: nucleus.h:165
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
void rotate(double phi, double theta, double psi)
Rotate vector by the given Euler angles phi, theta, psi.
Definition: threevector.h:276
Collection of useful constants that are known at compile time.
T canonical()
Definition: random.h:113
Definition: action.h:24
double y_l_0(int l, double cosx)
Spherical harmonics Y_2_0 and Y_4_0.