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