Version: SMASH-3.1
potentials.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2015,2017-2024
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 #include "smash/input_keys.h"
15 
16 namespace smash {
17 
19  : param_(param),
20  use_skyrme_(conf.has_value({"Skyrme"})),
21  use_symmetry_(conf.has_value({"Symmetry"})),
22  use_coulomb_(conf.has_value({"Coulomb"})),
23  use_vdf_(conf.has_value({"VDF"})),
24  use_momentum_dependence_(conf.has_value({"Momentum_Dependence"})),
25  use_potentials_outside_lattice_(
26  conf.take({"Use_Potentials_Outside_Lattice"},
28  .default_value())) {
29  if (use_skyrme_) {
30  skyrme_a_ = conf.take({"Skyrme", "Skyrme_A"});
31  skyrme_b_ = conf.take({"Skyrme", "Skyrme_B"});
32  skyrme_tau_ = conf.take({"Skyrme", "Skyrme_Tau"});
33  }
34  if (use_momentum_dependence_) {
35  mom_dependence_Lambda_ = conf.take({"Momentum_Dependence", "Lambda"});
36  mom_dependence_C_ = conf.take({"Momentum_Dependence", "C"});
37  }
38 
39  if (use_symmetry_) {
40  symmetry_S_Pot_ = conf.take({"Symmetry", "S_Pot"});
41  if (conf.has_value({"Symmetry", "gamma"})) {
42  symmetry_gamma_ = conf.take({"Symmetry", "gamma"});
43  symmetry_is_rhoB_dependent_ = true;
44  }
45  }
46  if (use_coulomb_) {
47  coulomb_r_cut_ = conf.take({"Coulomb", "R_Cut"});
48  }
49  if (use_vdf_) {
50  saturation_density_ = conf.take({"VDF", "Sat_rhoB"});
51  std::vector<double> aux_coeffs = conf.take({"VDF", "Coeffs"});
52  std::vector<double> aux_powers = conf.take({"VDF", "Powers"});
53  if (aux_coeffs.size() != aux_powers.size()) {
54  throw std::invalid_argument(
55  "The number of coefficients should equal the number of powers.");
56  }
57  const int n_terms = aux_powers.size();
58  for (int i = 0; i < n_terms; i++) {
59  if (aux_powers[i] < 0.0) {
60  throw std::invalid_argument("Powers need to be positive real numbers.");
61  }
62  // coefficients are provided in MeV, but the code uses GeV
63  coeffs_.push_back(aux_coeffs[i] * mev_to_gev);
64  powers_.push_back(aux_powers[i]);
65  }
66  }
67 }
68 
70 
71 double Potentials::skyrme_pot(const double baryon_density, const double A,
72  const double B, const double tau) {
73  const double tmp = baryon_density / nuclear_density;
74  /* U = U(|rho|) * sgn , because the sign of the potential changes
75  * under a charge reversal transformation. */
76  const int sgn = tmp > 0 ? 1 : -1;
77  // Return in GeV
78  return mev_to_gev * sgn *
79  (A * std::abs(tmp) + B * std::pow(std::abs(tmp), tau));
80 }
81 
82 double Potentials::symmetry_S(const double baryon_density) const {
84  return 12.3 * std::pow(baryon_density / nuclear_density, 2. / 3.) +
85  20.0 * std::pow(baryon_density / nuclear_density, symmetry_gamma_);
86  } else {
87  return 0.;
88  }
89 }
90 double Potentials::symmetry_pot(const double baryon_isospin_density,
91  const double baryon_density) const {
92  double pot = mev_to_gev * 2. * symmetry_S_Pot_ * baryon_isospin_density /
95  pot += mev_to_gev * symmetry_S(baryon_density) * baryon_isospin_density *
96  baryon_isospin_density / (baryon_density * baryon_density);
97  }
98  return pot;
99 }
100 
101 FourVector Potentials::vdf_pot(double rhoB, const FourVector jmuB_net) const {
102  // this needs to be used in order to prevent trying to calculate something
103  // like
104  // (-rho_B)^{3.4}
105  const int sgn = rhoB > 0 ? 1 : -1;
106  double abs_rhoB = std::abs(rhoB);
107  // to prevent NAN expressions
108  if (abs_rhoB < very_small_double) {
109  abs_rhoB = very_small_double;
110  }
111  // F_2 is a multiplicative factor in front of the baryon current
112  // in the VDF potential
113  double F_2 = 0.0;
114  for (int i = 0; i < number_of_terms(); i++) {
115  F_2 += coeffs_[i] * std::pow(abs_rhoB, powers_[i] - 2.0) /
116  std::pow(saturation_density_, powers_[i] - 1.0);
117  }
118  F_2 = F_2 * sgn;
119  // Return in GeV
120  return F_2 * jmuB_net;
121 }
122 
123 double Potentials::potential(const ThreeVector &r, const ParticleList &plist,
124  const ParticleType &acts_on) const {
125  double total_potential = 0.0;
126  const bool compute_gradient = false;
127  const bool smearing = true;
128  const auto scale = force_scale(acts_on);
129 
130  if (!(acts_on.is_baryon() || acts_on.is_nucleus())) {
131  return total_potential;
132  }
133  const auto baryon_density_and_gradient = current_eckart(
134  r, plist, param_, DensityType::Baryon, compute_gradient, smearing);
135  const double rhoB = std::get<0>(baryon_density_and_gradient);
136  if (use_skyrme_) {
137  total_potential += scale.first * skyrme_pot(rhoB);
138  }
139  if (use_symmetry_) {
140  const double rho_iso = std::get<0>(
142  compute_gradient, smearing));
143  const double sym_pot = symmetry_pot(rho_iso, rhoB) * acts_on.isospin3_rel();
144  total_potential += scale.second * sym_pot;
145  }
146 
147  if (use_vdf_) {
148  const FourVector jmuB = std::get<1>(baryon_density_and_gradient);
149  const FourVector VDF_potential = vdf_pot(rhoB, jmuB);
150  total_potential += scale.first * VDF_potential.x0();
151  }
152 
153  return total_potential;
154 }
155 
156 std::pair<double, int> Potentials::force_scale(const ParticleType &data) {
157  const auto &pdg = data.pdgcode();
158  const double skyrme_or_VDF_scale =
159  (3 - std::abs(pdg.strangeness())) / 3. * pdg.baryon_number();
160  const int symmetry_scale = pdg.baryon_number();
161  return std::make_pair(skyrme_or_VDF_scale, symmetry_scale);
162 }
163 
164 std::pair<ThreeVector, ThreeVector> Potentials::skyrme_force(
165  const double rhoB, const ThreeVector grad_j0B, const ThreeVector dvecjB_dt,
166  const ThreeVector curl_vecjB) const {
167  ThreeVector E_component(0.0, 0.0, 0.0), B_component(0.0, 0.0, 0.0);
168  if (use_skyrme_) {
169  const int sgn = rhoB > 0 ? 1 : -1;
170  const double abs_rhoB = std::abs(rhoB);
171  const double dV_drho = sgn *
173  std::pow(abs_rhoB / nuclear_density,
174  skyrme_tau_ - 1)) *
176  E_component -= dV_drho * (grad_j0B + dvecjB_dt);
177  B_component += dV_drho * curl_vecjB;
178  }
179  return std::make_pair(E_component, B_component);
180 }
181 
182 std::pair<ThreeVector, ThreeVector> Potentials::symmetry_force(
183  const double rhoI3, const ThreeVector grad_j0I3,
184  const ThreeVector dvecjI3_dt, const ThreeVector curl_vecjI3,
185  const double rhoB, const ThreeVector grad_j0B, const ThreeVector dvecjB_dt,
186  const ThreeVector curl_vecjB) const {
187  ThreeVector E_component(0.0, 0.0, 0.0), B_component(0.0, 0.0, 0.0);
188  if (use_symmetry_) {
189  E_component -= dVsym_drhoI3(rhoB, rhoI3) * (grad_j0I3 + dvecjI3_dt) +
190  dVsym_drhoB(rhoB, rhoI3) * (grad_j0B + dvecjB_dt);
191  B_component += dVsym_drhoI3(rhoB, rhoI3) * curl_vecjI3 +
192  dVsym_drhoB(rhoB, rhoI3) * curl_vecjB;
193  }
194  return std::make_pair(E_component, B_component);
195 }
196 
197 std::pair<ThreeVector, ThreeVector> Potentials::vdf_force(
198  double rhoB, const double drhoB_dt, const ThreeVector grad_rhoB,
199  const ThreeVector gradrhoB_cross_vecjB, const double j0B,
200  const ThreeVector grad_j0B, const ThreeVector vecjB,
201  const ThreeVector dvecjB_dt, const ThreeVector curl_vecjB) const {
202  // this needs to be used to prevent trying to calculate something like
203  // (-rhoB)^{3.4}
204  const int sgn = rhoB > 0 ? 1 : -1;
205  ThreeVector E_component(0.0, 0.0, 0.0), B_component(0.0, 0.0, 0.0);
206  // to prevent NAN expressions
207  double abs_rhoB = std::abs(rhoB);
208  if (abs_rhoB < very_small_double) {
209  abs_rhoB = very_small_double;
210  }
211  if (use_vdf_) {
212  // F_1 and F_2 are multiplicative factors in front of the baryon current
213  // in the VDF potential
214  double F_1 = 0.0;
215  for (int i = 0; i < number_of_terms(); i++) {
216  F_1 += coeffs_[i] * (powers_[i] - 2.0) *
217  std::pow(abs_rhoB, powers_[i] - 3.0) /
218  std::pow(saturation_density_, powers_[i] - 1.0);
219  }
220  F_1 = F_1 * sgn;
221 
222  double F_2 = 0.0;
223  for (int i = 0; i < number_of_terms(); i++) {
224  F_2 += coeffs_[i] * std::pow(abs_rhoB, powers_[i] - 2.0) /
225  std::pow(saturation_density_, powers_[i] - 1.0);
226  }
227  F_2 = F_2 * sgn;
228 
229  E_component -= (F_1 * (grad_rhoB * j0B + drhoB_dt * vecjB) +
230  F_2 * (grad_j0B + dvecjB_dt));
231  B_component += F_1 * gradrhoB_cross_vecjB + F_2 * curl_vecjB;
232  }
233  return std::make_pair(E_component, B_component);
234 }
235 
236 // overload of the above
237 std::pair<ThreeVector, ThreeVector> Potentials::vdf_force(
238  const ThreeVector grad_A_0, const ThreeVector dA_dt,
239  const ThreeVector curl_A) const {
240  ThreeVector E_component(0.0, 0.0, 0.0), B_component(0.0, 0.0, 0.0);
241  if (use_vdf_) {
242  E_component -= (grad_A_0 + dA_dt);
243  B_component += curl_A;
244  }
245  return std::make_pair(E_component, B_component);
246 }
247 
248 double Potentials::dVsym_drhoI3(const double rhoB, const double rhoI3) const {
249  double term1 = 2. * symmetry_S_Pot_ / nuclear_density;
251  double term2 = 2. * rhoI3 * symmetry_S(rhoB) / (rhoB * rhoB);
252  return mev_to_gev * (term1 + term2);
253  } else {
254  return mev_to_gev * term1;
255  }
256 }
257 
258 double Potentials::dVsym_drhoB(const double rhoB, const double rhoI3) const {
260  double rhoB_over_rho0 = rhoB / nuclear_density;
261  double term1 = 8.2 * std::pow(rhoB_over_rho0, -1. / 3.) / nuclear_density +
262  20. * symmetry_gamma_ *
263  std::pow(rhoB_over_rho0, symmetry_gamma_) / rhoB;
264  double term2 = -2. * symmetry_S(rhoB) / rhoB;
265  return mev_to_gev * (term1 + term2) * rhoI3 * rhoI3 / (rhoB * rhoB);
266  } else {
267  return 0.;
268  }
269 }
270 
271 std::tuple<ThreeVector, ThreeVector, ThreeVector, ThreeVector>
272 Potentials::all_forces(const ThreeVector &r, const ParticleList &plist) const {
273  const bool compute_gradient = true;
274  const bool smearing = true;
275  auto F_skyrme_or_VDF =
276  std::make_pair(ThreeVector(0., 0., 0.), ThreeVector(0., 0., 0.));
277  auto F_symmetry =
278  std::make_pair(ThreeVector(0., 0., 0.), ThreeVector(0., 0., 0.));
279 
280  const auto baryon_density_and_gradient = current_eckart(
281  r, plist, param_, DensityType::Baryon, compute_gradient, smearing);
282  double rhoB = std::get<0>(baryon_density_and_gradient);
283  const ThreeVector grad_j0B = std::get<2>(baryon_density_and_gradient);
284  const ThreeVector curl_vecjB = std::get<3>(baryon_density_and_gradient);
285  const FourVector djmuB_dt = std::get<4>(baryon_density_and_gradient);
286  if (use_skyrme_) {
287  F_skyrme_or_VDF =
288  skyrme_force(rhoB, grad_j0B, djmuB_dt.threevec(), curl_vecjB);
289  }
290 
291  if (use_symmetry_) {
292  const auto density_and_gradient =
294  compute_gradient, smearing);
295  const double rhoI3 = std::get<0>(density_and_gradient);
296  const ThreeVector grad_j0I3 = std::get<2>(density_and_gradient);
297  const ThreeVector curl_vecjI3 = std::get<3>(density_and_gradient);
298  const FourVector dvecjI3_dt = std::get<4>(density_and_gradient);
299  F_symmetry =
300  symmetry_force(rhoI3, grad_j0I3, dvecjI3_dt.threevec(), curl_vecjI3,
301  rhoB, grad_j0B, djmuB_dt.threevec(), curl_vecjB);
302  }
303 
304  if (use_vdf_) {
305  const FourVector jmuB = std::get<1>(baryon_density_and_gradient);
306  const FourVector djmuB_dx = std::get<5>(baryon_density_and_gradient);
307  const FourVector djmuB_dy = std::get<6>(baryon_density_and_gradient);
308  const FourVector djmuB_dz = std::get<7>(baryon_density_and_gradient);
309 
310  // safety check to not divide by zero
311  const int sgn = rhoB > 0 ? 1 : -1;
312  if (std::abs(rhoB) < very_small_double) {
313  rhoB = sgn * very_small_double;
314  }
315 
316  const double drhoB_dt =
317  (1 / rhoB) * (jmuB.x0() * djmuB_dt.x0() - jmuB.x1() * djmuB_dt.x1() -
318  jmuB.x2() * djmuB_dt.x2() - jmuB.x3() * djmuB_dt.x3());
319 
320  const double drhoB_dx =
321  (1 / rhoB) * (jmuB.x0() * djmuB_dx.x0() - jmuB.x1() * djmuB_dx.x1() -
322  jmuB.x2() * djmuB_dx.x2() - jmuB.x3() * djmuB_dx.x3());
323 
324  const double drhoB_dy =
325  (1 / rhoB) * (jmuB.x0() * djmuB_dy.x0() - jmuB.x1() * djmuB_dy.x1() -
326  jmuB.x2() * djmuB_dy.x2() - jmuB.x3() * djmuB_dy.x3());
327 
328  const double drhoB_dz =
329  (1 / rhoB) * (jmuB.x0() * djmuB_dz.x0() - jmuB.x1() * djmuB_dz.x1() -
330  jmuB.x2() * djmuB_dz.x2() - jmuB.x3() * djmuB_dz.x3());
331 
332  const FourVector drhoB_dxnu = {drhoB_dt, drhoB_dx, drhoB_dy, drhoB_dz};
333 
334  const ThreeVector grad_rhoB = drhoB_dxnu.threevec();
335  const ThreeVector vecjB = jmuB.threevec();
336  const ThreeVector Drho_cross_vecj = grad_rhoB.cross_product(vecjB);
337 
338  F_skyrme_or_VDF = vdf_force(
339  rhoB, drhoB_dt, drhoB_dxnu.threevec(), Drho_cross_vecj, jmuB.x0(),
340  grad_j0B, jmuB.threevec(), djmuB_dt.threevec(), curl_vecjB);
341  }
342 
343  return std::make_tuple(F_skyrme_or_VDF.first, F_skyrme_or_VDF.second,
344  F_symmetry.first, F_symmetry.second);
345 }
346 
347 } // 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
default_type default_value() const
Get the default value of the key.
Definition: input_keys.h:132
Particle type contains the static properties of a particle species.
Definition: particletype.h:98
bool is_baryon() const
Definition: particletype.h:204
bool is_nucleus() const
Definition: particletype.h:249
PdgCode pdgcode() const
Definition: particletype.h:157
double isospin3_rel() const
Definition: particletype.h:180
int baryon_number() const
Definition: pdgcode.h:381
bool use_skyrme_
Skyrme potential on/off.
Definition: potentials.h:483
bool use_symmetry_
Symmetry potential on/off.
Definition: potentials.h:486
double skyrme_pot(const double baryon_density) const
Evaluates Skyrme potential given a baryon density.
Definition: potentials.h:157
double symmetry_pot(const double baryon_isospin_density, const double baryon_density) const
Evaluates symmetry potential given baryon isospin density.
Definition: potentials.cc:90
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:182
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:123
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:101
std::vector< double > powers_
Parameters of the VDF potential: exponents .
Definition: potentials.h:557
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:258
double symmetry_S(const double baryon_density) const
Calculate the factor in the symmetry potential.
Definition: potentials.cc:82
double symmetry_S_Pot_
Parameter S_Pot in the symmetry potential in MeV.
Definition: potentials.h:528
double skyrme_a_
Parameter of skyrme potentials: the coefficient in front of in GeV.
Definition: potentials.h:501
std::vector< double > coeffs_
Parameters of the VDF potential: coefficients , in GeV.
Definition: potentials.h:555
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:197
double skyrme_tau_
Parameters of skyrme potentials: the power index.
Definition: potentials.h:513
Potentials(Configuration conf, const DensityParameters &parameters)
Potentials constructor.
Definition: potentials.cc:18
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:248
int number_of_terms() const
Definition: potentials.h:461
static std::pair< double, int > force_scale(const ParticleType &data)
Evaluates the scaling factor of the forces acting on the particles.
Definition: potentials.cc:156
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:164
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:272
double symmetry_gamma_
Power in formula for :
Definition: potentials.h:541
bool symmetry_is_rhoB_dependent_
Whether the baryon density dependence of the symmetry potential is included.
Definition: potentials.h:534
const DensityParameters param_
Struct that contains the gaussian smearing width , the distance cutoff and the testparticle number n...
Definition: potentials.h:480
bool use_vdf_
VDF potential on/off.
Definition: potentials.h:492
double saturation_density_
Saturation density of nuclear matter used in the VDF potential; it may vary between different paramet...
Definition: potentials.h:553
virtual ~Potentials()
Standard destructor.
Definition: potentials.cc:69
double skyrme_b_
Parameters of skyrme potentials: the coefficient in front of in GeV.
Definition: potentials.h:507
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
static const Key< bool > potentials_use_potentials_outside_lattice
See user guide description for more information.
Definition: input_keys.h:4936