Version: SMASH-2.1
deformednucleus.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2021
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) {
102  } else {
104  }
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  bool listed = 0;
138  const std::map<int, std::string> A_map = {
139  {238, "Uranium"}, {208, "Lead"}, {197, "Gold"}, {63, "Copper"}};
140  const std::map<std::string, std::string> Z_map = {
141  {"Uranium", "92"}, {"Lead", "82"}, {"Gold", "79"}, {"Copper", "29"}};
143  int Z = Nucleus::number_of_protons();
144  switch (A) {
145  case 238: // Uranium
146  if (Z == 92) {
147  set_beta_2(0.28);
148  set_beta_4(0.093);
149  } else {
150  listed = true;
151  }
152  break;
153  case 208: // Lead
154  if (Z == 82) {
155  set_beta_2(0.0);
156  set_beta_4(0.0);
157  } else {
158  listed = true;
159  }
160  break;
161  case 197: // Gold
162  if (Z == 79) {
163  set_beta_2(-0.131);
164  set_beta_4(-0.031);
165  } else {
166  listed = true;
167  }
168  break;
169  case 63: // Copper
170  if (Z == 29) {
171  set_beta_2(0.162);
172  set_beta_4(-0.006);
173  } else {
174  listed = true;
175  }
176  break;
177  case 96:
178  if (Z == 40) { // Zirconium
179  set_beta_2(0.0);
180  set_beta_4(0.0);
181  } else if (Z == 44) { // Ruthenium
182  set_beta_2(0.158);
183  set_beta_4(0.0);
184  } else {
185  throw std::domain_error(
186  "Number of protons for nuclei with mass number A = 96 does not "
187  "match that of Zirconium or Ruthenium. The deformation parameters "
188  "for additional isobars are currently not implemented."
189  " Please specify at least \"Beta_2\" and \"Beta_4\" "
190  "manually and set \"Automatic: False.\" ");
191  }
192  break;
193  default:
194  throw std::domain_error(
195  "Mass number not listed for automatically setting deformation "
196  "parameters. Please specify at least \"Beta_2\" and \"Beta_4\" "
197  "manually and set \"Automatic: False.\" ");
198  }
199  if (listed) {
200  throw std::domain_error("Mass number is listed under " + A_map.at(A) +
201  " but the proton "
202  "number of " +
203  std::to_string(Z) +
204  " does not match "
205  "its " +
206  Z_map.at(A_map.at(A)) +
207  " protons."
208  "Please specify at least \"Beta_2\" and \"Beta_4\" "
209  "manually and set \"Automatic: False.\" ");
210  }
211 }
212 
214  Configuration &config) {
215  // Deformation parameters.
216  if (config.has_value({"Deformed", "Beta_2"})) {
217  set_beta_2(static_cast<double>(config.take({"Deformed", "Beta_2"})));
218  }
219  if (config.has_value({"Deformed", "Beta_4"})) {
220  set_beta_4(static_cast<double>(config.take({"Deformed", "Beta_4"})));
221  }
222 }
223 
225  Configuration &orientation_config) {
226  // Read in orientation if provided, otherwise, the defaults are
227  // theta = pi/2, phi = 0, as declared in the angles class
228 
229  if (orientation_config.has_value({"Theta"})) {
230  if (orientation_config.has_value({"Random_Rotation"}) &&
231  orientation_config.take({"Random_Rotation"})) {
232  throw std::domain_error(
233  "Random rotation of nuclei is activated although"
234  " theta is provided. Please specify only either of them. ");
235  } else {
236  set_polar_angle(static_cast<double>(orientation_config.take({"Theta"})));
237  }
238  }
239 
240  if (orientation_config.has_value({"Phi"})) {
241  if (orientation_config.has_value({"Random_Rotation"}) &&
242  orientation_config.take({"Random_Rotation"})) {
243  throw std::domain_error(
244  "Random rotation of nuclei is activated although"
245  " phi is provided. Please specify only either of them. ");
246  } else {
248  static_cast<double>(orientation_config.take({"Phi"})));
249  }
250  }
251 
252  if (orientation_config.take({"Random_Rotation"}, false)) {
253  random_rotation_ = true;
254  }
255 }
256 
258  if (random_rotation_) {
259  // Randomly generate euler angles for theta and phi. Psi needs not be
260  // assigned, as the nucleus objects are symmetric with respect to psi.
264  }
265  for (auto &particle : *this) {
266  /* Rotate every vector by the nuclear azimuth phi and polar angle
267  * theta (the Euler angles). This means applying the matrix for a
268  * rotation of phi about z, followed by the matrix for a rotation
269  * theta about the rotated x axis. The third angle psi is 0 by symmetry.*/
270  ThreeVector three_pos = particle.position().threevec();
272  0.);
273  particle.set_3position(three_pos);
274  }
275 }
276 
277 double y_l_0(int l, double cosx) {
278  if (l == 2) {
279  return (1. / 4) * std::sqrt(5 / M_PI) * (3. * (cosx * cosx) - 1);
280  } else if (l == 4) {
281  return (3. / 16) * std::sqrt(1 / M_PI) *
282  (35. * (cosx * cosx) * (cosx * cosx) - 30. * (cosx * cosx) + 3);
283  } else {
284  throw std::domain_error(
285  "Not a valid angular momentum quantum number in y_l_0.");
286  }
287 }
288 
289 double DeformedNucleus::nucleon_density(double r, double cosx) const {
291  (1 + std::exp((r - Nucleus::get_nuclear_radius() *
292  (1 + beta2_ * y_l_0(2, cosx) +
293  beta4_ * y_l_0(4, cosx))) /
295 }
296 
297 } // 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.
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:302
double euler_theta_
Euler angel theta.
Definition: nucleus.h:274
double get_saturation_density() const
Definition: nucleus.h:314
void random_euler_angles()
Randomly generate Euler angles.
Definition: nucleus.cc:497
double get_nuclear_radius() const
Definition: nucleus.h:342
double euler_phi_
Euler angel phi.
Definition: nucleus.h:272
size_t number_of_protons() const
Number of physical protons in the nucleus:
Definition: nucleus.h:183
size_t number_of_particles() const
Number of physical particles in the nucleus:
Definition: nucleus.h:164
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.