Version: SMASH-1.8
hadgas_eos.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2016-
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include <gsl/gsl_sf_bessel.h>
11 
12 #include <fstream>
13 #include <iomanip>
14 #include <iostream>
15 
16 #include <boost/filesystem.hpp>
17 
18 #include "smash/constants.h"
20 #include "smash/fpenvironment.h"
21 #include "smash/hadgas_eos.h"
22 #include "smash/integrate.h"
23 #include "smash/logging.h"
24 #include "smash/pow.h"
25 #include "smash/random.h"
26 
27 namespace smash {
28 static constexpr int LResonances = LogArea::Resonances::id;
29 
30 EosTable::EosTable(double de, double dnb, size_t n_e, size_t n_nb)
31  : de_(de), dnb_(dnb), n_e_(n_e), n_nb_(n_nb) {
32  table_.resize(n_e_ * n_nb_);
33 }
34 
36  const std::string &eos_savefile_name) {
37  bool table_read_success = false, table_consistency = true;
38  if (boost::filesystem::exists(eos_savefile_name)) {
39  std::cout << "Reading table from file " << eos_savefile_name << std::endl;
40  std::ifstream file;
41  file.open(eos_savefile_name, std::ios::in);
42  file >> de_ >> dnb_;
43  file >> n_e_ >> n_nb_;
44  table_.resize(n_e_ * n_nb_);
45  for (size_t ie = 0; ie < n_e_; ie++) {
46  for (size_t inb = 0; inb < n_nb_; inb++) {
47  double p, T, mub, mus;
48  file >> p >> T >> mub >> mus;
49  table_[index(ie, inb)] = {p, T, mub, mus};
50  }
51  }
52  table_read_success = true;
53  std::cout << "Table consumed successfully." << std::endl;
54  }
55 
56  if (table_read_success) {
57  // Check if the saved table is consistent with the current particle table
58  std::cout << "Checking consistency of the table... " << std::endl;
59  constexpr size_t number_of_steps = 50;
60  const size_t ie_step = 1 + n_e_ / number_of_steps;
61  const size_t inb_step = 1 + n_nb_ / number_of_steps;
62  for (size_t ie = 0; ie < n_e_; ie += ie_step) {
63  for (size_t inb = 0; inb < n_nb_; inb += inb_step) {
64  const table_element x = table_[index(ie, inb)];
65  const bool w = eos.account_for_resonance_widths();
66  const double e_comp = eos.energy_density(x.T, x.mub, x.mus);
67  const double nb_comp = eos.net_baryon_density(x.T, x.mub, x.mus, w);
68  const double ns_comp = eos.net_strange_density(x.T, x.mub, x.mus, w);
69  const double p_comp = eos.pressure(x.T, x.mub, x.mus, w);
70  // Precision is just 10^-3, this is precision of saved data in the file
71  const double eps = 1.e-3;
72  // Only check the physical region, hence T > 0 condition
73  if ((std::abs(de_ * ie - e_comp) > eps ||
74  std::abs(dnb_ * inb - nb_comp) > eps || std::abs(ns_comp) > eps ||
75  std::abs(x.p - p_comp) > eps) &&
76  (x.T > 0.0)) {
77  std::cout << "discrepancy: " << de_ * ie << " = " << e_comp << ", "
78  << dnb_ * inb << " = " << nb_comp << ", " << x.p << " = "
79  << p_comp << ", 0 = " << ns_comp << std::endl;
80  table_consistency = false;
81  goto finish_consistency_check;
82  }
83  }
84  }
85  }
86 finish_consistency_check:
87 
88  if (!table_read_success || !table_consistency) {
89  std::cout << "Compiling an EoS table..." << std::endl;
90  const double ns = 0.0;
91  for (size_t ie = 0; ie < n_e_; ie++) {
92  std::cout << ie << "/" << n_e_ << "\r" << std::flush;
93  const double e = de_ * ie;
94  for (size_t inb = 0; inb < n_nb_; inb++) {
95  const double nb = dnb_ * inb;
96  // It is physically impossible to have energy density > nucleon mass*nb,
97  // therefore eqns have no solutions.
98  if (nb >= e) {
99  table_[index(ie, inb)] = {0.0, 0.0, 0.0, 0.0};
100  continue;
101  }
102  // Take extrapolated (T, mub, mus) as initial approximation
103  std::array<double, 3> init_approx;
104  if (inb >= 2) {
105  const table_element y = table_[index(ie, inb - 2)];
106  const table_element x = table_[index(ie, inb - 1)];
107  init_approx = {2.0 * x.T - y.T, 2.0 * x.mub - y.mub,
108  2.0 * x.mus - y.mus};
109  } else {
110  init_approx = eos.solve_eos_initial_approximation(e, nb);
111  }
112  const std::array<double, 3> res = eos.solve_eos(e, nb, ns, init_approx);
113  const double T = res[0];
114  const double mub = res[1];
115  const double mus = res[2];
116  const bool w = eos.account_for_resonance_widths();
117  table_[index(ie, inb)] = {eos.pressure(T, mub, mus, w), T, mub, mus};
118  }
119  }
120  // Save table to file
121  std::cout << "Saving table to file " << eos_savefile_name << std::endl;
122  std::ofstream file;
123  file.open(eos_savefile_name, std::ios::out);
124  file << de_ << " " << dnb_ << std::endl;
125  file << n_e_ << " " << n_nb_ << std::endl;
126  file << std::setprecision(7);
127  file << std::fixed;
128  for (size_t ie = 0; ie < n_e_; ie++) {
129  for (size_t inb = 0; inb < n_nb_; inb++) {
130  const EosTable::table_element x = table_[index(ie, inb)];
131  file << x.p << " " << x.T << " " << x.mub << " " << x.mus << std::endl;
132  }
133  }
134  }
135 }
136 
137 void EosTable::get(EosTable::table_element &res, double e, double nb) const {
138  const size_t ie = static_cast<size_t>(std::floor(e / de_));
139  const size_t inb = static_cast<size_t>(std::floor(nb / dnb_));
140 
141  if (ie >= n_e_ - 1 || inb >= n_nb_ - 1) {
142  res = {-1.0, -1.0, -1.0, -1.0};
143  } else {
144  // 1st order interpolation
145  const double ae = e / de_ - ie;
146  const double an = nb / dnb_ - inb;
147  const EosTable::table_element s1 = table_[index(ie, inb)];
148  const EosTable::table_element s2 = table_[index(ie + 1, inb)];
149  const EosTable::table_element s3 = table_[index(ie, inb + 1)];
150  const EosTable::table_element s4 = table_[index(ie + 1, inb + 1)];
151  res.p = ae * (an * s4.p + (1.0 - an) * s2.p) +
152  (1.0 - ae) * (an * s3.p + (1.0 - an) * s1.p);
153  res.T = ae * (an * s4.T + (1.0 - an) * s2.T) +
154  (1.0 - ae) * (an * s3.T + (1.0 - an) * s1.T);
155  res.mub = ae * (an * s4.mub + (1.0 - an) * s2.mub) +
156  (1.0 - ae) * (an * s3.mub + (1.0 - an) * s1.mub);
157  res.mus = ae * (an * s4.mus + (1.0 - an) * s2.mus) +
158  (1.0 - ae) * (an * s3.mus + (1.0 - an) * s1.mus);
159  }
160 }
161 
162 HadronGasEos::HadronGasEos(bool tabulate, bool account_for_width)
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 }
182 
184  gsl_multiroot_fsolver_free(solver_);
185  gsl_vector_free(x_);
186 }
187 
189  double mu_over_T) {
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 }
201 
203  double beta, double mub, double mus,
204  bool account_for_width) {
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;
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 }
233 
234 double HadronGasEos::partial_density(const ParticleType &ptype, double T,
235  double mub, double mus,
236  bool account_for_width) {
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 }
243 
244 double HadronGasEos::energy_density(double T, double mub, double mus) {
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 }
271 
272 double HadronGasEos::density(double T, double mub, double mus,
273  bool account_for_width) {
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 }
288 
289 double HadronGasEos::net_baryon_density(double T, double mub, double mus,
290  bool account_for_width) {
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 }
306 
307 double HadronGasEos::net_strange_density(double T, double mub, double mus,
308  bool account_for_width) {
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 }
324 
326  double beta) {
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 }
395 
396 double HadronGasEos::mus_net_strangeness0(double T, double mub) {
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 }
419 
420 int HadronGasEos::set_eos_solver_equations(const gsl_vector *x, void *params,
421  gsl_vector *f) {
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 }
437 
438 double HadronGasEos::e_equation(double T, void *params) {
439  const double edens = reinterpret_cast<struct eparams *>(params)->edens;
440  return edens - energy_density(T, 0.0, 0.0);
441 }
442 
443 std::array<double, 3> HadronGasEos::solve_eos_initial_approximation(double e,
444  double nb) {
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 }
505 
506 std::array<double, 3> HadronGasEos::solve_eos(
507  double e, double nb, double ns,
508  std::array<double, 3> initial_approximation) {
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 }
552 
553 std::string HadronGasEos::print_solver_state(size_t iter) const {
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 }
566 
567 } // namespace smash
smash::HadronGasEos
Class to handle the equation of state (EoS) of the hadron gas, consisting of all hadrons included int...
Definition: hadgas_eos.h:112
smash
Definition: action.h:24
smash::EosTable::table_element::T
double T
Temperature.
Definition: hadgas_eos.h:59
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::ParticleType::width_at_pole
double width_at_pole() const
Definition: particletype.h:150
smash::ParticleType::min_mass_spectral
double min_mass_spectral() const
The minimum mass of the resonance, where the spectral function is non-zero.
Definition: particletype.cc:374
pow.h
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::partial_density
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.
Definition: hadgas_eos.cc:234
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::eparams
Another structure for passing energy density to the gnu library.
Definition: hadgas_eos.h:334
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::EosTable::index
size_t index(size_t ie, size_t inb) const
proper index in a 1d vector, where the 2d table is stored
Definition: hadgas_eos.h:87
smash::Integrator
A C++ interface for numerical integration in one dimension with the GSL CQUAD integration functions.
Definition: integrate.h:106
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::EosTable::n_e_
size_t n_e_
Number of steps in energy density.
Definition: hadgas_eos.h:95
smash::HadronGasEos::e_equation
static double e_equation(double T, void *params)
Definition: hadgas_eos.cc:438
smash::ParticleType::mass
double mass() const
Definition: particletype.h:144
smash::EosTable::dnb_
double dnb_
Step in net-baryon density.
Definition: hadgas_eos.h:93
smash::EosTable::table_element::p
double p
Pressure.
Definition: hadgas_eos.h:57
smash::ParticleType::spectral_function
double spectral_function(double m) const
Full spectral function of the resonance (relativistic Breit-Wigner distribution with mass-dependent ...
Definition: particletype.cc:577
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::HadronGasEos::HadronGasEos
HadronGasEos(bool tabulate, bool account_for_widths)
Constructor of HadronGasEos.
Definition: hadgas_eos.cc:162
smash::ParticleType::spin
unsigned int spin() const
Definition: particletype.h:191
smash::DisableFloatTraps
Guard type that safely disables floating point traps for the scope in which it is placed.
Definition: fpenvironment.h:79
smash::EosTable::table_element::mub
double mub
Net baryochemical potential.
Definition: hadgas_eos.h:61
smash::EosTable::EosTable
EosTable(double de, double dnb, size_t n_e, size_t n_b)
Sets up a table p/T/muB/mus versus (e, nb), where e is energy density, nb is net baryon density,...
Definition: hadgas_eos.cc:30
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
random.h
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
forwarddeclarations.h
smash::EosTable::n_nb_
size_t n_nb_
Number of steos in net-baryon density.
Definition: hadgas_eos.h:97
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::sample_mass_thermal
static double sample_mass_thermal(const ParticleType &ptype, double beta)
Sample resonance mass in a thermal medium.
Definition: hadgas_eos.cc:325
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::ParticleType::is_stable
bool is_stable() const
Definition: particletype.h:236
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::ParticleType
Definition: particletype.h:97
smash::ParticleType::spectral_function_simple
double spectral_function_simple(double m) const
This one is the most simple form of the spectral function, using a Cauchy distribution (non-relativis...
Definition: particletype.cc:617
smash::ParticleType::name
const std::string & name() const
Definition: particletype.h:141
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::EosTable::table_element::mus
double mus
Net strangeness potential.
Definition: hadgas_eos.h:63
smash::HadronGasEos::~HadronGasEos
~HadronGasEos()
Definition: hadgas_eos.cc:183
smash::HadronGasEos::mus_net_strangeness0
static double mus_net_strangeness0(double T, double mub)
Compute strangeness chemical potential, requiring that net strangeness = 0.
Definition: hadgas_eos.cc:396
smash::EosTable::table_element
Define the data structure for one element of the table.
Definition: hadgas_eos.h:55
fpenvironment.h
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
integrate.h
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
constants.h
logging.h
smash::ParticleType::strangeness
int strangeness() const
Definition: particletype.h:209
smash::EosTable::de_
double de_
Step in energy density.
Definition: hadgas_eos.h:91
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
hadgas_eos.h
smash::EosTable::table_
std::vector< table_element > table_
Storage for the tabulated equation of state.
Definition: hadgas_eos.h:89
smash::HadronGasEos::pressure
static double pressure(double T, double mub, double mus, bool account_for_resonance_widths=false)
Compute pressure .
Definition: hadgas_eos.h:180
smash::HadronGasEos::rparams
A structure for passing equation parameters to the gnu library.
Definition: hadgas_eos.h:322
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
smash::ParticleType::baryon_number
int baryon_number() const
Definition: particletype.h:206