Version: SMASH-3.0
potentials.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2015,2017-2022
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/potentials.h"
11 
12 #include "smash/constants.h"
13 #include "smash/density.h"
14 
15 namespace smash {
16 
18  : param_(param),
19  use_skyrme_(conf.has_value({"Skyrme"})),
20  use_symmetry_(conf.has_value({"Symmetry"})),
21  use_coulomb_(conf.has_value({"Coulomb"})),
22  use_vdf_(conf.has_value({"VDF"})) {
23  if (use_skyrme_) {
24  skyrme_a_ = conf.take({"Skyrme", "Skyrme_A"});
25  skyrme_b_ = conf.take({"Skyrme", "Skyrme_B"});
26  skyrme_tau_ = conf.take({"Skyrme", "Skyrme_Tau"});
27  }
28 
29  if (use_symmetry_) {
30  symmetry_S_Pot_ = conf.take({"Symmetry", "S_Pot"});
31  if (conf.has_value({"Symmetry", "gamma"})) {
32  symmetry_gamma_ = conf.take({"Symmetry", "gamma"});
33  symmetry_is_rhoB_dependent_ = true;
34  }
35  }
36  if (use_coulomb_) {
37  coulomb_r_cut_ = conf.take({"Coulomb", "R_Cut"});
38  }
39  if (use_vdf_) {
40  saturation_density_ = conf.take({"VDF", "Sat_rhoB"});
41  std::vector<double> aux_coeffs = conf.take({"VDF", "Coeffs"});
42  std::vector<double> aux_powers = conf.take({"VDF", "Powers"});
43  if (aux_coeffs.size() != aux_powers.size()) {
44  throw std::invalid_argument(
45  "The number of coefficients should equal the number of powers.");
46  }
47  const int n_terms = aux_powers.size();
48  for (int i = 0; i < n_terms; i++) {
49  if (aux_powers[i] < 0.0) {
50  throw std::invalid_argument("Powers need to be positive real numbers.");
51  }
52  // coefficients are provided in MeV, but the code uses GeV
53  coeffs_.push_back(aux_coeffs[i] * mev_to_gev);
54  powers_.push_back(aux_powers[i]);
55  }
56  }
57 }
58 
60 
61 double Potentials::skyrme_pot(const double baryon_density) const {
62  const double tmp = baryon_density / nuclear_density;
63  /* U = U(|rho|) * sgn , because the sign of the potential changes
64  * under a charge reversal transformation. */
65  const int sgn = tmp > 0 ? 1 : -1;
66  // Return in GeV
67  return mev_to_gev * sgn *
68  (skyrme_a_ * std::abs(tmp) +
69  skyrme_b_ * std::pow(std::abs(tmp), skyrme_tau_));
70 }
71 double Potentials::symmetry_S(const double baryon_density) const {
73  return 12.3 * std::pow(baryon_density / nuclear_density, 2. / 3.) +
74  20.0 * std::pow(baryon_density / nuclear_density, symmetry_gamma_);
75  } else {
76  return 0.;
77  }
78 }
79 double Potentials::symmetry_pot(const double baryon_isospin_density,
80  const double baryon_density) const {
81  double pot = mev_to_gev * 2. * symmetry_S_Pot_ * baryon_isospin_density /
84  pot += mev_to_gev * symmetry_S(baryon_density) * baryon_isospin_density *
85  baryon_isospin_density / (baryon_density * baryon_density);
86  }
87  return pot;
88 }
89 
90 FourVector Potentials::vdf_pot(double rhoB, const FourVector jmuB_net) const {
91  // this needs to be used in order to prevent trying to calculate something
92  // like
93  // (-rho_B)^{3.4}
94  const int sgn = rhoB > 0 ? 1 : -1;
95  double abs_rhoB = std::abs(rhoB);
96  // to prevent NAN expressions
97  if (abs_rhoB < very_small_double) {
98  abs_rhoB = very_small_double;
99  }
100  // F_2 is a multiplicative factor in front of the baryon current
101  // in the VDF potential
102  double F_2 = 0.0;
103  for (int i = 0; i < number_of_terms(); i++) {
104  F_2 += coeffs_[i] * std::pow(abs_rhoB, powers_[i] - 2.0) /
105  std::pow(saturation_density_, powers_[i] - 1.0);
106  }
107  F_2 = F_2 * sgn;
108  // Return in GeV
109  return F_2 * jmuB_net;
110 }
111 
112 double Potentials::potential(const ThreeVector &r, const ParticleList &plist,
113  const ParticleType &acts_on) const {
114  double total_potential = 0.0;
115  const bool compute_gradient = false;
116  const bool smearing = true;
117  const auto scale = force_scale(acts_on);
118 
119  if (!(acts_on.is_baryon() || acts_on.is_nucleus())) {
120  return total_potential;
121  }
122  const auto baryon_density_and_gradient = current_eckart(
123  r, plist, param_, DensityType::Baryon, compute_gradient, smearing);
124  const double rhoB = std::get<0>(baryon_density_and_gradient);
125  if (use_skyrme_) {
126  total_potential += scale.first * skyrme_pot(rhoB);
127  }
128  if (use_symmetry_) {
129  const double rho_iso = std::get<0>(
131  compute_gradient, smearing));
132  const double sym_pot = symmetry_pot(rho_iso, rhoB) * acts_on.isospin3_rel();
133  total_potential += scale.second * sym_pot;
134  }
135 
136  if (use_vdf_) {
137  const FourVector jmuB = std::get<1>(baryon_density_and_gradient);
138  const FourVector VDF_potential = vdf_pot(rhoB, jmuB);
139  total_potential += scale.first * VDF_potential.x0();
140  }
141 
142  return total_potential;
143 }
144 
145 std::pair<double, int> Potentials::force_scale(const ParticleType &data) {
146  const auto &pdg = data.pdgcode();
147  const double skyrme_or_VDF_scale =
148  (3 - std::abs(pdg.strangeness())) / 3. * pdg.baryon_number();
149  const int symmetry_scale = pdg.baryon_number();
150  return std::make_pair(skyrme_or_VDF_scale, symmetry_scale);
151 }
152 
153 std::pair<ThreeVector, ThreeVector> Potentials::skyrme_force(
154  const double rhoB, const ThreeVector grad_j0B, const ThreeVector dvecjB_dt,
155  const ThreeVector curl_vecjB) const {
156  ThreeVector E_component(0.0, 0.0, 0.0), B_component(0.0, 0.0, 0.0);
157  if (use_skyrme_) {
158  const int sgn = rhoB > 0 ? 1 : -1;
159  const double abs_rhoB = std::abs(rhoB);
160  const double dV_drho = sgn *
162  std::pow(abs_rhoB / nuclear_density,
163  skyrme_tau_ - 1)) *
165  E_component -= dV_drho * (grad_j0B + dvecjB_dt);
166  B_component += dV_drho * curl_vecjB;
167  }
168  return std::make_pair(E_component, B_component);
169 }
170 
171 std::pair<ThreeVector, ThreeVector> Potentials::symmetry_force(
172  const double rhoI3, const ThreeVector grad_j0I3,
173  const ThreeVector dvecjI3_dt, const ThreeVector curl_vecjI3,
174  const double rhoB, const ThreeVector grad_j0B, const ThreeVector dvecjB_dt,
175  const ThreeVector curl_vecjB) const {
176  ThreeVector E_component(0.0, 0.0, 0.0), B_component(0.0, 0.0, 0.0);
177  if (use_symmetry_) {
178  E_component -= dVsym_drhoI3(rhoB, rhoI3) * (grad_j0I3 + dvecjI3_dt) +
179  dVsym_drhoB(rhoB, rhoI3) * (grad_j0B + dvecjB_dt);
180  B_component += dVsym_drhoI3(rhoB, rhoI3) * curl_vecjI3 +
181  dVsym_drhoB(rhoB, rhoI3) * curl_vecjB;
182  }
183  return std::make_pair(E_component, B_component);
184 }
185 
186 std::pair<ThreeVector, ThreeVector> Potentials::vdf_force(
187  double rhoB, const double drhoB_dt, const ThreeVector grad_rhoB,
188  const ThreeVector gradrhoB_cross_vecjB, const double j0B,
189  const ThreeVector grad_j0B, const ThreeVector vecjB,
190  const ThreeVector dvecjB_dt, const ThreeVector curl_vecjB) const {
191  // this needs to be used to prevent trying to calculate something like
192  // (-rhoB)^{3.4}
193  const int sgn = rhoB > 0 ? 1 : -1;
194  ThreeVector E_component(0.0, 0.0, 0.0), B_component(0.0, 0.0, 0.0);
195  // to prevent NAN expressions
196  double abs_rhoB = std::abs(rhoB);
197  if (abs_rhoB < very_small_double) {
198  abs_rhoB = very_small_double;
199  }
200  if (use_vdf_) {
201  // F_1 and F_2 are multiplicative factors in front of the baryon current
202  // in the VDF potential
203  double F_1 = 0.0;
204  for (int i = 0; i < number_of_terms(); i++) {
205  F_1 += coeffs_[i] * (powers_[i] - 2.0) *
206  std::pow(abs_rhoB, powers_[i] - 3.0) /
207  std::pow(saturation_density_, powers_[i] - 1.0);
208  }
209  F_1 = F_1 * sgn;
210 
211  double F_2 = 0.0;
212  for (int i = 0; i < number_of_terms(); i++) {
213  F_2 += coeffs_[i] * std::pow(abs_rhoB, powers_[i] - 2.0) /
214  std::pow(saturation_density_, powers_[i] - 1.0);
215  }
216  F_2 = F_2 * sgn;
217 
218  E_component -= (F_1 * (grad_rhoB * j0B + drhoB_dt * vecjB) +
219  F_2 * (grad_j0B + dvecjB_dt));
220  B_component += F_1 * gradrhoB_cross_vecjB + F_2 * curl_vecjB;
221  }
222  return std::make_pair(E_component, B_component);
223 }
224 
225 // overload of the above
226 std::pair<ThreeVector, ThreeVector> Potentials::vdf_force(
227  const ThreeVector grad_A_0, const ThreeVector dA_dt,
228  const ThreeVector curl_A) const {
229  ThreeVector E_component(0.0, 0.0, 0.0), B_component(0.0, 0.0, 0.0);
230  if (use_vdf_) {
231  E_component -= (grad_A_0 + dA_dt);
232  B_component += curl_A;
233  }
234  return std::make_pair(E_component, B_component);
235 }
236 
237 double Potentials::dVsym_drhoI3(const double rhoB, const double rhoI3) const {
238  double term1 = 2. * symmetry_S_Pot_ / nuclear_density;
240  double term2 = 2. * rhoI3 * symmetry_S(rhoB) / (rhoB * rhoB);
241  return mev_to_gev * (term1 + term2);
242  } else {
243  return mev_to_gev * term1;
244  }
245 }
246 
247 double Potentials::dVsym_drhoB(const double rhoB, const double rhoI3) const {
249  double rhoB_over_rho0 = rhoB / nuclear_density;
250  double term1 = 8.2 * std::pow(rhoB_over_rho0, -1. / 3.) / nuclear_density +
251  20. * symmetry_gamma_ *
252  std::pow(rhoB_over_rho0, symmetry_gamma_) / rhoB;
253  double term2 = -2. * symmetry_S(rhoB) / rhoB;
254  return mev_to_gev * (term1 + term2) * rhoI3 * rhoI3 / (rhoB * rhoB);
255  } else {
256  return 0.;
257  }
258 }
259 
260 std::tuple<ThreeVector, ThreeVector, ThreeVector, ThreeVector>
261 Potentials::all_forces(const ThreeVector &r, const ParticleList &plist) const {
262  const bool compute_gradient = true;
263  const bool smearing = true;
264  auto F_skyrme_or_VDF =
265  std::make_pair(ThreeVector(0., 0., 0.), ThreeVector(0., 0., 0.));
266  auto F_symmetry =
267  std::make_pair(ThreeVector(0., 0., 0.), ThreeVector(0., 0., 0.));
268 
269  const auto baryon_density_and_gradient = current_eckart(
270  r, plist, param_, DensityType::Baryon, compute_gradient, smearing);
271  double rhoB = std::get<0>(baryon_density_and_gradient);
272  const ThreeVector grad_j0B = std::get<2>(baryon_density_and_gradient);
273  const ThreeVector curl_vecjB = std::get<3>(baryon_density_and_gradient);
274  const FourVector djmuB_dt = std::get<4>(baryon_density_and_gradient);
275  if (use_skyrme_) {
276  F_skyrme_or_VDF =
277  skyrme_force(rhoB, grad_j0B, djmuB_dt.threevec(), curl_vecjB);
278  }
279 
280  if (use_symmetry_) {
281  const auto density_and_gradient =
283  compute_gradient, smearing);
284  const double rhoI3 = std::get<0>(density_and_gradient);
285  const ThreeVector grad_j0I3 = std::get<2>(density_and_gradient);
286  const ThreeVector curl_vecjI3 = std::get<3>(density_and_gradient);
287  const FourVector dvecjI3_dt = std::get<4>(density_and_gradient);
288  F_symmetry =
289  symmetry_force(rhoI3, grad_j0I3, dvecjI3_dt.threevec(), curl_vecjI3,
290  rhoB, grad_j0B, djmuB_dt.threevec(), curl_vecjB);
291  }
292 
293  if (use_vdf_) {
294  const FourVector jmuB = std::get<1>(baryon_density_and_gradient);
295  const FourVector djmuB_dx = std::get<5>(baryon_density_and_gradient);
296  const FourVector djmuB_dy = std::get<6>(baryon_density_and_gradient);
297  const FourVector djmuB_dz = std::get<7>(baryon_density_and_gradient);
298 
299  // safety check to not divide by zero
300  const int sgn = rhoB > 0 ? 1 : -1;
301  if (std::abs(rhoB) < very_small_double) {
302  rhoB = sgn * very_small_double;
303  }
304 
305  const double drhoB_dt =
306  (1 / rhoB) * (jmuB.x0() * djmuB_dt.x0() - jmuB.x1() * djmuB_dt.x1() -
307  jmuB.x2() * djmuB_dt.x2() - jmuB.x3() * djmuB_dt.x3());
308 
309  const double drhoB_dx =
310  (1 / rhoB) * (jmuB.x0() * djmuB_dx.x0() - jmuB.x1() * djmuB_dx.x1() -
311  jmuB.x2() * djmuB_dx.x2() - jmuB.x3() * djmuB_dx.x3());
312 
313  const double drhoB_dy =
314  (1 / rhoB) * (jmuB.x0() * djmuB_dy.x0() - jmuB.x1() * djmuB_dy.x1() -
315  jmuB.x2() * djmuB_dy.x2() - jmuB.x3() * djmuB_dy.x3());
316 
317  const double drhoB_dz =
318  (1 / rhoB) * (jmuB.x0() * djmuB_dz.x0() - jmuB.x1() * djmuB_dz.x1() -
319  jmuB.x2() * djmuB_dz.x2() - jmuB.x3() * djmuB_dz.x3());
320 
321  const FourVector drhoB_dxnu = {drhoB_dt, drhoB_dx, drhoB_dy, drhoB_dz};
322 
323  const ThreeVector grad_rhoB = drhoB_dxnu.threevec();
324  const ThreeVector vecjB = jmuB.threevec();
325  const ThreeVector Drho_cross_vecj = grad_rhoB.cross_product(vecjB);
326 
327  F_skyrme_or_VDF = vdf_force(
328  rhoB, drhoB_dt, drhoB_dxnu.threevec(), Drho_cross_vecj, jmuB.x0(),
329  grad_j0B, jmuB.threevec(), djmuB_dt.threevec(), curl_vecjB);
330  }
331 
332  return std::make_tuple(F_skyrme_or_VDF.first, F_skyrme_or_VDF.second,
333  F_symmetry.first, F_symmetry.second);
334 }
335 
336 } // namespace smash
Interface to the SMASH configuration files.
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:108
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
double x3() const
Definition: fourvector.h:325
double x2() const
Definition: fourvector.h:321
ThreeVector threevec() const
Definition: fourvector.h:329
double x0() const
Definition: fourvector.h:313
double x1() const
Definition: fourvector.h:317
Particle type contains the static properties of a particle species.
Definition: particletype.h:97
bool is_baryon() const
Definition: particletype.h:203
bool is_nucleus() const
Definition: particletype.h:245
PdgCode pdgcode() const
Definition: particletype.h:156
double isospin3_rel() const
Definition: particletype.h:179
int baryon_number() const
Definition: pdgcode.h:380
bool use_skyrme_
Skyrme potential on/off.
Definition: potentials.h:368
bool use_symmetry_
Symmetry potential on/off.
Definition: potentials.h:371
double skyrme_pot(const double baryon_density) const
Evaluates skyrme potential given a baryon density.
Definition: potentials.cc:61
double symmetry_pot(const double baryon_isospin_density, const double baryon_density) const
Evaluates symmetry potential given baryon isospin density.
Definition: potentials.cc:79
std::pair< ThreeVector, ThreeVector > symmetry_force(const double rhoI3, const ThreeVector grad_j0I3, const ThreeVector dvecjI3_dt, const ThreeVector curl_vecjI3, const double rhoB, const ThreeVector grad_j0B, const ThreeVector dvecjB_dt, const ThreeVector curl_vecjB) const
Evaluates the electric and magnetic components of the symmetry force.
Definition: potentials.cc:171
double potential(const ThreeVector &r, const ParticleList &plist, const ParticleType &acts_on) const
Evaluates potential (Skyrme with optional Symmetry or VDF) at point r.
Definition: potentials.cc:112
FourVector vdf_pot(double rhoB, const FourVector jmuB_net) const
Evaluates the FourVector potential in the VDF model given the rest frame density and the computationa...
Definition: potentials.cc:90
std::vector< double > powers_
Parameters of the VDF potential: exponents .
Definition: potentials.h:424
double dVsym_drhoB(const double rhoB, const double rhoI3) const
Calculate the derivative of the symmetry potential with respect to the net baryon density in GeV * fm...
Definition: potentials.cc:247
double symmetry_S(const double baryon_density) const
Calculate the factor in the symmetry potential.
Definition: potentials.cc:71
double symmetry_S_Pot_
Parameter S_Pot in the symmetry potential in MeV.
Definition: potentials.h:398
double skyrme_a_
Parameter of skyrme potentials: the coefficient in front of in GeV.
Definition: potentials.h:383
std::vector< double > coeffs_
Parameters of the VDF potential: coefficients , in GeV.
Definition: potentials.h:422
std::pair< ThreeVector, ThreeVector > vdf_force(double rhoB, const double drhoB_dt, const ThreeVector grad_rhoB, const ThreeVector gradrhoB_cross_vecjB, const double j0B, const ThreeVector grad_j0B, const ThreeVector vecjB, const ThreeVector dvecjB_dt, const ThreeVector curl_vecjB) const
Evaluates the electric and magnetic components of force in the VDF model given the derivatives of the...
Definition: potentials.cc:186
double skyrme_tau_
Parameters of skyrme potentials: the power index.
Definition: potentials.h:395
Potentials(Configuration conf, const DensityParameters &parameters)
Potentials constructor.
Definition: potentials.cc:17
double dVsym_drhoI3(const double rhoB, const double rhoI3) const
Calculate the derivative of the symmetry potential with respect to the isospin density in GeV * fm^3.
Definition: potentials.cc:237
int number_of_terms() const
Definition: potentials.h:354
static std::pair< double, int > force_scale(const ParticleType &data)
Evaluates the scaling factor of the forces acting on the particles.
Definition: potentials.cc:145
std::pair< ThreeVector, ThreeVector > skyrme_force(const double rhoB, const ThreeVector grad_j0B, const ThreeVector dvecjB_dt, const ThreeVector curl_vecjB) const
Evaluates the electric and magnetic components of the skyrme force.
Definition: potentials.cc:153
virtual std::tuple< ThreeVector, ThreeVector, ThreeVector, ThreeVector > all_forces(const ThreeVector &r, const ParticleList &plist) const
Evaluates the electric and magnetic components of the forces at point r.
Definition: potentials.cc:261
double symmetry_gamma_
Power in formula for :
Definition: potentials.h:411
bool symmetry_is_rhoB_dependent_
Whether the baryon density dependence of the symmetry potential is included.
Definition: potentials.h:404
const DensityParameters param_
Struct that contains the gaussian smearing width , the distance cutoff and the testparticle number n...
Definition: potentials.h:365
bool use_vdf_
VDF potential on/off.
Definition: potentials.h:377
double saturation_density_
Saturation density of nuclear matter used in the VDF potential; it may vary between different paramet...
Definition: potentials.h:420
virtual ~Potentials()
Standard destructor.
Definition: potentials.cc:59
double skyrme_b_
Parameters of skyrme potentials: the coefficient in front of in GeV.
Definition: potentials.h:389
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
ThreeVector cross_product(const ThreeVector &b) const
Definition: threevector.h:246
Collection of useful constants that are known at compile time.
int sgn(T val)
Signum function.
Definition: random.h:190
Definition: action.h:24
constexpr double mev_to_gev
MeV to GeV conversion factor.
Definition: constants.h:34
std::tuple< double, FourVector, ThreeVector, ThreeVector, FourVector, FourVector, FourVector, FourVector > current_eckart(const ThreeVector &r, const ParticleList &plist, const DensityParameters &par, DensityType dens_type, bool compute_gradient, bool smearing)
Calculates Eckart rest frame density and 4-current of a given density type and optionally the gradien...
Definition: density.cc:171
constexpr double very_small_double
A very small double, used to avoid division by zero.
Definition: constants.h:40
constexpr double nuclear_density
Ground state density of symmetric nuclear matter [fm^-3].
Definition: constants.h:48