10 #include <gsl/gsl_sf_bessel.h>    16 #include <boost/filesystem.hpp>    30     : de_(de), dnb_(dnb), n_e_(n_e), n_nb_(n_nb) {
    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;
    40     file.open(eos_savefile_name, std::ios::in);
    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;
    51     table_read_success = 
true;
    52     std::cout << 
"Table consumed successfully." << std::endl;
    55   if (table_read_success) {
    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) {
    69         const double eps = 1.e-3;
    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) &&
    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;
    84 finish_consistency_check:
    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;
   100         std::array<double, 3> init_approx;
   104           init_approx = {2.0 * x.
T - y.
T, 2.0 * x.
mub - y.
mub,
   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];
   117     std::cout << 
"Saving table to file " << eos_savefile_name << std::endl;
   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);
   124     for (
size_t ie = 0; ie < 
n_e_; ie++) {
   125       for (
size_t inb = 0; inb < 
n_nb_; inb++) {
   127         file << x.
p << 
" " << x.
T << 
" " << x.
mub << 
" " << x.
mus << std::endl;
   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_));
   137   if (ie >= 
n_e_ - 1 || inb >= 
n_nb_ - 1) {
   138     res = {-1.0, -1.0, -1.0, -1.0};
   141     const double ae = e / 
de_ - ie;
   142     const double an = nb / 
dnb_ - inb;
   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);
   159     : x_(gsl_vector_alloc(n_equations_)), tabulate_(tabulate) {
   160   const gsl_multiroot_fsolver_type *solver_type;
   161   solver_type = gsl_multiroot_fsolver_hybrid;
   169   gsl_multiroot_fsolver_free(
solver_);
   175   double x = mu_over_T - m_over_T;
   184              : m_over_T * m_over_T * x * gsl_sf_bessel_Kn_scaled(2, m_over_T);
   188                                             double beta, 
double mub,
   190   const double m_over_T = ptype.
mass() * 
beta;
   193   const double g = ptype.
spin() + 1;
   199     const double m0 = ptype.
mass();
   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) {
   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);
   220                                      double mub, 
double mus) {
   232   const double beta = 1.0 / T;
   238     const double z = ptype.mass() * 
beta;
   239     double x = beta * (mub * ptype.baryon_number() + mus * ptype.strangeness() -
   245     const size_t g = ptype.spin() + 1;
   249                                   (3.0 * gsl_sf_bessel_Kn_scaled(2, z) +
   250                                    z * gsl_sf_bessel_K1_scaled(z));
   260   const double beta = 1.0 / T;
   276   const double beta = 1.0 / T;
   293   const double beta = 1.0 / T;
   318   const double max_mass = 5.0;  
   325     const double m0 = ptype.
mass();
   327         m0 * m0 * std::exp(-beta * m0) * gsl_sf_bessel_Kn_scaled(2, m0 * beta) *
   330     constexpr 
int npoints = 31;
   331     double m_lower = mth, m_upper = max_mass, m_where_max = m0;
   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);
   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;
   356         const double thermal_factor =
   357             m * m * std::exp(-beta * m) * gsl_sf_bessel_Kn_scaled(2, m * beta);
   362         const auto &log = logger<LogArea::Resonances>();
   363         log.warn(ptype.
name(), 
" - maximum increased in",
   364                  " sample_mass_thermal from ", max_ratio, 
" to ", q,
   366                  " previously assumed maximum at m = ", m_where_max);
   379   double mus_u = mub + T;
   382   size_t iteration = 0;
   384   const size_t max_iteration = 50;
   386     mus = 0.5 * (mus_u + mus_l);
   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.");
   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;
   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);
   419   const double edens = 
reinterpret_cast<struct 
eparams *
>(params)->edens;
   427   int degeneracies_sum = 0.0;
   430       degeneracies_sum += ptype.spin() + 1;
   434   const double T_min = std::pow(e / 
prefactor_ / 6 / degeneracies_sum, 1. / 4.);
   436   const double T_max = 2.0;
   438   struct eparams parameters = {e};
   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);
   445   int iter = 0, status, max_iter = 100;
   450     status = gsl_root_fsolver_iterate(e_solver);
   451     if (status != GSL_SUCCESS) {
   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);
   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?"   465     throw std::runtime_error(gsl_strerror(status) + err_msg.str());
   468   gsl_root_fsolver_free(e_solver);
   471   double n_only_baryons = 0.0;
   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);
   482   std::array<double, 3> initial_approximation = {T_init, mub_init, 0.0};
   483   return initial_approximation;
   487     double e, 
double nb, 
double ns,
   488     std::array<double, 3> initial_approximation) {
   489   int residual_status = GSL_SUCCESS;
   492   struct rparams p = {e, nb, ns};
   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]);
   500   gsl_multiroot_fsolver_set(
solver_, &f, 
x_);
   503     const auto iterate_status = gsl_multiroot_fsolver_iterate(
solver_);
   507     if (gsl_vector_get(
solver_->x, 0) < 0.015) {
   508       return {0.0, 0.0, 0.0};
   512     if (iterate_status) {
   516   } 
while (residual_status == GSL_CONTINUE && iter < 1000);
   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() +
   530   return {gsl_vector_get(
solver_->x, 0), gsl_vector_get(
solver_->x, 1),
   531           gsl_vector_get(
solver_->x, 2)};
   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;
 HadronGasEos(const bool tabulate=false)
Constructor of HadronGasEos. 
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...
constexpr double really_small
Numerical error tolerance. 
double mub
Net baryochemical potential. 
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...
int baryon_number() const 
static double net_strange_density(double T, double mub, double mus)
Compute net strangeness density. 
Class to handle the equation of state (EoS) of the hadron gas, consisting of all hadrons included int...
Guard type that safely disables floating point traps for the scope in which it is placed...
Collection of useful constants that are known at compile time. 
static int set_eos_solver_equations(const gsl_vector *x, void *params, gsl_vector *f)
Interface EoS equations to be solved to gnu library. 
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...
double mus
Net strangeness potential. 
std::string print_solver_state(size_t iter) const 
Helpful printout, useful for debugging if gnu equation solving goes crazy. 
double dnb_
Step in net-baryon density. 
double spectral_function(double m) const 
Full spectral function  of the resonance (relativistic Breit-Wigner distribution with mass-dependent ...
static constexpr size_t n_equations_
Number of equations in the system of equations to be solved. 
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...
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS. 
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...
EosTable eos_table_
EOS Table to be used. 
static constexpr double prefactor_
Constant factor, that appears in front of many thermodyn. expressions. 
size_t n_nb_
Number of steos in net-baryon density. 
static constexpr double tolerance_
Precision of equation solving. 
size_t n_e_
Number of steps in energy density. 
static double net_baryon_density(double T, double mub, double mus)
Compute net baryon density. 
static const ParticleTypeList & list_all()
gsl_multiroot_fsolver * solver_
const std::string & name() const 
Particle type contains the static properties of a particle species. 
A structure for passing equation parameters to the gnu library. 
double min_mass_spectral() const 
The minimum mass of the resonance, where the spectral function is non-zero. 
size_t index(size_t ie, size_t inb) const 
proper index in a 1d vector, where the 2d table is stored 
static double sample_mass_thermal(const ParticleType &ptype, double beta)
Sample resonance mass in a thermal medium. 
Define the data structure for one element of the table. 
static double density(double T, double mub, double mus)
Compute particle number density. 
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...
std::array< double, 3 > solve_eos_initial_approximation(double e, double nb)
Compute a reasonable initial approximation for solve_eos. 
gsl_vector * x_
Variables used by gnu equation solver. 
static double partial_density(const ParticleType &ptype, double T, double mub, double mus)
Compute partial density of one hadron sort. 
double width_at_pole() const 
A C++ interface for numerical integration in one dimension with the GSL CQUAD integration functions...
const bool tabulate_
Create an EoS table or not? 
Another structure for passing energy density to the gnu library. 
static double mus_net_strangeness0(double T, double mub)
Compute strangeness chemical potential, requiring that net strangeness = 0. 
static double scaled_partial_density_auxiliary(double m_over_T, double mu_over_T)
Function used to avoid duplications in density calculations. 
double de_
Step in energy density. 
std::vector< table_element > table_
Storage for the tabulated equation of state. 
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 e_equation(double T, void *params)
unsigned int spin() const 
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of  is . 
static double pressure(double T, double mub, double mus)
Compute pressure . 
static Integrator integrate
static double energy_density(double T, double mub, double mus)
Compute energy density.