Version: SMASH-1.7
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

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

162  : x_(gsl_vector_alloc(n_equations_)),
163  tabulate_(tabulate),
164  account_for_resonance_widths_(account_for_width) {
165  const gsl_multiroot_fsolver_type *solver_type;
166  solver_type = gsl_multiroot_fsolver_hybrid;
167  solver_ = gsl_multiroot_fsolver_alloc(solver_type, n_equations_);
169  const auto &log = logger<LogArea::Resonances>();
170  log.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 }
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:388
EosTable eos_table_
EOS Table to be used.
Definition: hadgas_eos.h:391
gsl_multiroot_fsolver * solver_
Definition: hadgas_eos.h:402
const bool account_for_resonance_widths_
Use pole masses of resonances or integrate over spectral functions.
Definition: hadgas_eos.h:408
gsl_vector * x_
Variables used by gnu equation solver.
Definition: hadgas_eos.h:399
const bool tabulate_
Create an EoS table or not?
Definition: hadgas_eos.h:405

Here is the call graph for this function:

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 }
gsl_multiroot_fsolver * solver_
Definition: hadgas_eos.h:402
gsl_vector * x_
Variables used by gnu equation solver.
Definition: hadgas_eos.h:399

Member Function Documentation

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 }
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:308
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:381
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:329

Here is the call graph for this function:

Here is the caller graph for this function:

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 }
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
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:308
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:381
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:329

Here is the call graph for this function:

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  }
static double density(double T, double mub, double mus, bool account_for_resonance_widths=false)
Compute particle number density.
Definition: hadgas_eos.cc:272
bool account_for_resonance_widths() const
If resonance spectral functions are taken into account.
Definition: hadgas_eos.h:316

Here is the call graph for this function:

Here is the caller graph for this function:

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 }
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
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:308
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:381
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:329

Here is the call graph for this function:

Here is the caller graph for this function:

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 }
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
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:308
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:381
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:329

Here is the call graph for this function:

Here is the caller graph for this function:

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 }
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
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:381

Here is the call graph for this function:

Here is the caller graph for this function:

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  const auto &log = logger<LogArea::Resonances>();
383  log.warn(ptype.name(), " - maximum increased in",
384  " sample_mass_thermal from ", max_ratio, " to ", q,
385  ", mass = ", m,
386  " previously assumed maximum at m = ", m_where_max);
387  max_ratio = q;
388  m_where_max = m;
389  } else {
390  break;
391  }
392  } while (true);
393  }
394  return m;
395 }
T uniform(T min, T max)
Definition: random.h:88
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
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:329

Here is the call graph for this function:

Here is the caller graph for this function:

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

509  {
510  int residual_status = GSL_SUCCESS;
511  size_t iter = 0;
512 
513  struct rparams p = {e, nb, ns, account_for_resonance_widths_};
514  gsl_multiroot_function f = {&HadronGasEos::set_eos_solver_equations,
515  n_equations_, &p};
516 
517  gsl_vector_set(x_, 0, initial_approximation[0]);
518  gsl_vector_set(x_, 1, initial_approximation[1]);
519  gsl_vector_set(x_, 2, initial_approximation[2]);
520 
521  gsl_multiroot_fsolver_set(solver_, &f, x_);
522  do {
523  iter++;
524  const auto iterate_status = gsl_multiroot_fsolver_iterate(solver_);
525  // std::cout << print_solver_state(iter);
526 
527  // Avoiding too low temperature
528  if (gsl_vector_get(solver_->x, 0) < 0.015) {
529  return {0.0, 0.0, 0.0};
530  }
531 
532  // check if solver is stuck
533  if (iterate_status) {
534  break;
535  }
536  residual_status = gsl_multiroot_test_residual(solver_->f, tolerance_);
537  } while (residual_status == GSL_CONTINUE && iter < 1000);
538 
539  if (residual_status != GSL_SUCCESS) {
540  std::stringstream solver_parameters;
541  solver_parameters << "\nSolver run with "
542  << "e = " << e << ", nb = " << nb << ", ns = " << ns
543  << ", init. approx.: " << initial_approximation[0] << " "
544  << initial_approximation[1] << " "
545  << initial_approximation[2] << std::endl;
546  const auto &log = logger<LogArea::HadronGasEos>();
547  log.warn(gsl_strerror(residual_status) + solver_parameters.str() +
548  print_solver_state(iter));
549  }
550 
551  return {gsl_vector_get(solver_->x, 0), gsl_vector_get(solver_->x, 1),
552  gsl_vector_get(solver_->x, 2)};
553 }
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:421
std::string print_solver_state(size_t iter) const
Helpful printout, useful for debugging if gnu equation solving goes crazy.
Definition: hadgas_eos.cc:555
static constexpr size_t n_equations_
Number of equations in the system of equations to be solved.
Definition: hadgas_eos.h:388
static constexpr double tolerance_
Precision of equation solving.
Definition: hadgas_eos.h:385
gsl_multiroot_fsolver * solver_
Definition: hadgas_eos.h:402
const bool account_for_resonance_widths_
Use pole masses of resonances or integrate over spectral functions.
Definition: hadgas_eos.h:408
gsl_vector * x_
Variables used by gnu equation solver.
Definition: hadgas_eos.h:399
constexpr int p
Proton.

Here is the call graph for this function:

Here is the caller graph for this function:

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  }
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:507
std::array< double, 3 > solve_eos_initial_approximation(double e, double nb)
Compute a reasonable initial approximation for solve_eos.
Definition: hadgas_eos.cc:444
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 444 of file hadgas_eos.cc.

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

Here is the call graph for this function:

Here is the caller graph for this function:

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

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

Here is the call graph for this function:

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  }
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:136
EosTable eos_table_
EOS Table to be used.
Definition: hadgas_eos.h:391

Here is the caller graph for this function:

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:

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_; }
const bool tabulate_
Create an EoS table or not?
Definition: hadgas_eos.h:405

Here is the caller graph for this function:

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  }
const bool account_for_resonance_widths_
Use pole masses of resonances or integrate over spectral functions.
Definition: hadgas_eos.h:408

Here is the caller graph for this function:

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 }
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37

Here is the caller graph for this function:

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 }
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
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:329
static Integrator integrate
Definition: decaytype.cc:147

Here is the call graph for this function:

Here is the caller graph for this function:

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

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

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 439 of file hadgas_eos.cc.

439  {
440  const double edens = reinterpret_cast<struct eparams *>(params)->edens;
441  return edens - energy_density(T, 0.0, 0.0);
442 }
static double energy_density(double T, double mub, double mus)
Compute energy density.
Definition: hadgas_eos.cc:244

Here is the call graph for this function:

Here is the caller graph for this function:

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

555  {
556  std::stringstream s;
557  // clang-format off
558  s << "iter = " << iter << ","
559  << " x = " << gsl_vector_get(solver_->x, 0) << " "
560  << gsl_vector_get(solver_->x, 1) << " "
561  << gsl_vector_get(solver_->x, 2) << ", "
562  << "f(x) = " << gsl_vector_get(solver_->f, 0) << " "
563  << gsl_vector_get(solver_->f, 1) << " "
564  << gsl_vector_get(solver_->f, 2) << std::endl;
565  // clang-format on
566  return s.str();
567 }
gsl_multiroot_fsolver * solver_
Definition: hadgas_eos.h:402

Here is the caller graph for this function:

Member Data Documentation

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 381 of file hadgas_eos.h.

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

Precision of equation solving.

Definition at line 385 of file hadgas_eos.h.

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

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

Definition at line 388 of file hadgas_eos.h.

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.

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.

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

Definition at line 402 of file hadgas_eos.h.

const bool smash::HadronGasEos::tabulate_
private

Create an EoS table or not?

Definition at line 405 of file hadgas_eos.h.

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: