45   const int max_iter = 50;
 
   47   double e_previous_step = 0.0;
 
   48   const double tolerance = 5.e-4;
 
   50   for (iter = 0; iter < max_iter; iter++) {
 
   53     if (std::abs(
e_ - e_previous_step) < tolerance) {
 
   56     const double gamma_inv = std::sqrt(1.0 - 
v_.
sqr());
 
   62       T_ = T_mub_mus_muq[0];
 
   63       mub_ = T_mub_mus_muq[1];
 
   64       mus_ = T_mub_mus_muq[2];
 
   65       muq_ = T_mub_mus_muq[3];
 
   76   if (iter == max_iter) {
 
   77     std::cout << 
"Warning from solver: max iterations exceeded." 
   78               << 
" Accuracy: " << std::abs(
e_ - e_previous_step)
 
   79               << 
" is less than tolerance " << tolerance << std::endl;
 
   84                                                  double mus0, 
double muq0,
 
   99   return out << 
"T[mu,0]: " << node.
Tmu0() << 
", nb: " << node.
nb()
 
  100              << 
", ns: " << node.
ns() << 
", v: " << node.
v()
 
  101              << 
", e: " << node.
e() << 
", p: " << node.
p()
 
  102              << 
", T: " << node.
T() << 
", mub: " << node.
mub()
 
  103              << 
", mus: " << node.
mus() << 
", muq: " << node.
muq();
 
  107                                          const std::array<int, 3> n_cells,
 
  108                                          const std::array<double, 3> origin,
 
  109                                          bool periodicity, 
double e_critical,
 
  110                                          double t_start, 
double delta_t,
 
  112                                          bool BF_microcanonical)
 
  113     : eos_typelist_(list_eos_particles()),
 
  114       N_sorts_(eos_typelist_.size()),
 
  119       BF_enforce_microcanonical_(BF_microcanonical) {
 
  121   lat_ = make_unique<RectangularLattice<ThermLatticeNode>>(
 
  122       lat_sizes, n_cells, origin, periodicity, upd);
 
  123   const std::array<double, 3> abc = 
lat_->cell_sizes();
 
  132     bool ignore_cells_under_treshold) {
 
  136   for (
auto &node : *
lat_) {
 
  140     if (!ignore_cells_under_treshold ||
 
  141         node.Tmu0().x0() + std::abs(node.Tmu0().x1()) +
 
  142                 std::abs(node.Tmu0().x2()) + std::abs(node.Tmu0().x3()) >=
 
  144       node.compute_rest_frame_quantities(
eos_);
 
  153                                      +0.5 * 
lat_->cell_sizes()[0]),
 
  155                                      +0.5 * 
lat_->cell_sizes()[1]),
 
  157                                      +0.5 * 
lat_->cell_sizes()[2]));
 
  161     ParticleList &plist, 
const FourVector required_total_momentum) {
 
  165                                   required_total_momentum);
 
  171   for (
auto &particle : plist) {
 
  172     particle.set_4momentum(particle.type().mass(),
 
  173                            particle.momentum().threevec() + mom_to_add);
 
  182   double E_expected = required_total_momentum.
abs();
 
  183   for (
auto &particle : plist) {
 
  184     particle.boost_momentum(beta_CM_generated);
 
  185     E += particle.momentum().x0();
 
  189   double a, a_min, a_max, er;
 
  190   const int max_iter = 100;
 
  192   if (E_expected >= E) {
 
  200     a = 0.5 * (a_min + a_max);
 
  202     for (
const auto &particle : plist) {
 
  203       const double p2 = particle.momentum().threevec().sqr();
 
  204       const double E2 = particle.momentum().x0() * particle.momentum().x0();
 
  205       E += std::sqrt(E2 + a * (a + 2.0) * p2);
 
  216   } 
while (std::abs(er) > tolerance && iter < max_iter);
 
  220   for (
auto &particle : plist) {
 
  221     particle.set_4momentum(particle.type().mass(),
 
  222                            (1 + a) * particle.momentum().threevec());
 
  223     particle.boost_momentum(-beta_CM_required);
 
  234   for (
size_t i_type = 0; (i_type < 
N_sorts_) && (N_to_sample > 0); i_type++) {
 
  235     if (
get_class(i_type) != particle_class) {
 
  259     const double gamma = 1.0 / std::sqrt(1.0 - cell.
v().
sqr());
 
  260     const double N_this_cell =
 
  268   for (
int i = 0; i < 
mult_int_[type_index]; i++) {
 
  271     double partial_sum = 0.0;
 
  272     int index_only_thermalized = -1;
 
  273     while (partial_sum < r) {
 
  274       index_only_thermalized++;
 
  275       partial_sum += 
N_in_cells_[index_only_thermalized];
 
  294     plist.push_back(particle);
 
  299                                              double time, 
int ntest) {
 
  303     const double gamma = 1.0 / std::sqrt(1.0 - cell.
v().
sqr());
 
  304     for (
size_t i = 0; i < 
N_sorts_; i++) {
 
  314   for (
size_t i = 0; i < 
N_sorts_; i++) {
 
  325     const auto Nbar_antibar = bessel_sampler_B.
sample();
 
  332     for (
size_t i = 0; i < 
N_sorts_; i++) {
 
  336     std::pair<int, int> NS_antiS;
 
  342       NS_antiS = bessel_sampler_S.
sample();
 
  344       NS_antiS = std::make_pair(
 
  347       if (NS_antiS.first - NS_antiS.second !=
 
  357     for (
size_t i = 0; i < 
N_sorts_; i++) {
 
  361     std::pair<int, int> NC_antiC;
 
  366           conserved_initial.
charge() - ch_sampled);
 
  367       NC_antiC = bessel_sampler_C.
sample();
 
  369       NC_antiC = std::make_pair(
 
  372       if (NC_antiC.first - NC_antiC.second !=
 
  373           conserved_initial.
charge() - ch_sampled) {
 
  384     for (
size_t itype = 0; itype < 
N_sorts_; itype++) {
 
  389       const double e_init = conserved_initial.
momentum().
x0();
 
  392         e_tot += particle.momentum().x0();
 
  394       if (std::abs(e_tot - e_init) > 0.01 * e_init) {
 
  396                                         " too far from ", e_init);
 
  407   int S_plus = 0, S_minus = 0, B_plus = 0, B_minus = 0, E_plus = 0, E_minus = 0;
 
  409   auto condition1 = [](int, int, int) { 
return true; };
 
  411   while (conserved_initial.
momentum().
x0() > energy ||
 
  414     energy += 
p.momentum().x0();
 
  415     if (
p.pdgcode().strangeness() > 0) {
 
  417       S_plus += 
p.pdgcode().strangeness();
 
  422   auto condition2 = [](
int S, int, int) { 
return (
S < 0); };
 
  424   while (S_plus + S_minus > conserved_initial.
strangeness()) {
 
  426     const int s_part = 
p.pdgcode().strangeness();
 
  428     if (S_plus + S_minus + s_part >= conserved_initial.
strangeness()) {
 
  435   auto condition3 = [](
int S, int, int) { 
return (
S == 0); };
 
  440   while (conserved_remaining.
momentum().
x0() > energy ||
 
  443     energy += 
p.momentum().x0();
 
  444     if (
p.pdgcode().baryon_number() > 0) {
 
  446       B_plus += 
p.pdgcode().baryon_number();
 
  451   auto condition4 = [](
int S, 
int B, int) { 
return (
S == 0) && (B < 0); };
 
  453   while (B_plus + B_minus > conserved_remaining.
baryon_number()) {
 
  455     const int bar = 
p.pdgcode().baryon_number();
 
  456     if (B_plus + B_minus + bar >= conserved_remaining.
baryon_number()) {
 
  463   auto condition5 = [](
int S, 
int B, int) { 
return (
S == 0) && (B == 0); };
 
  467   while (conserved_remaining.
momentum().
x0() > energy ||
 
  468          E_plus < conserved_remaining.
charge()) {
 
  470     energy += 
p.momentum().x0();
 
  471     if (
p.pdgcode().charge() > 0) {
 
  473       E_plus += 
p.pdgcode().charge();
 
  478   auto condition6 = [](
int S, 
int B, 
int C) {
 
  479     return (
S == 0) && (B == 0) && (C < 0);
 
  482   while (E_plus + E_minus > conserved_remaining.
charge()) {
 
  484     const int charge = 
p.pdgcode().charge();
 
  485     if (E_plus + E_minus + charge >= conserved_remaining.
charge()) {
 
  492   auto condition7 = [](
int S, 
int B, 
int C) {
 
  493     return (
S == 0) && (B == 0) && (C == 0);
 
  498   while (conserved_remaining.
momentum().
x0() > energy) {
 
  501     energy += 
p.momentum().x0();
 
  515   for (
auto &particle : particles) {
 
  516     const bool is_on_lattice =
 
  517         lat_->value_at(particle.position().threevec(), node);
 
  518     if (is_on_lattice && node.
e() > 
e_crit_) {
 
  540   const size_t lattice_total_cells = 
lat_->size();
 
  541   for (
size_t i = 0; i < lattice_total_cells; i++) {
 
  547       "Number of cells in the thermalization region = ",
 
  550       ", in % of lattice: ",
 
  562       throw std::invalid_argument(
 
  563           "This thermalization algorithm is" 
  564           " not yet implemented");
 
  583   struct to_average on_lattice = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
 
  584   struct to_average in_therm_reg = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
 
  585   double e_sum_on_lattice = 0.0, e_sum_in_therm_reg = 0.0;
 
  586   int node_counter = 0;
 
  587   for (
const auto &node : *
lat_) {
 
  588     const double e = node.e();
 
  589     on_lattice.T += node.T() * e;
 
  590     on_lattice.mub += node.mub() * e;
 
  591     on_lattice.mus += node.mus() * e;
 
  592     on_lattice.muq += node.muq() * e;
 
  593     on_lattice.nb += node.nb() * e;
 
  594     on_lattice.ns += node.ns() * e;
 
  595     on_lattice.nq += node.nq() * e;
 
  596     e_sum_on_lattice += e;
 
  598       in_therm_reg.T += node.T() * e;
 
  599       in_therm_reg.mub += node.mub() * e;
 
  600       in_therm_reg.mus += node.mus() * e;
 
  601       in_therm_reg.muq += node.muq() * e;
 
  602       in_therm_reg.nb += node.nb() * e;
 
  603       in_therm_reg.ns += node.ns() * e;
 
  604       in_therm_reg.nq += node.nq() * e;
 
  605       e_sum_in_therm_reg += e;
 
  610     on_lattice.T /= e_sum_on_lattice;
 
  611     on_lattice.mub /= e_sum_on_lattice;
 
  612     on_lattice.mus /= e_sum_on_lattice;
 
  613     on_lattice.muq /= e_sum_on_lattice;
 
  614     on_lattice.nb /= e_sum_on_lattice;
 
  615     on_lattice.ns /= e_sum_on_lattice;
 
  616     on_lattice.nq /= e_sum_on_lattice;
 
  619     in_therm_reg.T /= e_sum_in_therm_reg;
 
  620     in_therm_reg.mub /= e_sum_in_therm_reg;
 
  621     in_therm_reg.mus /= e_sum_in_therm_reg;
 
  622     in_therm_reg.muq /= e_sum_in_therm_reg;
 
  623     in_therm_reg.nb /= e_sum_in_therm_reg;
 
  624     in_therm_reg.ns /= e_sum_in_therm_reg;
 
  625     in_therm_reg.nq /= e_sum_in_therm_reg;
 
  628   std::cout << 
"Current time [fm/c]: " << clock.
current_time() << std::endl;
 
  629   std::cout << 
"Averages on the lattice - T[GeV], mub[GeV], mus[GeV], muq[GeV] " 
  630             << 
"nb[fm^-3], ns[fm^-3], nq[fm^-3]: " << on_lattice.T << 
" " 
  631             << on_lattice.mub << 
" " << on_lattice.mus << 
" " << on_lattice.muq
 
  632             << 
" " << on_lattice.nb << 
" " << on_lattice.ns << 
" " 
  633             << on_lattice.nq << std::endl;
 
  635       << 
"Averages in therm. region - T[GeV], mub[GeV], mus[GeV], muq[GeV] " 
  636       << 
"nb[fm^-3], ns[fm^-3], nq[fm^-3]: " << in_therm_reg.T << 
" " 
  637       << in_therm_reg.mub << 
" " << in_therm_reg.mus << 
" " << in_therm_reg.muq
 
  638       << 
" " << in_therm_reg.nb << 
" " << in_therm_reg.ns << 
" " 
  639       << in_therm_reg.nq << std::endl;
 
  640   std::cout << 
"Volume with e > e_crit [fm^3]: " 
Angles provides a common interface for generating directions: i.e., two angles that should be interpr...
 
ThreeVector threevec() const
 
void distribute_isotropically()
Populate the object with a new direction.
 
Clock tracks the time in the simulation.
 
virtual double current_time() const =0
 
A class to pre-calculate and store parameters relevant for density calculation.
 
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
 
double abs() const
calculate the lorentz invariant absolute value
 
ThreeVector threevec() const
 
ThreeVector velocity() const
Get the velocity (3-vector divided by zero component).
 
void thermalize_BF_algo(QuantumNumbers &conserved_initial, double time, int ntest)
Samples particles according to the BF algorithm by making use of the.
 
void compute_N_in_cells_mode_algo(F &&condition)
Computes average number of particles in each cell for the mode algorithm.
 
void print_statistics(const Clock &clock) const
Generates standard output with information about the thermodynamic properties of the lattice,...
 
std::vector< double > mult_sort_
Real number multiplicity for each particle type.
 
std::vector< int > mult_int_
Integer multiplicity for each particle type.
 
HadronGasEos eos_
Hadron gas equation of state.
 
ParticleList to_remove_
Particles to be removed after this thermalization step.
 
const bool BF_enforce_microcanonical_
Enforce energy conservation as part of BF sampling algorithm or not.
 
ThreeVector uniform_in_cell() const
 
std::unique_ptr< RectangularLattice< ThermLatticeNode > > lat_
The lattice on which the thermodynamic quantities are calculated.
 
double mult_class(const HadronClass cl) const
 
HadronClass get_class(size_t typelist_index) const
Defines the class of hadrons by quantum numbers.
 
GrandCanThermalizer(const std::array< double, 3 > lat_sizes, const std::array< int, 3 > n_cells, const std::array< double, 3 > origin, bool periodicity, double e_critical, double t_start, double delta_t, ThermalizationAlgorithm algo, bool BF_microcanonical)
Default constructor for the GranCanThermalizer to allocate the lattice.
 
const double e_crit_
Critical energy density above which cells are thermalized.
 
ParticleList sampled_list_
Newly generated particles by thermalizer.
 
std::array< double, 7 > mult_classes_
The different hadron species according to the enum defined in.
 
void sample_in_random_cell_BF_algo(ParticleList &plist, const double time, size_t type_index)
The total number of particles of species type_index is defined by mult_int_ array that is returned by...
 
void update_thermalizer_lattice(const std::vector< Particles > &ensembles, const DensityParameters &par, bool ignore_cells_under_threshold=true)
Compute all the thermodynamical quantities on the lattice from particles.
 
std::vector< size_t > cells_to_sample_
Cells above critical energy density.
 
const ThermalizationAlgorithm algorithm_
Algorithm to choose for sampling of particles obeying conservation laws.
 
const ParticleTypePtrList eos_typelist_
List of particle types from which equation of state is computed.
 
std::vector< double > N_in_cells_
Number of particles to be sampled in one cell.
 
ParticleData sample_in_random_cell_mode_algo(const double time, F &&condition)
Samples one particle and the species, cell, momentum and coordinate are chosen from the corresponding...
 
double lat_cell_volume_
Volume of a single lattice cell, necessary to convert thermal densities to actual particle numbers.
 
const size_t N_sorts_
Number of different species to be sampled.
 
double N_total_in_cells_
Total number of particles over all cells in thermalization region.
 
void thermalize(const Particles &particles, double time, int ntest)
Main thermalize function, that chooses the algorithm to follow (BF or mode sampling).
 
void renormalize_momenta(ParticleList &plist, const FourVector required_total_momentum)
Changes energy and momenta of the particles in plist to match the required_total_momentum.
 
void sample_multinomial(HadronClass particle_class, int N)
The sample_multinomial function samples integer numbers n_i distributed according to the multinomial ...
 
void thermalize_mode_algo(QuantumNumbers &conserved_initial, double time)
Samples particles to the according to the mode algorithm.
 
Class to handle the equation of state (EoS) of the hadron gas, consisting of all hadrons included in ...
 
static double net_charge_density(double T, double mub, double mus, double muq, bool account_for_resonance_widths=false)
Compute net charge density.
 
static double partial_density(const ParticleType &ptype, double T, double mub, double mus, double muq, bool account_for_resonance_widths=false)
Compute partial density of one hadron sort.
 
std::array< double, 4 > solve_eos(double e, double nb, double ns, double nq, std::array< double, 4 > initial_approximation)
Compute temperature and chemical potentials given energy-, net baryon-, net strangeness- and net char...
 
bool is_tabulated() const
Create an EoS table or not?
 
void from_table(EosTable::table_element &res, double e, double nb, double nq) const
Get the element of eos table.
 
static double net_baryon_density(double T, double mub, double mus, double muq, bool account_for_resonance_widths=false)
Compute net baryon density.
 
static double energy_density(double T, double mub, double mus, double muq)
Compute energy density.
 
static double net_strange_density(double T, double mub, double mus, double muq, bool account_for_resonance_widths=false)
Compute net strangeness density.
 
static double pressure(double T, double mub, double mus, double muq, bool account_for_resonance_widths=false)
Compute pressure .
 
ParticleData contains the dynamic information of a certain particle.
 
void set_4momentum(const FourVector &momentum_vector)
Set the particle's 4-momentum directly.
 
const ParticleType & type() const
Get the type of the particle.
 
void set_4position(const FourVector &pos)
Set the particle's 4-position directly.
 
const FourVector & momentum() const
Get the particle's 4-momentum.
 
void set_formation_time(const double &form_time)
Set the absolute formation time.
 
void boost_momentum(const ThreeVector &v)
Apply a Lorentz-boost to only the momentum.
 
int32_t charge() const
The charge of the particle.
 
int baryon_number() const
 
The Particles class abstracts the storage and manipulation of particles.
 
A container for storing conserved values.
 
void add_values(const ParticleData &p)
Add the quantum numbers of a single particle to the collection.
 
int baryon_number() const
 
FourVector momentum() const
 
The ThermLatticeNode class is intended to compute thermodynamical quantities in a cell given a set of...
 
void compute_rest_frame_quantities(HadronGasEos &eos)
Temperature, chemical potentials and rest frame velocity are calculated given the hadron gas equation...
 
double muq() const
Get the net charge chemical potential.
 
FourVector Tmu0() const
Get Four-momentum flow of the cell.
 
double ns_
Net strangeness density of the cell in the computational frame.
 
void set_rest_frame_quantities(double T0, double mub0, double mus0, double muq0, const ThreeVector v0)
Set all the rest frame quantities to some values, this is useful for testing.
 
double p() const
Get pressure in the rest frame.
 
double p_
Pressure in the rest frame.
 
double mus_
Net strangeness chemical potential.
 
ThreeVector v() const
Get 3-velocity of the rest frame.
 
double ns() const
Get net strangeness density of the cell in the computational frame.
 
double e_
Energy density in the rest frame.
 
double nb_
Net baryon density of the cell in the computational frame.
 
void add_particle(const ParticleData &p, double factor)
Add particle contribution to Tmu0, nb, ns and nq May look like unused at first glance,...
 
double muq_
Net charge chemical potential.
 
double mub_
Net baryon chemical potential.
 
FourVector Tmu0_
Four-momentum flow of the cell.
 
double mus() const
Get the net strangeness chemical potential.
 
ThreeVector v_
Velocity of the rest frame.
 
ThermLatticeNode()
Default constructor of thermal quantities on the lattice returning thermodynamic quantities in comput...
 
double mub() const
Get the net baryon chemical potential.
 
double nb() const
Get net baryon density of the cell in the computational frame.
 
double nq_
Net charge density of the cell in the computational frame.
 
double e() const
Get energy density in the rest frame.
 
double T() const
Get the temperature.
 
The ThreeVector class represents a physical three-vector  with the components .
 
The intention of this class is to efficiently sample  from the Bessel distribution ,...
 
std::pair< int, int > sample()
Sample two numbers from given Poissonians with a fixed difference.
 
ThermalizationAlgorithm
Defines the algorithm used for the forced thermalization.
 
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
 
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
 
int poisson(const T &lam)
Returns a Poisson distributed random number.
 
int binomial(const int N, const T &p)
Returns a binomially distributed random number.
 
double sample_momenta_from_thermal(const double temperature, const double mass)
Samples a momentum from the Maxwell-Boltzmann (thermal) distribution in a faster way,...
 
void update_lattice(RectangularLattice< T > *lat, const LatticeUpdate update, const DensityType dens_type, const DensityParameters &par, const std::vector< Particles > &ensembles, const bool compute_gradient)
Updates the contents on the lattice.
 
static constexpr int LGrandcanThermalizer
 
LatticeUpdate
Enumerator option for lattice updates.
 
constexpr double really_small
Numerical error tolerance.
 
DensityType
Allows to choose which kind of density to calculate.
 
HadronClass
Specifier to classify the different hadron species according to their quantum numbers.
 
@ Antibaryon
All anti-baryons.
 
@ ZeroQZeroSMeson
Neutral non-strange mesons.
 
@ NegativeSMeson
Mesons with strangeness S < 0.
 
@ NegativeQZeroSMeson
Non-strange mesons (S = 0) with electric cherge Q < 0.
 
@ PositiveSMeson
Mesons with strangeness S > 0.
 
@ PositiveQZeroSMeson
Non-strange mesons (S = 0) with electric cherge Q > 0.
 
Define the data structure for one element of the table.
 
double mub
Net baryochemical potential.
 
double muq
Net charge chemical potential.
 
double mus
Net strangeness potential.