Version: SMASH-1.5
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 
29 EosTable::EosTable(double de, double dnb, size_t n_e, size_t n_nb)
30  : de_(de), dnb_(dnb), n_e_(n_e), n_nb_(n_nb) {
31  table_.resize(n_e_ * n_nb_);
32 }
33 
35  const std::string &eos_savefile_name) {
36  bool table_read_success = false, table_consistency = true;
37  if (boost::filesystem::exists(eos_savefile_name)) {
38  std::cout << "Reading table from file " << eos_savefile_name << std::endl;
39  std::ifstream file;
40  file.open(eos_savefile_name, std::ios::in);
41  file >> de_ >> dnb_;
42  file >> n_e_ >> n_nb_;
43  table_.resize(n_e_ * n_nb_);
44  for (size_t ie = 0; ie < n_e_; ie++) {
45  for (size_t inb = 0; inb < n_nb_; inb++) {
46  double p, T, mub, mus;
47  file >> p >> T >> mub >> mus;
48  table_[index(ie, inb)] = {p, T, mub, mus};
49  }
50  }
51  table_read_success = true;
52  std::cout << "Table consumed successfully." << std::endl;
53  }
54 
55  if (table_read_success) {
56  // Check if the saved table is consistent with the current particle table
57  std::cout << "Checking consistency of the table... " << std::endl;
58  constexpr size_t number_of_steps = 50;
59  const size_t ie_step = 1 + n_e_ / number_of_steps;
60  const size_t inb_step = 1 + n_nb_ / number_of_steps;
61  for (size_t ie = 0; ie < n_e_; ie += ie_step) {
62  for (size_t inb = 0; inb < n_nb_; inb += inb_step) {
63  const table_element x = table_[index(ie, inb)];
64  const double e_comp = eos.energy_density(x.T, x.mub, x.mus);
65  const double nb_comp = eos.net_baryon_density(x.T, x.mub, x.mus);
66  const double ns_comp = eos.net_strange_density(x.T, x.mub, x.mus);
67  const double p_comp = eos.pressure(x.T, x.mub, x.mus);
68  // Precision is just 10^-3, this is precision of saved data in the file
69  const double eps = 1.e-3;
70  // Only check the physical region, hence T > 0 condition
71  if ((std::abs(de_ * ie - e_comp) > eps ||
72  std::abs(dnb_ * inb - nb_comp) > eps || std::abs(ns_comp) > eps ||
73  std::abs(x.p - p_comp) > eps) &&
74  (x.T > 0.0)) {
75  std::cout << "discrepancy: " << de_ * ie << " = " << e_comp << ", "
76  << dnb_ * inb << " = " << nb_comp << ", " << x.p << " = "
77  << p_comp << ", 0 = " << ns_comp << std::endl;
78  table_consistency = false;
79  goto finish_consistency_check;
80  }
81  }
82  }
83  }
84 finish_consistency_check:
85 
86  if (!table_read_success || !table_consistency) {
87  std::cout << "Compiling an EoS table..." << std::endl;
88  const double ns = 0.0;
89  for (size_t ie = 0; ie < n_e_; ie++) {
90  const double e = de_ * ie;
91  for (size_t inb = 0; inb < n_nb_; inb++) {
92  const double nb = dnb_ * inb;
93  // It is physically impossible to have energy density > nucleon mass*nb,
94  // therefore eqns have no solutions.
95  if (nb >= e) {
96  table_[index(ie, inb)] = {0.0, 0.0, 0.0, 0.0};
97  continue;
98  }
99  // Take extrapolated (T, mub, mus) as initial approximation
100  std::array<double, 3> init_approx;
101  if (inb >= 2) {
102  const table_element y = table_[index(ie, inb - 2)];
103  const table_element x = table_[index(ie, inb - 1)];
104  init_approx = {2.0 * x.T - y.T, 2.0 * x.mub - y.mub,
105  2.0 * x.mus - y.mus};
106  } else {
107  init_approx = eos.solve_eos_initial_approximation(e, nb);
108  }
109  const std::array<double, 3> res = eos.solve_eos(e, nb, ns, init_approx);
110  const double T = res[0];
111  const double mub = res[1];
112  const double mus = res[2];
113  table_[index(ie, inb)] = {eos.pressure(T, mub, mus), T, mub, mus};
114  }
115  }
116  // Save table to file
117  std::cout << "Saving table to file " << eos_savefile_name << std::endl;
118  std::ofstream file;
119  file.open(eos_savefile_name, std::ios::out);
120  file << de_ << " " << dnb_ << std::endl;
121  file << n_e_ << " " << n_nb_ << std::endl;
122  file << std::setprecision(7);
123  file << std::fixed;
124  for (size_t ie = 0; ie < n_e_; ie++) {
125  for (size_t inb = 0; inb < n_nb_; inb++) {
126  const EosTable::table_element x = table_[index(ie, inb)];
127  file << x.p << " " << x.T << " " << x.mub << " " << x.mus << std::endl;
128  }
129  }
130  }
131 }
132 
133 void EosTable::get(EosTable::table_element &res, double e, double nb) const {
134  const size_t ie = static_cast<size_t>(std::floor(e / de_));
135  const size_t inb = static_cast<size_t>(std::floor(nb / dnb_));
136 
137  if (ie >= n_e_ - 1 || inb >= n_nb_ - 1) {
138  res = {-1.0, -1.0, -1.0, -1.0};
139  } else {
140  // 1st order interpolation
141  const double ae = e / de_ - ie;
142  const double an = nb / dnb_ - inb;
143  const EosTable::table_element s1 = table_[index(ie, inb)];
144  const EosTable::table_element s2 = table_[index(ie + 1, inb)];
145  const EosTable::table_element s3 = table_[index(ie, inb + 1)];
146  const EosTable::table_element s4 = table_[index(ie + 1, inb + 1)];
147  res.p = ae * (an * s4.p + (1.0 - an) * s2.p) +
148  (1.0 - ae) * (an * s3.p + (1.0 - an) * s1.p);
149  res.T = ae * (an * s4.T + (1.0 - an) * s2.T) +
150  (1.0 - ae) * (an * s3.T + (1.0 - an) * s1.T);
151  res.mub = ae * (an * s4.mub + (1.0 - an) * s2.mub) +
152  (1.0 - ae) * (an * s3.mub + (1.0 - an) * s1.mub);
153  res.mus = ae * (an * s4.mus + (1.0 - an) * s2.mus) +
154  (1.0 - ae) * (an * s3.mus + (1.0 - an) * s1.mus);
155  }
156 }
157 
158 HadronGasEos::HadronGasEos(const bool tabulate)
159  : x_(gsl_vector_alloc(n_equations_)), tabulate_(tabulate) {
160  const gsl_multiroot_fsolver_type *solver_type;
161  solver_type = gsl_multiroot_fsolver_hybrid;
162  solver_ = gsl_multiroot_fsolver_alloc(solver_type, n_equations_);
163  if (tabulate_) {
164  eos_table_.compile_table(*this);
165  }
166 }
167 
169  gsl_multiroot_fsolver_free(solver_);
170  gsl_vector_free(x_);
171 }
172 
174  double mu_over_T) {
175  double x = mu_over_T - m_over_T;
176  if (x < -500.0) {
177  return 0.0;
178  }
179  x = std::exp(x);
180  // In the case of small masses: K_n(z) -> (n-1)!/2 *(2/z)^n, z -> 0,
181  // z*z*K_2(z) -> 2
182  return (m_over_T < really_small)
183  ? 2.0 * x
184  : m_over_T * m_over_T * x * gsl_sf_bessel_Kn_scaled(2, m_over_T);
185 }
186 
188  double beta, double mub,
189  double mus) {
190  const double m_over_T = ptype.mass() * beta;
191  double mu_over_T =
192  beta * (ptype.baryon_number() * mub + ptype.strangeness() * mus);
193  const double g = ptype.spin() + 1;
194  if (ptype.is_stable()) {
195  return g * scaled_partial_density_auxiliary(m_over_T, mu_over_T);
196  } else {
197  // Integral \int_{threshold}^{\infty} A(m) N_{thermal}(m) dm,
198  // where A(m) is the spectral function of the resonance.
199  const double m0 = ptype.mass();
200  const double w0 = ptype.width_at_pole();
201  const double mth = ptype.min_mass_spectral();
202  const double u_min = std::atan(2.0 * (mth - m0) / w0);
203  const double u_max = 0.5 * M_PI;
205  const double result =
206  g * integrate(u_min, u_max, [&](double u) {
207  // One of many possible variable substitutions. Not clear if it has
208  // any advantages, except transforming (m_th, inf) to finite interval.
209  const double tanu = std::tan(u);
210  const double m = m0 + 0.5 * w0 * tanu;
211  const double jacobian = 0.5 * w0 * (1.0 + tanu * tanu);
212  return ptype.spectral_function(m) * jacobian *
213  scaled_partial_density_auxiliary(m * beta, mu_over_T);
214  });
215  return result;
216  }
217 }
218 
219 double HadronGasEos::partial_density(const ParticleType &ptype, double T,
220  double mub, double mus) {
221  if (T < really_small) {
222  return 0.0;
223  }
224  return prefactor_ * T * T * T *
225  scaled_partial_density(ptype, 1.0 / T, mub, mus);
226 }
227 
228 double HadronGasEos::energy_density(double T, double mub, double mus) {
229  if (T < really_small) {
230  return 0.0;
231  }
232  const double beta = 1.0 / T;
233  double e = 0.0;
234  for (const ParticleType &ptype : ParticleType::list_all()) {
235  if (!is_eos_particle(ptype)) {
236  continue;
237  }
238  const double z = ptype.mass() * beta;
239  double x = beta * (mub * ptype.baryon_number() + mus * ptype.strangeness() -
240  ptype.mass());
241  if (x < -500.0) {
242  return 0.0;
243  }
244  x = std::exp(x);
245  const size_t g = ptype.spin() + 1;
246  // Small mass case, z*z*K_2(z) -> 2, z*z*z*K_1(z) -> 0 at z->0
247  e += (z < really_small) ? 3.0 * g * x
248  : z * z * g * x *
249  (3.0 * gsl_sf_bessel_Kn_scaled(2, z) +
250  z * gsl_sf_bessel_K1_scaled(z));
251  }
252  e *= prefactor_ * T * T * T * T;
253  return e;
254 }
255 
256 double HadronGasEos::density(double T, double mub, double mus) {
257  if (T < really_small) {
258  return 0.0;
259  }
260  const double beta = 1.0 / T;
261  double rho = 0.0;
262  for (const ParticleType &ptype : ParticleType::list_all()) {
263  if (!is_eos_particle(ptype)) {
264  continue;
265  }
266  rho += scaled_partial_density(ptype, beta, mub, mus);
267  }
268  rho *= prefactor_ * T * T * T;
269  return rho;
270 }
271 
272 double HadronGasEos::net_baryon_density(double T, double mub, double mus) {
273  if (T < really_small) {
274  return 0.0;
275  }
276  const double beta = 1.0 / T;
277  double rho = 0.0;
278  for (const ParticleType &ptype : ParticleType::list_all()) {
279  if (!ptype.is_baryon() || !is_eos_particle(ptype)) {
280  continue;
281  }
282  rho +=
283  scaled_partial_density(ptype, beta, mub, mus) * ptype.baryon_number();
284  }
285  rho *= prefactor_ * T * T * T;
286  return rho;
287 }
288 
289 double HadronGasEos::net_strange_density(double T, double mub, double mus) {
290  if (T < really_small) {
291  return 0.0;
292  }
293  const double beta = 1.0 / T;
294  double rho = 0.0;
295  for (const ParticleType &ptype : ParticleType::list_all()) {
296  if (ptype.strangeness() == 0 || !is_eos_particle(ptype)) {
297  continue;
298  }
299  rho += scaled_partial_density(ptype, beta, mub, mus) * ptype.strangeness();
300  }
301  rho *= prefactor_ * T * T * T;
302  return rho;
303 }
304 
306  double beta) {
307  if (ptype.is_stable()) {
308  return ptype.mass();
309  }
310  // Sampling mass m from A(m) x^2 BesselK_2(x), where x = beta m.
311  // Strategy employs the idea of importance sampling:
312  // -- Sample mass from the simple Breit-Wigner first, then
313  // reject by the ratio.
314  // -- Note that f(x) = x^2 BesselK_2(x) monotonously decreases
315  // and has maximum at x = xmin. That is why instead of f(x)
316  // the ratio f(x)/f(xmin) is used.
317 
318  const double max_mass = 5.0; // GeV
319  double m, q;
320  {
321  // Allow underflows in exponentials
322  DisableFloatTraps guard(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
323  const double w0 = ptype.width_at_pole();
324  const double mth = ptype.min_mass_spectral();
325  const double m0 = ptype.mass();
326  double max_ratio =
327  m0 * m0 * std::exp(-beta * m0) * gsl_sf_bessel_Kn_scaled(2, m0 * beta) *
328  ptype.spectral_function(m0) / ptype.spectral_function_simple(m0);
329  // Heuristic adaptive maximum search to find max_ratio
330  constexpr int npoints = 31;
331  double m_lower = mth, m_upper = max_mass, m_where_max = m0;
332 
333  for (size_t n_iterations = 0; n_iterations < 2; n_iterations++) {
334  const double dm = (m_upper - m_lower) / npoints;
335  for (size_t i = 1; i < npoints; i++) {
336  m = m_lower + dm * i;
337  const double thermal_factor =
338  m * m * std::exp(-beta * m) * gsl_sf_bessel_Kn_scaled(2, m * beta);
339  q = ptype.spectral_function(m) * thermal_factor /
340  ptype.spectral_function_simple(m);
341  if (q > max_ratio) {
342  max_ratio = q;
343  m_where_max = m;
344  }
345  }
346  m_lower = m_where_max - (m_where_max - m_lower) * 0.1;
347  m_upper = m_where_max + (m_upper - m_where_max) * 0.1;
348  }
349  // Safety factor
350  max_ratio *= 1.5;
351 
352  do {
353  // sample mass from A(m)
354  do {
355  m = random::cauchy(m0, 0.5 * w0, mth, max_mass);
356  const double thermal_factor =
357  m * m * std::exp(-beta * m) * gsl_sf_bessel_Kn_scaled(2, m * beta);
358  q = ptype.spectral_function(m) * thermal_factor /
359  ptype.spectral_function_simple(m);
360  } while (q < random::uniform(0., max_ratio));
361  if (q > max_ratio) {
362  const auto &log = logger<LogArea::Resonances>();
363  log.warn(ptype.name(), " - maximum increased in",
364  " sample_mass_thermal from ", max_ratio, " to ", q,
365  ", mass = ", m,
366  " previously assumed maximum at m = ", m_where_max);
367  max_ratio = q;
368  m_where_max = m;
369  } else {
370  break;
371  }
372  } while (true);
373  }
374  return m;
375 }
376 
377 double HadronGasEos::mus_net_strangeness0(double T, double mub) {
378  // Binary search
379  double mus_u = mub + T;
380  double mus_l = 0.0;
381  double mus, rhos;
382  size_t iteration = 0;
383  // 50 iterations should give precision 2^-50 ~ 10^-15
384  const size_t max_iteration = 50;
385  do {
386  mus = 0.5 * (mus_u + mus_l);
387  rhos = net_strange_density(T, mub, mus);
388  if (rhos > 0.0) {
389  mus_u = mus;
390  } else {
391  mus_l = mus;
392  }
393  iteration++;
394  } while (std::abs(rhos) > tolerance_ && iteration < max_iteration);
395  if (iteration == max_iteration) {
396  throw std::runtime_error("Solving rho_s = 0: too many iterations.");
397  }
398  return mus;
399 }
400 
401 int HadronGasEos::set_eos_solver_equations(const gsl_vector *x, void *params,
402  gsl_vector *f) {
403  double e = reinterpret_cast<struct rparams *>(params)->e;
404  double nb = reinterpret_cast<struct rparams *>(params)->nb;
405  double ns = reinterpret_cast<struct rparams *>(params)->ns;
406 
407  const double T = gsl_vector_get(x, 0);
408  const double mub = gsl_vector_get(x, 1);
409  const double mus = gsl_vector_get(x, 2);
410 
411  gsl_vector_set(f, 0, energy_density(T, mub, mus) - e);
412  gsl_vector_set(f, 1, net_baryon_density(T, mub, mus) - nb);
413  gsl_vector_set(f, 2, net_strange_density(T, mub, mus) - ns);
414 
415  return GSL_SUCCESS;
416 }
417 
418 double HadronGasEos::e_equation(double T, void *params) {
419  const double edens = reinterpret_cast<struct eparams *>(params)->edens;
420  return edens - energy_density(T, 0.0, 0.0);
421 }
422 
423 std::array<double, 3> HadronGasEos::solve_eos_initial_approximation(double e,
424  double nb) {
425  assert(e >= 0.0);
426  // 1. Get temperature from energy density assuming zero chemical potentials
427  int degeneracies_sum = 0.0;
428  for (const ParticleType &ptype : ParticleType::list_all()) {
429  if (is_eos_particle(ptype)) {
430  degeneracies_sum += ptype.spin() + 1;
431  }
432  }
433  // Temperature in case of massless gas. For massive it should be larger.
434  const double T_min = std::pow(e / prefactor_ / 6 / degeneracies_sum, 1. / 4.);
435  // Simply assume that the temperature is not higher than 2 GeV.
436  const double T_max = 2.0;
437 
438  struct eparams parameters = {e};
439  gsl_function F = {&e_equation, &parameters};
440  const gsl_root_fsolver_type *T = gsl_root_fsolver_brent;
441  gsl_root_fsolver *e_solver;
442  e_solver = gsl_root_fsolver_alloc(T);
443  gsl_root_fsolver_set(e_solver, &F, T_min, T_max);
444 
445  int iter = 0, status, max_iter = 100;
446  double T_init = 0.0;
447 
448  do {
449  iter++;
450  status = gsl_root_fsolver_iterate(e_solver);
451  if (status != GSL_SUCCESS) {
452  break;
453  }
454  T_init = gsl_root_fsolver_root(e_solver);
455  double x_lo = gsl_root_fsolver_x_lower(e_solver);
456  double x_hi = gsl_root_fsolver_x_upper(e_solver);
457  status = gsl_root_test_interval(x_lo, x_hi, 0.0, 0.001);
458  } while (status == GSL_CONTINUE && iter < max_iter);
459 
460  if (status != GSL_SUCCESS) {
461  std::stringstream err_msg;
462  err_msg << "Solver of equation for temperature with e = " << e
463  << " failed to converge. Maybe Tmax = " << T_max << " is too small?"
464  << std::endl;
465  throw std::runtime_error(gsl_strerror(status) + err_msg.str());
466  }
467 
468  gsl_root_fsolver_free(e_solver);
469 
470  // 2. Get the baryon chemical potential for mus = 0 and previously obtained T
471  double n_only_baryons = 0.0;
472  for (const ParticleType &ptype : ParticleType::list_all()) {
473  if (is_eos_particle(ptype) && ptype.baryon_number() == 1) {
474  n_only_baryons += scaled_partial_density(ptype, 1.0 / T_init, 0.0, 0.0);
475  }
476  }
477  const double nb_scaled = nb / prefactor_ / (T_init * T_init * T_init);
478  double mub_init = T_init * std::asinh(nb_scaled / n_only_baryons / 2.0);
479 
480  // 3. mus = 0 is typically a good initial approximation
481 
482  std::array<double, 3> initial_approximation = {T_init, mub_init, 0.0};
483  return initial_approximation;
484 }
485 
486 std::array<double, 3> HadronGasEos::solve_eos(
487  double e, double nb, double ns,
488  std::array<double, 3> initial_approximation) {
489  int residual_status = GSL_SUCCESS;
490  size_t iter = 0;
491 
492  struct rparams p = {e, nb, ns};
493  gsl_multiroot_function f = {&HadronGasEos::set_eos_solver_equations,
494  n_equations_, &p};
495 
496  gsl_vector_set(x_, 0, initial_approximation[0]);
497  gsl_vector_set(x_, 1, initial_approximation[1]);
498  gsl_vector_set(x_, 2, initial_approximation[2]);
499 
500  gsl_multiroot_fsolver_set(solver_, &f, x_);
501  do {
502  iter++;
503  const auto iterate_status = gsl_multiroot_fsolver_iterate(solver_);
504  // std::cout << print_solver_state(iter);
505 
506  // Avoiding too low temperature
507  if (gsl_vector_get(solver_->x, 0) < 0.015) {
508  return {0.0, 0.0, 0.0};
509  }
510 
511  // check if solver is stuck
512  if (iterate_status) {
513  break;
514  }
515  residual_status = gsl_multiroot_test_residual(solver_->f, tolerance_);
516  } while (residual_status == GSL_CONTINUE && iter < 1000);
517 
518  if (residual_status != GSL_SUCCESS) {
519  std::stringstream solver_parameters;
520  solver_parameters << "Solver run with "
521  << "e = " << e << ", nb = " << nb << ", ns = " << ns
522  << ", init. approx.: " << initial_approximation[0] << " "
523  << initial_approximation[1] << " "
524  << initial_approximation[2] << std::endl;
525  throw std::runtime_error(gsl_strerror(residual_status) +
526  solver_parameters.str() +
527  print_solver_state(iter));
528  }
529 
530  return {gsl_vector_get(solver_->x, 0), gsl_vector_get(solver_->x, 1),
531  gsl_vector_get(solver_->x, 2)};
532 }
533 
534 std::string HadronGasEos::print_solver_state(size_t iter) const {
535  std::stringstream s;
536  // clang-format off
537  s << "iter = " << iter << ","
538  << " x = " << gsl_vector_get(solver_->x, 0) << " "
539  << gsl_vector_get(solver_->x, 1) << " "
540  << gsl_vector_get(solver_->x, 2) << ", "
541  << "f(x) = " << gsl_vector_get(solver_->f, 0) << " "
542  << gsl_vector_get(solver_->f, 1) << " "
543  << gsl_vector_get(solver_->f, 2) << std::endl;
544  // clang-format on
545  return s.str();
546 }
547 
548 } // namespace smash
double mass() const
Definition: particletype.h:134
HadronGasEos(const bool tabulate=false)
Constructor of HadronGasEos.
Definition: hadgas_eos.cc:158
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
double min_mass_spectral() const
The minimum mass of the resonance, where the spectral function is non-zero.
std::string print_solver_state(size_t iter) const
Helpful printout, useful for debugging if gnu equation solving goes crazy.
Definition: hadgas_eos.cc:534
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
double mub
Net baryochemical potential.
Definition: hadgas_eos.h:61
std::array< double, 3 > solve_eos(double e, double nb, double ns, std::array< double, 3 > initial_approximation)
Compute temperature and chemical potentials given energy-, net baryon-, net strangeness density and a...
Definition: hadgas_eos.cc:486
static double net_strange_density(double T, double mub, double mus)
Compute net strangeness density.
Definition: hadgas_eos.cc:289
Class to handle the equation of state (EoS) of the hadron gas, consisting of all hadrons included int...
Definition: hadgas_eos.h:112
Guard type that safely disables floating point traps for the scope in which it is placed...
Definition: fpenvironment.h:79
Collection of useful constants that are known at compile time.
double width_at_pole() const
Definition: particletype.h:140
static int set_eos_solver_equations(const gsl_vector *x, void *params, gsl_vector *f)
Interface EoS equations to be solved to gnu library.
Definition: hadgas_eos.cc:401
static double scaled_partial_density(const ParticleType &ptype, double beta, double mub, double mus)
Compute (unnormalized) density of one hadron sort - helper functions used to reduce code duplication...
Definition: hadgas_eos.cc:187
double mus
Net strangeness potential.
Definition: hadgas_eos.h:63
double T
Temperature.
Definition: hadgas_eos.h:59
double dnb_
Step in net-baryon density.
Definition: hadgas_eos.h:93
static constexpr size_t n_equations_
Number of equations in the system of equations to be solved.
Definition: hadgas_eos.h:346
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:29
double spectral_function(double m) const
Full spectral function of the resonance (relativistic Breit-Wigner distribution with mass-dependent ...
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:277
EosTable eos_table_
EOS Table to be used.
Definition: hadgas_eos.h:349
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions.
Definition: hadgas_eos.h:339
size_t n_nb_
Number of steos in net-baryon density.
Definition: hadgas_eos.h:97
static constexpr double tolerance_
Precision of equation solving.
Definition: hadgas_eos.h:343
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
size_t n_e_
Number of steps in energy density.
Definition: hadgas_eos.h:95
static double net_baryon_density(double T, double mub, double mus)
Compute net baryon density.
Definition: hadgas_eos.cc:272
static const ParticleTypeList & list_all()
Definition: particletype.cc:55
gsl_multiroot_fsolver * solver_
Definition: hadgas_eos.h:360
int baryon_number() const
Definition: particletype.h:196
bool is_stable() const
Definition: particletype.h:226
Particle type contains the static properties of a particle species.
Definition: particletype.h:87
A structure for passing equation parameters to the gnu library.
Definition: hadgas_eos.h:286
int strangeness() const
Definition: particletype.h:199
void get(table_element &res, double e, double nb) const
Obtain interpolated p/T/muB/muS from the tabulated equation of state given energy density and net bar...
Definition: hadgas_eos.cc:133
static double sample_mass_thermal(const ParticleType &ptype, double beta)
Sample resonance mass in a thermal medium.
Definition: hadgas_eos.cc:305
T uniform(T min, T max)
Definition: random.h:85
Define the data structure for one element of the table.
Definition: hadgas_eos.h:55
static double density(double T, double mub, double mus)
Compute particle number density.
Definition: hadgas_eos.cc:256
T cauchy(T pole, T width, T min, T max)
Draws a random number from a Cauchy distribution (sometimes also called Lorentz or non-relativistic B...
Definition: random.h:304
std::array< double, 3 > solve_eos_initial_approximation(double e, double nb)
Compute a reasonable initial approximation for solve_eos.
Definition: hadgas_eos.cc:423
gsl_vector * x_
Variables used by gnu equation solver.
Definition: hadgas_eos.h:357
unsigned int spin() const
Definition: particletype.h:181
constexpr int p
Proton.
static double partial_density(const ParticleType &ptype, double T, double mub, double mus)
Compute partial density of one hadron sort.
Definition: hadgas_eos.cc:219
A C++ interface for numerical integration in one dimension with the GSL CQUAD integration functions...
Definition: integrate.h:106
const bool tabulate_
Create an EoS table or not?
Definition: hadgas_eos.h:363
Another structure for passing energy density to the gnu library.
Definition: hadgas_eos.h:296
double spectral_function_simple(double m) const
This one is the most simple form of the spectral function, using a Cauchy distribution (non-relativis...
static double mus_net_strangeness0(double T, double mub)
Compute strangeness chemical potential, requiring that net strangeness = 0.
Definition: hadgas_eos.cc:377
static double scaled_partial_density_auxiliary(double m_over_T, double mu_over_T)
Function used to avoid duplications in density calculations.
Definition: hadgas_eos.cc:173
double de_
Step in energy density.
Definition: hadgas_eos.h:91
std::vector< table_element > table_
Storage for the tabulated equation of state.
Definition: hadgas_eos.h:89
static double e_equation(double T, void *params)
Definition: hadgas_eos.cc:418
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:326
static double pressure(double T, double mub, double mus)
Compute pressure .
Definition: hadgas_eos.h:159
Definition: action.h:24
static Integrator integrate
Definition: decaytype.cc:147
static double energy_density(double T, double mub, double mus)
Compute energy density.
Definition: hadgas_eos.cc:228
const std::string & name() const
Definition: particletype.h:131