Version: SMASH-1.5
smash::HadronGasEos Class Reference

#include <hadgas_eos.h>

Class to handle the equation of state (EoS) of the hadron gas, consisting of all hadrons included into SMASH.

This implementation deals with ideal Boltzmann gas and allows to compute:

  • energy density \(\epsilon\), pressure \(p\), density \(n\), net baryon density \(n_B\) and net strangeness \(n_S\) as a function of temperature \(T\), baryon chemical potential \(\mu_B\) and strange chemical potential \(\mu_S\).
  • Temperature and chemical potentials given energy-, net baryon- and net strangeness density. This requires solving a system of nonlinear equations.

Definition at line 112 of file hadgas_eos.h.

Collaboration diagram for smash::HadronGasEos:
[legend]

Classes

struct  eparams
 Another structure for passing energy density to the gnu library. More...
 
struct  rparams
 A structure for passing equation parameters to the gnu library. More...
 

Public Member Functions

 HadronGasEos (const bool tabulate=false)
 Constructor of HadronGasEos. More...
 
 ~HadronGasEos ()
 
std::array< double, 3 > solve_eos (double e, double nb, double ns, std::array< double, 3 > initial_approximation)
 Compute temperature and chemical potentials given energy-, net baryon-, net strangeness density and an inital approximation. More...
 
std::array< double, 3 > solve_eos (double e, double nb, double ns)
 Compute temperature and chemical potentials given energy-, net baryon- and net strangeness density without an inital approximation. More...
 
std::array< double, 3 > solve_eos_initial_approximation (double e, double nb)
 Compute a reasonable initial approximation for solve_eos. More...
 
void from_table (EosTable::table_element &res, double e, double nb) const
 Get the element of eos table. More...
 
bool is_tabulated () const
 Create an EoS table or not? More...
 

Static Public Member Functions

static double energy_density (double T, double mub, double mus)
 Compute energy density. More...
 
static double density (double T, double mub, double mus)
 Compute particle number density. More...
 
static double pressure (double T, double mub, double mus)
 Compute pressure \( p = n T \). More...
 
static double net_baryon_density (double T, double mub, double mus)
 Compute net baryon density. More...
 
static double net_strange_density (double T, double mub, double mus)
 Compute net strangeness density. More...
 
static double partial_density (const ParticleType &ptype, double T, double mub, double mus)
 Compute partial density of one hadron sort. More...
 
static double sample_mass_thermal (const ParticleType &ptype, double beta)
 Sample resonance mass in a thermal medium. More...
 
static double mus_net_strangeness0 (double T, double mub)
 Compute strangeness chemical potential, requiring that net strangeness = 0. More...
 
static bool is_eos_particle (const ParticleType &ptype)
 Check if a particle belongs to the EoS. More...
 

Private Member Functions

std::string print_solver_state (size_t iter) const
 Helpful printout, useful for debugging if gnu equation solving goes crazy. More...
 

Static Private Member Functions

static double scaled_partial_density_auxiliary (double m_over_T, double mu_over_T)
 Function used to avoid duplications in density calculations. More...
 
static double scaled_partial_density (const ParticleType &ptype, double beta, double mub, double mus)
 Compute (unnormalized) density of one hadron sort - helper functions used to reduce code duplication. More...
 
static int set_eos_solver_equations (const gsl_vector *x, void *params, gsl_vector *f)
 Interface EoS equations to be solved to gnu library. More...
 
static double e_equation (double T, void *params)
 

Private Attributes

EosTable eos_table_ = EosTable(1.e-2, 1.e-2, 900, 900)
 EOS Table to be used. More...
 
gsl_vector * x_
 Variables used by gnu equation solver. More...
 
gsl_multiroot_fsolver * solver_
 
const bool tabulate_
 Create an EoS table or not? More...
 

Static Private Attributes

static constexpr double prefactor_
 Constant factor, that appears in front of many thermodyn. expressions. More...
 
static constexpr double tolerance_ = 1.e-8
 Precision of equation solving. More...
 
static constexpr size_t n_equations_ = 3
 Number of equations in the system of equations to be solved. More...
 

Constructor & Destructor Documentation

◆ HadronGasEos()

smash::HadronGasEos::HadronGasEos ( const bool  tabulate = false)
explicit

Constructor of HadronGasEos.

Definition at line 158 of file hadgas_eos.cc.

159  : x_(gsl_vector_alloc(n_equations_)), tabulate_(tabulate) {
160  const gsl_multiroot_fsolver_type *solver_type;
161  solver_type = gsl_multiroot_fsolver_hybrid;
162  solver_ = gsl_multiroot_fsolver_alloc(solver_type, n_equations_);
163  if (tabulate_) {
164  eos_table_.compile_table(*this);
165  }
166 }
void compile_table(HadronGasEos &eos, const std::string &eos_savefile_name="hadgas_eos.dat")
Computes the actual content of the table (for EosTable description see documentation of the construct...
Definition: hadgas_eos.cc:34
static constexpr size_t n_equations_
Number of equations in the system of equations to be solved.
Definition: hadgas_eos.h:346
EosTable eos_table_
EOS Table to be used.
Definition: hadgas_eos.h:349
gsl_multiroot_fsolver * solver_
Definition: hadgas_eos.h:360
gsl_vector * x_
Variables used by gnu equation solver.
Definition: hadgas_eos.h:357
const bool tabulate_
Create an EoS table or not?
Definition: hadgas_eos.h:363
Here is the call graph for this function:

◆ ~HadronGasEos()

smash::HadronGasEos::~HadronGasEos ( )

Definition at line 168 of file hadgas_eos.cc.

168  {
169  gsl_multiroot_fsolver_free(solver_);
170  gsl_vector_free(x_);
171 }
gsl_multiroot_fsolver * solver_
Definition: hadgas_eos.h:360
gsl_vector * x_
Variables used by gnu equation solver.
Definition: hadgas_eos.h:357

Member Function Documentation

◆ energy_density()

double smash::HadronGasEos::energy_density ( double  T,
double  mub,
double  mus 
)
static

Compute energy density.

Grand-canonical Boltzmann ideal gas, consisting of all hadrons in SMASH:

\[ \epsilon = \sum \frac{g_i m_i^2 T^2}{2\pi^2(\hbar c)^3} exp \left(\frac{\mu_B B_i + \mu_S S_i}{T} \right) \times \left[ 3 K_2\left( \frac{m_i}{T}\right) + \frac{m_i}{T} K_1\left( \frac{m_i}{T}\right)\right] \]

Parameters
[in]Ttemperature [GeV]
[in]mubbaryon chemical potential [GeV]
[in]musstrangeness chemical potential [GeV]
Returns
energy density e [GeV/fm \(^3\)]

Definition at line 228 of file hadgas_eos.cc.

228  {
229  if (T < really_small) {
230  return 0.0;
231  }
232  const double beta = 1.0 / T;
233  double e = 0.0;
234  for (const ParticleType &ptype : ParticleType::list_all()) {
235  if (!is_eos_particle(ptype)) {
236  continue;
237  }
238  const double z = ptype.mass() * beta;
239  double x = beta * (mub * ptype.baryon_number() + mus * ptype.strangeness() -
240  ptype.mass());
241  if (x < -500.0) {
242  return 0.0;
243  }
244  x = std::exp(x);
245  const size_t g = ptype.spin() + 1;
246  // Small mass case, z*z*K_2(z) -> 2, z*z*z*K_1(z) -> 0 at z->0
247  e += (z < really_small) ? 3.0 * g * x
248  : z * z * g * x *
249  (3.0 * gsl_sf_bessel_Kn_scaled(2, z) +
250  z * gsl_sf_bessel_K1_scaled(z));
251  }
252  e *= prefactor_ * T * T * T * T;
253  return e;
254 }
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:277
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:339
static const ParticleTypeList & list_all()
Definition: particletype.cc:55
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:326
Here is the call graph for this function:
Here is the caller graph for this function:

◆ density()

double smash::HadronGasEos::density ( double  T,
double  mub,
double  mus 
)
static

Compute particle number density.

Grand-canonical Boltzmann ideal gas, consisting of all hadrons in SMASH:

\[ n = \sum \frac{g_i m_i^2 T}{2\pi^2(\hbar c)^3} exp \left(\frac{\mu_B B_i + \mu_S S_i}{T} \right) K_2\left( \frac{m_i}{T}\right) \]

Parameters
[in]Ttemperature [GeV]
[in]mubbaryon chemical potential [GeV]
[in]musstrangeness chemical potential [GeV]
Returns
particle number density n [fm \(^{-3}\)]

Definition at line 256 of file hadgas_eos.cc.

256  {
257  if (T < really_small) {
258  return 0.0;
259  }
260  const double beta = 1.0 / T;
261  double rho = 0.0;
262  for (const ParticleType &ptype : ParticleType::list_all()) {
263  if (!is_eos_particle(ptype)) {
264  continue;
265  }
266  rho += scaled_partial_density(ptype, beta, mub, mus);
267  }
268  rho *= prefactor_ * T * T * T;
269  return rho;
270 }
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
static double scaled_partial_density(const ParticleType &ptype, double beta, double mub, double mus)
Compute (unnormalized) density of one hadron sort - helper functions used to reduce code duplication...
Definition: hadgas_eos.cc:187
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:277
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:339
static const ParticleTypeList & list_all()
Definition: particletype.cc:55
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:326
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pressure()

static double smash::HadronGasEos::pressure ( double  T,
double  mub,
double  mus 
)
inlinestatic

Compute pressure \( p = n T \).

Parameters
[in]Ttemperature [GeV]
[in]mubbaryon chemical potential [GeV]
[in]musstrangeness chemical potential [GeV]
Returns
pressure p [GeV/fm \(^{-3}\)]

Definition at line 159 of file hadgas_eos.h.

159  {
160  return T * density(T, mub, mus);
161  }
static double density(double T, double mub, double mus)
Compute particle number density.
Definition: hadgas_eos.cc:256
Here is the call graph for this function:
Here is the caller graph for this function:

◆ net_baryon_density()

double smash::HadronGasEos::net_baryon_density ( double  T,
double  mub,
double  mus 
)
static

Compute net baryon density.

Grand-canonical Boltzmann ideal gas, consisting of all hadrons in SMASH:

\[ n_B = \sum B_i \frac{g_i m_i^2 T}{2\pi^2(\hbar c)^3} exp \left(\frac{\mu_B B_i + \mu_S S_i}{T} \right) K_2\left( \frac{m_i}{T}\right) \]

Parameters
[in]Ttemperature [GeV]
[in]mubbaryon chemical potential [GeV]
[in]musstrangeness chemical potential [GeV]
Returns
net baryon density density \(n_B\) [fm \(^{-3}\)]

Definition at line 272 of file hadgas_eos.cc.

272  {
273  if (T < really_small) {
274  return 0.0;
275  }
276  const double beta = 1.0 / T;
277  double rho = 0.0;
278  for (const ParticleType &ptype : ParticleType::list_all()) {
279  if (!ptype.is_baryon() || !is_eos_particle(ptype)) {
280  continue;
281  }
282  rho +=
283  scaled_partial_density(ptype, beta, mub, mus) * ptype.baryon_number();
284  }
285  rho *= prefactor_ * T * T * T;
286  return rho;
287 }
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
static double scaled_partial_density(const ParticleType &ptype, double beta, double mub, double mus)
Compute (unnormalized) density of one hadron sort - helper functions used to reduce code duplication...
Definition: hadgas_eos.cc:187
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:277
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:339
static const ParticleTypeList & list_all()
Definition: particletype.cc:55
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:326
Here is the call graph for this function:
Here is the caller graph for this function:

◆ net_strange_density()

double smash::HadronGasEos::net_strange_density ( double  T,
double  mub,
double  mus 
)
static

Compute net strangeness density.

Grand-canonical Boltzmann ideal gas, consisting of all hadrons in SMASH:

\[ n_S = \sum S_i \frac{g_i m_i^2 T}{2\pi^2(\hbar c)^3} exp \left(\frac{\mu_B B_i + \mu_S S_i}{T} \right) K_2\left( \frac{m_i}{T}\right) \]

Parameters
[in]Ttemperature [GeV]
[in]mubbaryon chemical potential [GeV]
[in]musstrangeness chemical potential [GeV]
Returns
net strangeness density density \(n_S\) [fm \(^{-3}\)]

Definition at line 289 of file hadgas_eos.cc.

289  {
290  if (T < really_small) {
291  return 0.0;
292  }
293  const double beta = 1.0 / T;
294  double rho = 0.0;
295  for (const ParticleType &ptype : ParticleType::list_all()) {
296  if (ptype.strangeness() == 0 || !is_eos_particle(ptype)) {
297  continue;
298  }
299  rho += scaled_partial_density(ptype, beta, mub, mus) * ptype.strangeness();
300  }
301  rho *= prefactor_ * T * T * T;
302  return rho;
303 }
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
static double scaled_partial_density(const ParticleType &ptype, double beta, double mub, double mus)
Compute (unnormalized) density of one hadron sort - helper functions used to reduce code duplication...
Definition: hadgas_eos.cc:187
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:277
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:339
static const ParticleTypeList & list_all()
Definition: particletype.cc:55
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:326
Here is the call graph for this function:
Here is the caller graph for this function:

◆ partial_density()

double smash::HadronGasEos::partial_density ( const ParticleType ptype,
double  T,
double  mub,
double  mus 
)
static

Compute partial density of one hadron sort.

Grand-canonical Boltzmann ideal gas:

\[ n = \frac{g m^2 T}{2\pi^2(\hbar c)^3} exp \left(\frac{\mu_B B + \mu_S S}{T} \right) K_2\left( \frac{m}{T}\right) \]

Parameters
[in]ptypethe hadron sort, for which partial density is computed
[in]Ttemperature [GeV]
[in]mubbaryon chemical potential [GeV]
[in]musstrangeness chemical potential [GeV]
Returns
partial density of the given hadron sort \(n\) [fm \(^{-3}\)]

Definition at line 219 of file hadgas_eos.cc.

220  {
221  if (T < really_small) {
222  return 0.0;
223  }
224  return prefactor_ * T * T * T *
225  scaled_partial_density(ptype, 1.0 / T, mub, mus);
226 }
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
static double scaled_partial_density(const ParticleType &ptype, double beta, double mub, double mus)
Compute (unnormalized) density of one hadron sort - helper functions used to reduce code duplication...
Definition: hadgas_eos.cc:187
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:339
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sample_mass_thermal()

double smash::HadronGasEos::sample_mass_thermal ( const ParticleType ptype,
double  beta 
)
static

Sample resonance mass in a thermal medium.

Samples mass from the distribution

\[ dN/dm \sim A(m) m^2 K_2\left( \frac{m}{T}\right) \]

For stable particles always returns pole mass.

Parameters
[in]ptypethe hadron sort, for which mass is sampled
[in]betainverse temperature 1/T [1/GeV]
Returns
sampled mass

Definition at line 305 of file hadgas_eos.cc.

306  {
307  if (ptype.is_stable()) {
308  return ptype.mass();
309  }
310  // Sampling mass m from A(m) x^2 BesselK_2(x), where x = beta m.
311  // Strategy employs the idea of importance sampling:
312  // -- Sample mass from the simple Breit-Wigner first, then
313  // reject by the ratio.
314  // -- Note that f(x) = x^2 BesselK_2(x) monotonously decreases
315  // and has maximum at x = xmin. That is why instead of f(x)
316  // the ratio f(x)/f(xmin) is used.
317 
318  const double max_mass = 5.0; // GeV
319  double m, q;
320  {
321  // Allow underflows in exponentials
322  DisableFloatTraps guard(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
323  const double w0 = ptype.width_at_pole();
324  const double mth = ptype.min_mass_spectral();
325  const double m0 = ptype.mass();
326  double max_ratio =
327  m0 * m0 * std::exp(-beta * m0) * gsl_sf_bessel_Kn_scaled(2, m0 * beta) *
328  ptype.spectral_function(m0) / ptype.spectral_function_simple(m0);
329  // Heuristic adaptive maximum search to find max_ratio
330  constexpr int npoints = 31;
331  double m_lower = mth, m_upper = max_mass, m_where_max = m0;
332 
333  for (size_t n_iterations = 0; n_iterations < 2; n_iterations++) {
334  const double dm = (m_upper - m_lower) / npoints;
335  for (size_t i = 1; i < npoints; i++) {
336  m = m_lower + dm * i;
337  const double thermal_factor =
338  m * m * std::exp(-beta * m) * gsl_sf_bessel_Kn_scaled(2, m * beta);
339  q = ptype.spectral_function(m) * thermal_factor /
340  ptype.spectral_function_simple(m);
341  if (q > max_ratio) {
342  max_ratio = q;
343  m_where_max = m;
344  }
345  }
346  m_lower = m_where_max - (m_where_max - m_lower) * 0.1;
347  m_upper = m_where_max + (m_upper - m_where_max) * 0.1;
348  }
349  // Safety factor
350  max_ratio *= 1.5;
351 
352  do {
353  // sample mass from A(m)
354  do {
355  m = random::cauchy(m0, 0.5 * w0, mth, max_mass);
356  const double thermal_factor =
357  m * m * std::exp(-beta * m) * gsl_sf_bessel_Kn_scaled(2, m * beta);
358  q = ptype.spectral_function(m) * thermal_factor /
359  ptype.spectral_function_simple(m);
360  } while (q < random::uniform(0., max_ratio));
361  if (q > max_ratio) {
362  const auto &log = logger<LogArea::Resonances>();
363  log.warn(ptype.name(), " - maximum increased in",
364  " sample_mass_thermal from ", max_ratio, " to ", q,
365  ", mass = ", m,
366  " previously assumed maximum at m = ", m_where_max);
367  max_ratio = q;
368  m_where_max = m;
369  } else {
370  break;
371  }
372  } while (true);
373  }
374  return m;
375 }
T uniform(T min, T max)
Definition: random.h:85
T cauchy(T pole, T width, T min, T max)
Draws a random number from a Cauchy distribution (sometimes also called Lorentz or non-relativistic B...
Definition: random.h:304
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:326
Here is the call graph for this function:
Here is the caller graph for this function:

◆ solve_eos() [1/2]

std::array< double, 3 > smash::HadronGasEos::solve_eos ( double  e,
double  nb,
double  ns,
std::array< double, 3 >  initial_approximation 
)

Compute temperature and chemical potentials given energy-, net baryon-, net strangeness density and an inital approximation.

Parameters
[in]eenergy density [GeV/fm \(^3\)]
[in]nbnet baryon density [fm \(^{-3}\)]
[in]nsnet strangeness density [fm \(^{-3}\)]
[in]initial_approximation(T [GeV], mub [GeV], mus [GeV]) to use as starting point
Returns
array of 3 values: temperature, baryon chemical potential and strange chemical potential

Definition at line 486 of file hadgas_eos.cc.

488  {
489  int residual_status = GSL_SUCCESS;
490  size_t iter = 0;
491 
492  struct rparams p = {e, nb, ns};
493  gsl_multiroot_function f = {&HadronGasEos::set_eos_solver_equations,
494  n_equations_, &p};
495 
496  gsl_vector_set(x_, 0, initial_approximation[0]);
497  gsl_vector_set(x_, 1, initial_approximation[1]);
498  gsl_vector_set(x_, 2, initial_approximation[2]);
499 
500  gsl_multiroot_fsolver_set(solver_, &f, x_);
501  do {
502  iter++;
503  const auto iterate_status = gsl_multiroot_fsolver_iterate(solver_);
504  // std::cout << print_solver_state(iter);
505 
506  // Avoiding too low temperature
507  if (gsl_vector_get(solver_->x, 0) < 0.015) {
508  return {0.0, 0.0, 0.0};
509  }
510 
511  // check if solver is stuck
512  if (iterate_status) {
513  break;
514  }
515  residual_status = gsl_multiroot_test_residual(solver_->f, tolerance_);
516  } while (residual_status == GSL_CONTINUE && iter < 1000);
517 
518  if (residual_status != GSL_SUCCESS) {
519  std::stringstream solver_parameters;
520  solver_parameters << "Solver run with "
521  << "e = " << e << ", nb = " << nb << ", ns = " << ns
522  << ", init. approx.: " << initial_approximation[0] << " "
523  << initial_approximation[1] << " "
524  << initial_approximation[2] << std::endl;
525  throw std::runtime_error(gsl_strerror(residual_status) +
526  solver_parameters.str() +
527  print_solver_state(iter));
528  }
529 
530  return {gsl_vector_get(solver_->x, 0), gsl_vector_get(solver_->x, 1),
531  gsl_vector_get(solver_->x, 2)};
532 }
std::string print_solver_state(size_t iter) const
Helpful printout, useful for debugging if gnu equation solving goes crazy.
Definition: hadgas_eos.cc:534
static int set_eos_solver_equations(const gsl_vector *x, void *params, gsl_vector *f)
Interface EoS equations to be solved to gnu library.
Definition: hadgas_eos.cc:401
static constexpr size_t n_equations_
Number of equations in the system of equations to be solved.
Definition: hadgas_eos.h:346
static constexpr double tolerance_
Precision of equation solving.
Definition: hadgas_eos.h:343
gsl_multiroot_fsolver * solver_
Definition: hadgas_eos.h:360
gsl_vector * x_
Variables used by gnu equation solver.
Definition: hadgas_eos.h:357
constexpr int p
Proton.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ solve_eos() [2/2]

std::array<double, 3> smash::HadronGasEos::solve_eos ( double  e,
double  nb,
double  ns 
)
inline

Compute temperature and chemical potentials given energy-, net baryon- and net strangeness density without an inital approximation.

Parameters
[in]eenergy density [GeV/fm \(^3\)]
[in]nbnet baryon density [fm \(^{-3}\)]
[in]nsnet strangeness density [fm \(^{-3}\)]
Returns
array of 3 values: temperature, baryon chemical potential and strange chemical potential

Definition at line 248 of file hadgas_eos.h.

248  {
249  return solve_eos(e, nb, ns, solve_eos_initial_approximation(e, nb));
250  }
std::array< double, 3 > solve_eos(double e, double nb, double ns, std::array< double, 3 > initial_approximation)
Compute temperature and chemical potentials given energy-, net baryon-, net strangeness density and a...
Definition: hadgas_eos.cc:486
std::array< double, 3 > solve_eos_initial_approximation(double e, double nb)
Compute a reasonable initial approximation for solve_eos.
Definition: hadgas_eos.cc:423
Here is the call graph for this function:

◆ solve_eos_initial_approximation()

std::array< double, 3 > smash::HadronGasEos::solve_eos_initial_approximation ( double  e,
double  nb 
)

Compute a reasonable initial approximation for solve_eos.

Parameters
[in]eenergy density [GeV/fm \(^3\)]
[in]nbnet baryon density [fm \(^{-3}\)]
Returns
array of 3 values: temperature, baryon chemical potential and strange chemical potential

Definition at line 423 of file hadgas_eos.cc.

424  {
425  assert(e >= 0.0);
426  // 1. Get temperature from energy density assuming zero chemical potentials
427  int degeneracies_sum = 0.0;
428  for (const ParticleType &ptype : ParticleType::list_all()) {
429  if (is_eos_particle(ptype)) {
430  degeneracies_sum += ptype.spin() + 1;
431  }
432  }
433  // Temperature in case of massless gas. For massive it should be larger.
434  const double T_min = std::pow(e / prefactor_ / 6 / degeneracies_sum, 1. / 4.);
435  // Simply assume that the temperature is not higher than 2 GeV.
436  const double T_max = 2.0;
437 
438  struct eparams parameters = {e};
439  gsl_function F = {&e_equation, &parameters};
440  const gsl_root_fsolver_type *T = gsl_root_fsolver_brent;
441  gsl_root_fsolver *e_solver;
442  e_solver = gsl_root_fsolver_alloc(T);
443  gsl_root_fsolver_set(e_solver, &F, T_min, T_max);
444 
445  int iter = 0, status, max_iter = 100;
446  double T_init = 0.0;
447 
448  do {
449  iter++;
450  status = gsl_root_fsolver_iterate(e_solver);
451  if (status != GSL_SUCCESS) {
452  break;
453  }
454  T_init = gsl_root_fsolver_root(e_solver);
455  double x_lo = gsl_root_fsolver_x_lower(e_solver);
456  double x_hi = gsl_root_fsolver_x_upper(e_solver);
457  status = gsl_root_test_interval(x_lo, x_hi, 0.0, 0.001);
458  } while (status == GSL_CONTINUE && iter < max_iter);
459 
460  if (status != GSL_SUCCESS) {
461  std::stringstream err_msg;
462  err_msg << "Solver of equation for temperature with e = " << e
463  << " failed to converge. Maybe Tmax = " << T_max << " is too small?"
464  << std::endl;
465  throw std::runtime_error(gsl_strerror(status) + err_msg.str());
466  }
467 
468  gsl_root_fsolver_free(e_solver);
469 
470  // 2. Get the baryon chemical potential for mus = 0 and previously obtained T
471  double n_only_baryons = 0.0;
472  for (const ParticleType &ptype : ParticleType::list_all()) {
473  if (is_eos_particle(ptype) && ptype.baryon_number() == 1) {
474  n_only_baryons += scaled_partial_density(ptype, 1.0 / T_init, 0.0, 0.0);
475  }
476  }
477  const double nb_scaled = nb / prefactor_ / (T_init * T_init * T_init);
478  double mub_init = T_init * std::asinh(nb_scaled / n_only_baryons / 2.0);
479 
480  // 3. mus = 0 is typically a good initial approximation
481 
482  std::array<double, 3> initial_approximation = {T_init, mub_init, 0.0};
483  return initial_approximation;
484 }
static double scaled_partial_density(const ParticleType &ptype, double beta, double mub, double mus)
Compute (unnormalized) density of one hadron sort - helper functions used to reduce code duplication...
Definition: hadgas_eos.cc:187
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:277
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:339
static const ParticleTypeList & list_all()
Definition: particletype.cc:55
static double e_equation(double T, void *params)
Definition: hadgas_eos.cc:418
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mus_net_strangeness0()

double smash::HadronGasEos::mus_net_strangeness0 ( double  T,
double  mub 
)
static

Compute strangeness chemical potential, requiring that net strangeness = 0.

Parameters
[in]mubbaryon chemical potential [GeV]
[in]Ttemperature [GeV]
Returns
strangeness chemical potential [GeV]

Definition at line 377 of file hadgas_eos.cc.

377  {
378  // Binary search
379  double mus_u = mub + T;
380  double mus_l = 0.0;
381  double mus, rhos;
382  size_t iteration = 0;
383  // 50 iterations should give precision 2^-50 ~ 10^-15
384  const size_t max_iteration = 50;
385  do {
386  mus = 0.5 * (mus_u + mus_l);
387  rhos = net_strange_density(T, mub, mus);
388  if (rhos > 0.0) {
389  mus_u = mus;
390  } else {
391  mus_l = mus;
392  }
393  iteration++;
394  } while (std::abs(rhos) > tolerance_ && iteration < max_iteration);
395  if (iteration == max_iteration) {
396  throw std::runtime_error("Solving rho_s = 0: too many iterations.");
397  }
398  return mus;
399 }
static double net_strange_density(double T, double mub, double mus)
Compute net strangeness density.
Definition: hadgas_eos.cc:289
static constexpr double tolerance_
Precision of equation solving.
Definition: hadgas_eos.h:343
Here is the call graph for this function:

◆ from_table()

void smash::HadronGasEos::from_table ( EosTable::table_element res,
double  e,
double  nb 
) const
inline

Get the element of eos table.

Definition at line 272 of file hadgas_eos.h.

272  {
273  eos_table_.get(res, e, nb);
274  }
EosTable eos_table_
EOS Table to be used.
Definition: hadgas_eos.h:349
void get(table_element &res, double e, double nb) const
Obtain interpolated p/T/muB/muS from the tabulated equation of state given energy density and net bar...
Definition: hadgas_eos.cc:133
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_eos_particle()

static bool smash::HadronGasEos::is_eos_particle ( const ParticleType ptype)
inlinestatic

Check if a particle belongs to the EoS.

Definition at line 277 of file hadgas_eos.h.

277  {
278  return ptype.is_hadron() && ptype.pdgcode().charmness() == 0;
279  }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_tabulated()

bool smash::HadronGasEos::is_tabulated ( ) const
inline

Create an EoS table or not?

Definition at line 282 of file hadgas_eos.h.

282 { return tabulate_; }
const bool tabulate_
Create an EoS table or not?
Definition: hadgas_eos.h:363
Here is the caller graph for this function:

◆ scaled_partial_density_auxiliary()

double smash::HadronGasEos::scaled_partial_density_auxiliary ( double  m_over_T,
double  mu_over_T 
)
staticprivate

Function used to avoid duplications in density calculations.

Parameters
[in]m_over_Tmass to temperature ratio \( m/T \)
[in]mu_over_Tchemical potential to temperature ratio \( \mu/T \)
Returns
calculated \( (m/T)^2 exp(\mu/T) K_2(m/T) \)

Definition at line 173 of file hadgas_eos.cc.

174  {
175  double x = mu_over_T - m_over_T;
176  if (x < -500.0) {
177  return 0.0;
178  }
179  x = std::exp(x);
180  // In the case of small masses: K_n(z) -> (n-1)!/2 *(2/z)^n, z -> 0,
181  // z*z*K_2(z) -> 2
182  return (m_over_T < really_small)
183  ? 2.0 * x
184  : m_over_T * m_over_T * x * gsl_sf_bessel_Kn_scaled(2, m_over_T);
185 }
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
Here is the caller graph for this function:

◆ scaled_partial_density()

double smash::HadronGasEos::scaled_partial_density ( const ParticleType ptype,
double  beta,
double  mub,
double  mus 
)
staticprivate

Compute (unnormalized) density of one hadron sort - helper functions used to reduce code duplication.

Parameters
[in]ptypethe hadron sort, for which partial density is computed
[in]betainverse temperature [1/GeV]
[in]mubbaryon chemical potential [GeV]
[in]musstrangeness chemical potential [GeV]
Returns
partial (unnormalized) density of the given hadron sort \(n\) [fm \(^{-3}\)]

Definition at line 187 of file hadgas_eos.cc.

189  {
190  const double m_over_T = ptype.mass() * beta;
191  double mu_over_T =
192  beta * (ptype.baryon_number() * mub + ptype.strangeness() * mus);
193  const double g = ptype.spin() + 1;
194  if (ptype.is_stable()) {
195  return g * scaled_partial_density_auxiliary(m_over_T, mu_over_T);
196  } else {
197  // Integral \int_{threshold}^{\infty} A(m) N_{thermal}(m) dm,
198  // where A(m) is the spectral function of the resonance.
199  const double m0 = ptype.mass();
200  const double w0 = ptype.width_at_pole();
201  const double mth = ptype.min_mass_spectral();
202  const double u_min = std::atan(2.0 * (mth - m0) / w0);
203  const double u_max = 0.5 * M_PI;
204  Integrator integrate;
205  const double result =
206  g * integrate(u_min, u_max, [&](double u) {
207  // One of many possible variable substitutions. Not clear if it has
208  // any advantages, except transforming (m_th, inf) to finite interval.
209  const double tanu = std::tan(u);
210  const double m = m0 + 0.5 * w0 * tanu;
211  const double jacobian = 0.5 * w0 * (1.0 + tanu * tanu);
212  return ptype.spectral_function(m) * jacobian *
213  scaled_partial_density_auxiliary(m * beta, mu_over_T);
214  });
215  return result;
216  }
217 }
static double scaled_partial_density_auxiliary(double m_over_T, double mu_over_T)
Function used to avoid duplications in density calculations.
Definition: hadgas_eos.cc:173
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:326
static Integrator integrate
Definition: decaytype.cc:147
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_eos_solver_equations()

int smash::HadronGasEos::set_eos_solver_equations ( const gsl_vector *  x,
void *  params,
gsl_vector *  f 
)
staticprivate

Interface EoS equations to be solved to gnu library.

Definition at line 401 of file hadgas_eos.cc.

402  {
403  double e = reinterpret_cast<struct rparams *>(params)->e;
404  double nb = reinterpret_cast<struct rparams *>(params)->nb;
405  double ns = reinterpret_cast<struct rparams *>(params)->ns;
406 
407  const double T = gsl_vector_get(x, 0);
408  const double mub = gsl_vector_get(x, 1);
409  const double mus = gsl_vector_get(x, 2);
410 
411  gsl_vector_set(f, 0, energy_density(T, mub, mus) - e);
412  gsl_vector_set(f, 1, net_baryon_density(T, mub, mus) - nb);
413  gsl_vector_set(f, 2, net_strange_density(T, mub, mus) - ns);
414 
415  return GSL_SUCCESS;
416 }
static double net_strange_density(double T, double mub, double mus)
Compute net strangeness density.
Definition: hadgas_eos.cc:289
static double net_baryon_density(double T, double mub, double mus)
Compute net baryon density.
Definition: hadgas_eos.cc:272
static double energy_density(double T, double mub, double mus)
Compute energy density.
Definition: hadgas_eos.cc:228
Here is the call graph for this function:
Here is the caller graph for this function:

◆ e_equation()

double smash::HadronGasEos::e_equation ( double  T,
void *  params 
)
staticprivate
See also
set_eos_solver_equations()

Definition at line 418 of file hadgas_eos.cc.

418  {
419  const double edens = reinterpret_cast<struct eparams *>(params)->edens;
420  return edens - energy_density(T, 0.0, 0.0);
421 }
static double energy_density(double T, double mub, double mus)
Compute energy density.
Definition: hadgas_eos.cc:228
Here is the call graph for this function:
Here is the caller graph for this function:

◆ print_solver_state()

std::string smash::HadronGasEos::print_solver_state ( size_t  iter) const
private

Helpful printout, useful for debugging if gnu equation solving goes crazy.

Parameters
[in]itercurrent value of iterator
Returns
debug output string with iter, x and f(x) from solver

Definition at line 534 of file hadgas_eos.cc.

534  {
535  std::stringstream s;
536  // clang-format off
537  s << "iter = " << iter << ","
538  << " x = " << gsl_vector_get(solver_->x, 0) << " "
539  << gsl_vector_get(solver_->x, 1) << " "
540  << gsl_vector_get(solver_->x, 2) << ", "
541  << "f(x) = " << gsl_vector_get(solver_->f, 0) << " "
542  << gsl_vector_get(solver_->f, 1) << " "
543  << gsl_vector_get(solver_->f, 2) << std::endl;
544  // clang-format on
545  return s.str();
546 }
gsl_multiroot_fsolver * solver_
Definition: hadgas_eos.h:360
Here is the caller graph for this function:

Member Data Documentation

◆ prefactor_

constexpr double smash::HadronGasEos::prefactor_
staticprivate
Initial value:
=
0.5 * M_1_PI * M_1_PI / (hbarc * hbarc * hbarc)

Constant factor, that appears in front of many thermodyn. expressions.

Definition at line 339 of file hadgas_eos.h.

◆ tolerance_

constexpr double smash::HadronGasEos::tolerance_ = 1.e-8
staticprivate

Precision of equation solving.

Definition at line 343 of file hadgas_eos.h.

◆ n_equations_

constexpr size_t smash::HadronGasEos::n_equations_ = 3
staticprivate

Number of equations in the system of equations to be solved.

Definition at line 346 of file hadgas_eos.h.

◆ eos_table_

EosTable smash::HadronGasEos::eos_table_ = EosTable(1.e-2, 1.e-2, 900, 900)
private

EOS Table to be used.

Definition at line 349 of file hadgas_eos.h.

◆ x_

gsl_vector* smash::HadronGasEos::x_
private

Variables used by gnu equation solver.

They are stored here to allocate and deallocate memory for them only once. It is expected that this class will be used for solving the EoS many times, so multiple allocations and frees are unwanted.

Definition at line 357 of file hadgas_eos.h.

◆ solver_

gsl_multiroot_fsolver* smash::HadronGasEos::solver_
private
See also
x_

Definition at line 360 of file hadgas_eos.h.

◆ tabulate_

const bool smash::HadronGasEos::tabulate_
private

Create an EoS table or not?

Definition at line 363 of file hadgas_eos.h.


The documentation for this class was generated from the following files: