Version: SMASH-1.8
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 (bool tabulate, bool account_for_widths)
 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...
 
bool account_for_resonance_widths () const
 If resonance spectral functions are taken into account. 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, bool account_for_resonance_widths=false)
 Compute particle number density. More...
 
static double pressure (double T, double mub, double mus, bool account_for_resonance_widths=false)
 Compute pressure \( p = n T \). More...
 
static double net_baryon_density (double T, double mub, double mus, bool account_for_resonance_widths=false)
 Compute net baryon density. More...
 
static double net_strange_density (double T, double mub, double mus, bool account_for_resonance_widths=false)
 Compute net strangeness density. More...
 
static double partial_density (const ParticleType &ptype, double T, double mub, double mus, bool account_for_resonance_widths=false)
 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, bool account_for_width=false)
 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...
 
const bool account_for_resonance_widths_
 Use pole masses of resonances or integrate over spectral functions. 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 ( bool  tabulate,
bool  account_for_widths 
)

Constructor of HadronGasEos.

Parameters
[in]tabulateWhether the equation of state should be tabulated Tabulation takes time once (typically around 5 minutes), but makes the further usage of the class much faster. Tabulated values are saved in a file and loaded at the next run.
[in]account_for_widthsWhether equation of state should account for resonance spectral functions. Normally one wants to do it, if HadronGasEos is used for density calculations, for example in the box initialization. However, it is not recommended to account for spectral functions if EoS is tabulated (tabulate = true), because this makes tabulation incredibly slow. Therefore, for HadronGasEos to be used in thermalizer, this option has to be false. Also note that presently width account is not implemented for energy density calculation.

Definition at line 162 of file hadgas_eos.cc.

163  : x_(gsl_vector_alloc(n_equations_)),
164  tabulate_(tabulate),
165  account_for_resonance_widths_(account_for_width) {
166  const gsl_multiroot_fsolver_type *solver_type;
167  solver_type = gsl_multiroot_fsolver_hybrid;
168  solver_ = gsl_multiroot_fsolver_alloc(solver_type, n_equations_);
170  logg[LResonances].error(
171  "Compilation of hadron gas EoS table requested with"
172  " account of resonance spectral functions. This is not "
173  "advised, as it will likely take a few days to finish."
174  " Besides, the effect of resonance widths is currently not "
175  "implemented for energy density computation, so the computed"
176  " table will be inconsistent anyways.");
177  }
178  if (tabulate_) {
179  eos_table_.compile_table(*this);
180  }
181 }
Here is the call graph for this function:

◆ ~HadronGasEos()

smash::HadronGasEos::~HadronGasEos ( )

Definition at line 183 of file hadgas_eos.cc.

183  {
184  gsl_multiroot_fsolver_free(solver_);
185  gsl_vector_free(x_);
186 }

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 244 of file hadgas_eos.cc.

244  {
245  if (T < really_small) {
246  return 0.0;
247  }
248  const double beta = 1.0 / T;
249  double e = 0.0;
250  for (const ParticleType &ptype : ParticleType::list_all()) {
251  if (!is_eos_particle(ptype)) {
252  continue;
253  }
254  const double z = ptype.mass() * beta;
255  double x = beta * (mub * ptype.baryon_number() + mus * ptype.strangeness() -
256  ptype.mass());
257  if (x < -500.0) {
258  return 0.0;
259  }
260  x = std::exp(x);
261  const size_t g = ptype.spin() + 1;
262  // Small mass case, z*z*K_2(z) -> 2, z*z*z*K_1(z) -> 0 at z->0
263  e += (z < really_small) ? 3.0 * g * x
264  : z * z * g * x *
265  (3.0 * gsl_sf_bessel_Kn_scaled(2, z) +
266  z * gsl_sf_bessel_K1_scaled(z));
267  }
268  e *= prefactor_ * T * T * T * T;
269  return e;
270 }
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,
bool  account_for_resonance_widths = false 
)
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]
[in]account_for_resonance_widthsif false, pole masses are used; if true, then integration over spectral function is included
Returns
particle number density n [fm \(^{-3}\)]

Definition at line 272 of file hadgas_eos.cc.

273  {
274  if (T < really_small) {
275  return 0.0;
276  }
277  const double beta = 1.0 / T;
278  double rho = 0.0;
279  for (const ParticleType &ptype : ParticleType::list_all()) {
280  if (!is_eos_particle(ptype)) {
281  continue;
282  }
283  rho += scaled_partial_density(ptype, beta, mub, mus, account_for_width);
284  }
285  rho *= prefactor_ * T * T * T;
286  return rho;
287 }
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,
bool  account_for_resonance_widths = false 
)
inlinestatic

Compute pressure \( p = n T \).

Parameters
[in]Ttemperature [GeV]
[in]mubbaryon chemical potential [GeV]
[in]musstrangeness chemical potential [GeV]
[in]account_for_resonance_widthsif false, pole masses are used; if true, then integration over spectral function is included
Returns
pressure p [GeV/fm \(^{-3}\)]

Definition at line 180 of file hadgas_eos.h.

181  {
182  return T * density(T, mub, mus, account_for_resonance_widths);
183  }
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,
bool  account_for_resonance_widths = false 
)
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]
[in]account_for_resonance_widthsif false, pole masses are used; if true, then integration over spectral function is included
Returns
net baryon density density \(n_B\) [fm \(^{-3}\)]

Definition at line 289 of file hadgas_eos.cc.

290  {
291  if (T < really_small) {
292  return 0.0;
293  }
294  const double beta = 1.0 / T;
295  double rho = 0.0;
296  for (const ParticleType &ptype : ParticleType::list_all()) {
297  if (!ptype.is_baryon() || !is_eos_particle(ptype)) {
298  continue;
299  }
300  rho += scaled_partial_density(ptype, beta, mub, mus, account_for_width) *
301  ptype.baryon_number();
302  }
303  rho *= prefactor_ * T * T * T;
304  return rho;
305 }
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,
bool  account_for_resonance_widths = false 
)
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]
[in]account_for_resonance_widthsif false, pole masses are used; if true, then integration over spectral function is included
Returns
net strangeness density density \(n_S\) [fm \(^{-3}\)]

Definition at line 307 of file hadgas_eos.cc.

308  {
309  if (T < really_small) {
310  return 0.0;
311  }
312  const double beta = 1.0 / T;
313  double rho = 0.0;
314  for (const ParticleType &ptype : ParticleType::list_all()) {
315  if (ptype.strangeness() == 0 || !is_eos_particle(ptype)) {
316  continue;
317  }
318  rho += scaled_partial_density(ptype, beta, mub, mus, account_for_width) *
319  ptype.strangeness();
320  }
321  rho *= prefactor_ * T * T * T;
322  return rho;
323 }
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,
bool  account_for_resonance_widths = false 
)
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]
[in]account_for_resonance_widthsif false, pole masses are used; if true, then integration over spectral function is included
Returns
partial density of the given hadron sort \(n\) [fm \(^{-3}\)]

Definition at line 234 of file hadgas_eos.cc.

236  {
237  if (T < really_small) {
238  return 0.0;
239  }
240  return prefactor_ * T * T * T *
241  scaled_partial_density(ptype, 1.0 / T, mub, mus, account_for_width);
242 }
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 325 of file hadgas_eos.cc.

326  {
327  if (ptype.is_stable()) {
328  return ptype.mass();
329  }
330  // Sampling mass m from A(m) x^2 BesselK_2(x), where x = beta m.
331  // Strategy employs the idea of importance sampling:
332  // -- Sample mass from the simple Breit-Wigner first, then
333  // reject by the ratio.
334  // -- Note that f(x) = x^2 BesselK_2(x) monotonously decreases
335  // and has maximum at x = xmin. That is why instead of f(x)
336  // the ratio f(x)/f(xmin) is used.
337 
338  const double max_mass = 5.0; // GeV
339  double m, q;
340  {
341  // Allow underflows in exponentials
342  DisableFloatTraps guard(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
343  const double w0 = ptype.width_at_pole();
344  const double mth = ptype.min_mass_spectral();
345  const double m0 = ptype.mass();
346  double max_ratio =
347  m0 * m0 * std::exp(-beta * m0) * gsl_sf_bessel_Kn_scaled(2, m0 * beta) *
348  ptype.spectral_function(m0) / ptype.spectral_function_simple(m0);
349  // Heuristic adaptive maximum search to find max_ratio
350  constexpr int npoints = 31;
351  double m_lower = mth, m_upper = max_mass, m_where_max = m0;
352 
353  for (size_t n_iterations = 0; n_iterations < 2; n_iterations++) {
354  const double dm = (m_upper - m_lower) / npoints;
355  for (size_t i = 1; i < npoints; i++) {
356  m = m_lower + dm * i;
357  const double thermal_factor =
358  m * m * std::exp(-beta * m) * gsl_sf_bessel_Kn_scaled(2, m * beta);
359  q = ptype.spectral_function(m) * thermal_factor /
360  ptype.spectral_function_simple(m);
361  if (q > max_ratio) {
362  max_ratio = q;
363  m_where_max = m;
364  }
365  }
366  m_lower = m_where_max - (m_where_max - m_lower) * 0.1;
367  m_upper = m_where_max + (m_upper - m_where_max) * 0.1;
368  }
369  // Safety factor
370  max_ratio *= 1.5;
371 
372  do {
373  // sample mass from A(m)
374  do {
375  m = random::cauchy(m0, 0.5 * w0, mth, max_mass);
376  const double thermal_factor =
377  m * m * std::exp(-beta * m) * gsl_sf_bessel_Kn_scaled(2, m * beta);
378  q = ptype.spectral_function(m) * thermal_factor /
379  ptype.spectral_function_simple(m);
380  } while (q < random::uniform(0., max_ratio));
381  if (q > max_ratio) {
382  logg[LResonances].warn(
383  ptype.name(), " - maximum increased in",
384  " sample_mass_thermal from ", max_ratio, " to ", q, ", mass = ", m,
385  " previously assumed maximum at m = ", m_where_max);
386  max_ratio = q;
387  m_where_max = m;
388  } else {
389  break;
390  }
391  } while (true);
392  }
393  return m;
394 }
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 506 of file hadgas_eos.cc.

508  {
509  int residual_status = GSL_SUCCESS;
510  size_t iter = 0;
511 
512  struct rparams p = {e, nb, ns, account_for_resonance_widths_};
513  gsl_multiroot_function f = {&HadronGasEos::set_eos_solver_equations,
514  n_equations_, &p};
515 
516  gsl_vector_set(x_, 0, initial_approximation[0]);
517  gsl_vector_set(x_, 1, initial_approximation[1]);
518  gsl_vector_set(x_, 2, initial_approximation[2]);
519 
520  gsl_multiroot_fsolver_set(solver_, &f, x_);
521  do {
522  iter++;
523  const auto iterate_status = gsl_multiroot_fsolver_iterate(solver_);
524  // std::cout << print_solver_state(iter);
525 
526  // Avoiding too low temperature
527  if (gsl_vector_get(solver_->x, 0) < 0.015) {
528  return {0.0, 0.0, 0.0};
529  }
530 
531  // check if solver is stuck
532  if (iterate_status) {
533  break;
534  }
535  residual_status = gsl_multiroot_test_residual(solver_->f, tolerance_);
536  } while (residual_status == GSL_CONTINUE && iter < 1000);
537 
538  if (residual_status != GSL_SUCCESS) {
539  std::stringstream solver_parameters;
540  solver_parameters << "\nSolver run with "
541  << "e = " << e << ", nb = " << nb << ", ns = " << ns
542  << ", init. approx.: " << initial_approximation[0] << " "
543  << initial_approximation[1] << " "
544  << initial_approximation[2] << std::endl;
545  logg[LResonances].warn(gsl_strerror(residual_status) +
546  solver_parameters.str() + print_solver_state(iter));
547  }
548 
549  return {gsl_vector_get(solver_->x, 0), gsl_vector_get(solver_->x, 1),
550  gsl_vector_get(solver_->x, 2)};
551 }
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 279 of file hadgas_eos.h.

279  {
280  return solve_eos(e, nb, ns, solve_eos_initial_approximation(e, nb));
281  }
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 443 of file hadgas_eos.cc.

444  {
445  assert(e >= 0.0);
446  // 1. Get temperature from energy density assuming zero chemical potentials
447  int degeneracies_sum = 0.0;
448  for (const ParticleType &ptype : ParticleType::list_all()) {
449  if (is_eos_particle(ptype)) {
450  degeneracies_sum += ptype.spin() + 1;
451  }
452  }
453  // Temperature in case of massless gas. For massive it should be larger.
454  const double T_min = std::pow(e / prefactor_ / 6 / degeneracies_sum, 1. / 4.);
455  // Simply assume that the temperature is not higher than 2 GeV.
456  const double T_max = 2.0;
457 
458  struct eparams parameters = {e};
459  gsl_function F = {&e_equation, &parameters};
460  const gsl_root_fsolver_type *T = gsl_root_fsolver_brent;
461  gsl_root_fsolver *e_solver;
462  e_solver = gsl_root_fsolver_alloc(T);
463  gsl_root_fsolver_set(e_solver, &F, T_min, T_max);
464 
465  int iter = 0, status, max_iter = 100;
466  double T_init = 0.0;
467 
468  do {
469  iter++;
470  status = gsl_root_fsolver_iterate(e_solver);
471  if (status != GSL_SUCCESS) {
472  break;
473  }
474  T_init = gsl_root_fsolver_root(e_solver);
475  double x_lo = gsl_root_fsolver_x_lower(e_solver);
476  double x_hi = gsl_root_fsolver_x_upper(e_solver);
477  status = gsl_root_test_interval(x_lo, x_hi, 0.0, 0.001);
478  } while (status == GSL_CONTINUE && iter < max_iter);
479 
480  if (status != GSL_SUCCESS) {
481  std::stringstream err_msg;
482  err_msg << "Solver of equation for temperature with e = " << e
483  << " failed to converge. Maybe Tmax = " << T_max << " is too small?"
484  << std::endl;
485  throw std::runtime_error(gsl_strerror(status) + err_msg.str());
486  }
487 
488  gsl_root_fsolver_free(e_solver);
489 
490  // 2. Get the baryon chemical potential for mus = 0 and previously obtained T
491  double n_only_baryons = 0.0;
492  for (const ParticleType &ptype : ParticleType::list_all()) {
493  if (is_eos_particle(ptype) && ptype.baryon_number() == 1) {
494  n_only_baryons += scaled_partial_density(ptype, 1.0 / T_init, 0.0, 0.0);
495  }
496  }
497  const double nb_scaled = nb / prefactor_ / (T_init * T_init * T_init);
498  double mub_init = T_init * std::asinh(nb_scaled / n_only_baryons / 2.0);
499 
500  // 3. mus = 0 is typically a good initial approximation
501 
502  std::array<double, 3> initial_approximation = {T_init, mub_init, 0.0};
503  return initial_approximation;
504 }
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 396 of file hadgas_eos.cc.

396  {
397  // Binary search
398  double mus_u = mub + T;
399  double mus_l = 0.0;
400  double mus, rhos;
401  size_t iteration = 0;
402  // 50 iterations should give precision 2^-50 ~ 10^-15
403  const size_t max_iteration = 50;
404  do {
405  mus = 0.5 * (mus_u + mus_l);
406  rhos = net_strange_density(T, mub, mus);
407  if (rhos > 0.0) {
408  mus_u = mus;
409  } else {
410  mus_l = mus;
411  }
412  iteration++;
413  } while (std::abs(rhos) > tolerance_ && iteration < max_iteration);
414  if (iteration == max_iteration) {
415  throw std::runtime_error("Solving rho_s = 0: too many iterations.");
416  }
417  return mus;
418 }
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 303 of file hadgas_eos.h.

303  {
304  eos_table_.get(res, e, nb);
305  }
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 308 of file hadgas_eos.h.

308  {
309  return ptype.is_hadron() && ptype.pdgcode().charmness() == 0;
310  }
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 313 of file hadgas_eos.h.

313 { return tabulate_; }
Here is the caller graph for this function:

◆ account_for_resonance_widths()

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

If resonance spectral functions are taken into account.

Definition at line 316 of file hadgas_eos.h.

316  {
318  }
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 188 of file hadgas_eos.cc.

189  {
190  double x = mu_over_T - m_over_T;
191  if (x < -500.0) {
192  return 0.0;
193  }
194  x = std::exp(x);
195  // In the case of small masses: K_n(z) -> (n-1)!/2 *(2/z)^n, z -> 0,
196  // z*z*K_2(z) -> 2
197  return (m_over_T < really_small)
198  ? 2.0 * x
199  : m_over_T * m_over_T * x * gsl_sf_bessel_Kn_scaled(2, m_over_T);
200 }
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,
bool  account_for_width = false 
)
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]
[in]account_for_widthTake hadron spectral functions into account or not. When taken into account, they result in a considerable slow down.
Returns
partial (unnormalized) density of the given hadron sort \(n\) [fm \(^{-3}\)]

Definition at line 202 of file hadgas_eos.cc.

204  {
205  const double m_over_T = ptype.mass() * beta;
206  double mu_over_T =
207  beta * (ptype.baryon_number() * mub + ptype.strangeness() * mus);
208  const double g = ptype.spin() + 1;
209  if (ptype.is_stable() || !account_for_width) {
210  return g * scaled_partial_density_auxiliary(m_over_T, mu_over_T);
211  } else {
212  // Integral \int_{threshold}^{\infty} A(m) N_{thermal}(m) dm,
213  // where A(m) is the spectral function of the resonance.
214  const double m0 = ptype.mass();
215  const double w0 = ptype.width_at_pole();
216  const double mth = ptype.min_mass_spectral();
217  const double u_min = std::atan(2.0 * (mth - m0) / w0);
218  const double u_max = 0.5 * M_PI;
219  Integrator integrate;
220  const double result =
221  g * integrate(u_min, u_max, [&](double u) {
222  // One of many possible variable substitutions. Not clear if it has
223  // any advantages, except transforming (m_th, inf) to finite interval.
224  const double tanu = std::tan(u);
225  const double m = m0 + 0.5 * w0 * tanu;
226  const double jacobian = 0.5 * w0 * (1.0 + tanu * tanu);
227  return ptype.spectral_function(m) * jacobian *
228  scaled_partial_density_auxiliary(m * beta, mu_over_T);
229  });
230  return result;
231  }
232 }
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 420 of file hadgas_eos.cc.

421  {
422  double e = reinterpret_cast<struct rparams *>(params)->e;
423  double nb = reinterpret_cast<struct rparams *>(params)->nb;
424  double ns = reinterpret_cast<struct rparams *>(params)->ns;
425  bool w = reinterpret_cast<struct rparams *>(params)->account_for_width;
426 
427  const double T = gsl_vector_get(x, 0);
428  const double mub = gsl_vector_get(x, 1);
429  const double mus = gsl_vector_get(x, 2);
430 
431  gsl_vector_set(f, 0, energy_density(T, mub, mus) - e);
432  gsl_vector_set(f, 1, net_baryon_density(T, mub, mus, w) - nb);
433  gsl_vector_set(f, 2, net_strange_density(T, mub, mus, w) - ns);
434 
435  return GSL_SUCCESS;
436 }
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 438 of file hadgas_eos.cc.

438  {
439  const double edens = reinterpret_cast<struct eparams *>(params)->edens;
440  return edens - energy_density(T, 0.0, 0.0);
441 }
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 553 of file hadgas_eos.cc.

553  {
554  std::stringstream s;
555  // clang-format off
556  s << "iter = " << iter << ","
557  << " x = " << gsl_vector_get(solver_->x, 0) << " "
558  << gsl_vector_get(solver_->x, 1) << " "
559  << gsl_vector_get(solver_->x, 2) << ", "
560  << "f(x) = " << gsl_vector_get(solver_->f, 0) << " "
561  << gsl_vector_get(solver_->f, 1) << " "
562  << gsl_vector_get(solver_->f, 2) << std::endl;
563  // clang-format on
564  return s.str();
565 }
Here is the caller graph for this function:

Member Data Documentation

◆ prefactor_

constexpr double smash::HadronGasEos::prefactor_
staticconstexprprivate
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 381 of file hadgas_eos.h.

◆ tolerance_

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

Precision of equation solving.

Definition at line 385 of file hadgas_eos.h.

◆ n_equations_

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

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

Definition at line 388 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 391 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 399 of file hadgas_eos.h.

◆ solver_

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

Definition at line 402 of file hadgas_eos.h.

◆ tabulate_

const bool smash::HadronGasEos::tabulate_
private

Create an EoS table or not?

Definition at line 405 of file hadgas_eos.h.

◆ account_for_resonance_widths_

const bool smash::HadronGasEos::account_for_resonance_widths_
private

Use pole masses of resonances or integrate over spectral functions.

Definition at line 408 of file hadgas_eos.h.


The documentation for this class was generated from the following files:
smash::random::cauchy
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:307
smash::HadronGasEos::solve_eos
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:506
smash::HadronGasEos::eos_table_
EosTable eos_table_
EOS Table to be used.
Definition: hadgas_eos.h:391
smash::HadronGasEos::density
static double density(double T, double mub, double mus, bool account_for_resonance_widths=false)
Compute particle number density.
Definition: hadgas_eos.cc:272
smash::HadronGasEos::solver_
gsl_multiroot_fsolver * solver_
Definition: hadgas_eos.h:402
smash::HadronGasEos::net_strange_density
static double net_strange_density(double T, double mub, double mus, bool account_for_resonance_widths=false)
Compute net strangeness density.
Definition: hadgas_eos.cc:307
smash::HadronGasEos::scaled_partial_density_auxiliary
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:188
smash::HadronGasEos::solve_eos_initial_approximation
std::array< double, 3 > solve_eos_initial_approximation(double e, double nb)
Compute a reasonable initial approximation for solve_eos.
Definition: hadgas_eos.cc:443
smash::HadronGasEos::tolerance_
static constexpr double tolerance_
Precision of equation solving.
Definition: hadgas_eos.h:385
smash::HadronGasEos::e_equation
static double e_equation(double T, void *params)
Definition: hadgas_eos.cc:438
smash::HadronGasEos::prefactor_
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:381
smash::HadronGasEos::account_for_resonance_widths_
const bool account_for_resonance_widths_
Use pole masses of resonances or integrate over spectral functions.
Definition: hadgas_eos.h:408
smash::hbarc
constexpr double hbarc
GeV <-> fm conversion factor.
Definition: constants.h:25
smash::logg
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
smash::random::beta
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:329
smash::LResonances
static constexpr int LResonances
Definition: clebschgordan.cc:16
smash::really_small
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
smash::HadronGasEos::print_solver_state
std::string print_solver_state(size_t iter) const
Helpful printout, useful for debugging if gnu equation solving goes crazy.
Definition: hadgas_eos.cc:553
smash::integrate
static Integrator integrate
Definition: decaytype.cc:147
smash::HadronGasEos::x_
gsl_vector * x_
Variables used by gnu equation solver.
Definition: hadgas_eos.h:399
smash::HadronGasEos::account_for_resonance_widths
bool account_for_resonance_widths() const
If resonance spectral functions are taken into account.
Definition: hadgas_eos.h:316
smash::HadronGasEos::scaled_partial_density
static double scaled_partial_density(const ParticleType &ptype, double beta, double mub, double mus, bool account_for_width=false)
Compute (unnormalized) density of one hadron sort - helper functions used to reduce code duplication.
Definition: hadgas_eos.cc:202
smash::HadronGasEos::net_baryon_density
static double net_baryon_density(double T, double mub, double mus, bool account_for_resonance_widths=false)
Compute net baryon density.
Definition: hadgas_eos.cc:289
smash::HadronGasEos::tabulate_
const bool tabulate_
Create an EoS table or not?
Definition: hadgas_eos.h:405
smash::EosTable::get
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:137
smash::HadronGasEos::set_eos_solver_equations
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:420
smash::HadronGasEos::n_equations_
static constexpr size_t n_equations_
Number of equations in the system of equations to be solved.
Definition: hadgas_eos.h:388
smash::HadronGasEos::is_eos_particle
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:308
smash::pdg::p
constexpr int p
Proton.
Definition: pdgcode_constants.h:28
smash::random::uniform
T uniform(T min, T max)
Definition: random.h:88
smash::EosTable::compile_table
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:35
smash::ParticleType::list_all
static const ParticleTypeList & list_all()
Definition: particletype.cc:57
smash::HadronGasEos::energy_density
static double energy_density(double T, double mub, double mus)
Compute energy density.
Definition: hadgas_eos.cc:244