Version: SMASH-1.5
grandcan_thermalizer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-
3  * SMASH Team
4  *
5  * GNU General Public License (GPLv3 or later)
6  */
7 
9 
10 #include <time.h>
11 
12 #include "smash/angles.h"
13 #include "smash/cxx14compat.h"
14 #include "smash/distributions.h"
16 #include "smash/logging.h"
17 #include "smash/particles.h"
18 #include "smash/quantumnumbers.h"
19 #include "smash/random.h"
20 
21 namespace smash {
22 
24  : Tmu0_(FourVector()),
25  nb_(0.0),
26  ns_(0.0),
27  e_(0.0),
28  p_(0.0),
29  v_(ThreeVector()),
30  T_(0.0),
31  mub_(0.0),
32  mus_(0.0) {}
33 
34 void ThermLatticeNode::add_particle(const ParticleData &part, double factor) {
35  Tmu0_ += part.momentum() * factor;
36  nb_ += static_cast<double>(part.type().baryon_number()) * factor;
37  ns_ += static_cast<double>(part.type().strangeness()) * factor;
38 }
39 
42  const int max_iter = 50;
43  v_ = ThreeVector(0.0, 0.0, 0.0);
44  double e_previous_step = 0.0;
45  const double tolerance = 5.e-4;
46  int iter;
47  for (iter = 0; iter < max_iter; iter++) {
48  e_previous_step = e_;
49  e_ = Tmu0_.x0() - Tmu0_.threevec() * v_;
50  if (std::abs(e_ - e_previous_step) < tolerance) {
51  break;
52  }
53  const double gamma_inv = std::sqrt(1.0 - v_.sqr());
54  EosTable::table_element tabulated;
55  eos.from_table(tabulated, e_, gamma_inv * nb_);
56  if (!eos.is_tabulated() || tabulated.p < 0.0) {
57  auto T_mub_mus = eos.solve_eos(e_, gamma_inv * nb_, gamma_inv * ns_);
58  T_ = T_mub_mus[0];
59  mub_ = T_mub_mus[1];
60  mus_ = T_mub_mus[2];
62  } else {
63  p_ = tabulated.p;
64  T_ = tabulated.T;
65  mub_ = tabulated.mub;
66  mus_ = tabulated.mus;
67  }
68  v_ = Tmu0_.threevec() / (Tmu0_.x0() + p_);
69  }
70  if (iter == max_iter) {
71  std::cout << "Warning from solver: max iterations exceeded."
72  << " Accuracy: " << std::abs(e_ - e_previous_step)
73  << " is less than tolerance " << tolerance << std::endl;
74  }
75 }
76 
77 void ThermLatticeNode::set_rest_frame_quantities(double T0, double mub0,
78  double mus0,
79  const ThreeVector v0) {
80  T_ = T0;
81  mub_ = mub0;
82  mus_ = mus0;
83  v_ = v0;
88 }
89 
90 std::ostream &operator<<(std::ostream &out, const ThermLatticeNode &node) {
91  return out << "T[mu,0]: " << node.Tmu0() << ", nb: " << node.nb()
92  << ", ns: " << node.ns() << ", v: " << node.v()
93  << ", e: " << node.e() << ", p: " << node.p()
94  << ", T: " << node.T() << ", mub: " << node.mub()
95  << ", mus: " << node.mus();
96 }
97 
98 GrandCanThermalizer::GrandCanThermalizer(const std::array<double, 3> lat_sizes,
99  const std::array<int, 3> n_cells,
100  const std::array<double, 3> origin,
101  bool periodicity, double e_critical,
102  double t_start, double delta_t,
104  : eos_typelist_(list_eos_particles()),
105  N_sorts_(eos_typelist_.size()),
106  e_crit_(e_critical),
107  t_start_(t_start),
108  period_(delta_t),
109  algorithm_(algo) {
111  lat_ = make_unique<RectangularLattice<ThermLatticeNode>>(
112  lat_sizes, n_cells, origin, periodicity, upd);
113  const std::array<double, 3> abc = lat_->cell_sizes();
114  cell_volume_ = abc[0] * abc[1] * abc[2];
115  cells_to_sample_.resize(50000);
116  mult_sort_.resize(N_sorts_);
117  mult_int_.resize(N_sorts_);
118 }
119 
121  const Particles &particles, const DensityParameters &dens_par,
122  bool ignore_cells_under_treshold) {
123  const DensityType dens_type = DensityType::Hadron;
125  update_lattice(lat_.get(), update, dens_type, dens_par, particles);
126  for (auto &node : *lat_) {
127  /* If energy density is definitely below e_crit -
128  no need to find T, mu, etc. So if e = T00 - T0i*vi <=
129  T00 + sum abs(T0i) < e_crit, no efforts are necessary. */
130  if (!ignore_cells_under_treshold ||
131  node.Tmu0().x0() + std::abs(node.Tmu0().x1()) +
132  std::abs(node.Tmu0().x2()) + std::abs(node.Tmu0().x3()) >=
133  e_crit_) {
134  node.compute_rest_frame_quantities(eos_);
135  } else {
136  node = ThermLatticeNode();
137  }
138  }
139 }
140 
142  return ThreeVector(random::uniform(-0.5 * lat_->cell_sizes()[0],
143  +0.5 * lat_->cell_sizes()[0]),
144  random::uniform(-0.5 * lat_->cell_sizes()[1],
145  +0.5 * lat_->cell_sizes()[1]),
146  random::uniform(-0.5 * lat_->cell_sizes()[2],
147  +0.5 * lat_->cell_sizes()[2]));
148 }
149 
151  ParticleList &plist, const FourVector required_total_momentum) {
152  const auto &log = logger<LogArea::GrandcanThermalizer>();
153 
154  // Centralize momenta
155  QuantumNumbers conserved = QuantumNumbers(plist);
156  log.info("Required 4-momentum: ", required_total_momentum);
157  log.info("Sampled 4-momentum: ", conserved.momentum());
158  const ThreeVector mom_to_add =
159  (required_total_momentum.threevec() - conserved.momentum().threevec()) /
160  plist.size();
161  log.info("Adjusting momenta by ", mom_to_add);
162  for (auto &particle : plist) {
163  particle.set_4momentum(particle.type().mass(),
164  particle.momentum().threevec() + mom_to_add);
165  }
166 
167  // Boost every particle to the common center of mass frame
168  conserved = QuantumNumbers(plist);
169  const ThreeVector beta_CM_generated = conserved.momentum().velocity();
170  const ThreeVector beta_CM_required = required_total_momentum.velocity();
171 
172  double E = 0.0;
173  double E_expected = required_total_momentum.abs();
174  for (auto &particle : plist) {
175  particle.boost_momentum(beta_CM_generated);
176  E += particle.momentum().x0();
177  }
178  // Renorm. momenta by factor (1+a) to get the right energy, binary search
179  const double tolerance = really_small;
180  double a, a_min, a_max, er;
181  const int max_iter = 50;
182  int iter = 0;
183  if (E_expected >= E) {
184  a_min = 0.0;
185  a_max = 1.0;
186  } else {
187  a_min = -1.0;
188  a_max = 0.0;
189  }
190  do {
191  a = 0.5 * (a_min + a_max);
192  E = 0.0;
193  for (const auto &particle : plist) {
194  const double p2 = particle.momentum().threevec().sqr();
195  const double E2 = particle.momentum().x0() * particle.momentum().x0();
196  E += std::sqrt(E2 + a * (a + 2.0) * p2);
197  }
198  er = E - E_expected;
199  if (er >= 0.0) {
200  a_max = a;
201  } else {
202  a_min = a;
203  }
204  log.debug("Iteration ", iter, ": a = ", a, ", Δ = ", er);
205  iter++;
206  } while (std::abs(er) > tolerance && iter < max_iter);
207 
208  log.info("Renormalizing momenta by factor 1+a, a = ", a);
209  for (auto &particle : plist) {
210  particle.set_4momentum(particle.type().mass(),
211  (1 + a) * particle.momentum().threevec());
212  particle.boost_momentum(-beta_CM_required);
213  }
214 }
215 
217  int N_to_sample) {
218  /* The array mult_sort_ contains real numbers \f$ a_i \f$. The numbers \f$
219  * n_i \f$ are saved in the mult_int_ array. Only particles of class
220  * particle_class are sampled, where particle_class is defined by the
221  * get_class function. */
222  double sum = mult_class(particle_class);
223  for (size_t i_type = 0; (i_type < N_sorts_) && (N_to_sample > 0); i_type++) {
224  if (get_class(i_type) != particle_class) {
225  continue;
226  }
227  const double p = mult_sort_[i_type] / sum;
228  mult_int_[i_type] = random::binomial(N_to_sample, p);
230  /*std::cout << eos_typelist_[i_type]->name() <<
231  ": mult_sort = " << mult_sort_[i_type] <<
232  ", sum = " << sum <<
233  ", p = " << p <<
234  ", N to sample = " << N_to_sample <<
235  ", mult_int_ = " << mult_int_[i_type] << std::endl;*/
236  sum -= mult_sort_[i_type];
237  N_to_sample -= mult_int_[i_type];
238  }
239 }
240 
242  const double time,
243  size_t type_index) {
244  N_in_cells_.clear();
245  N_total_in_cells_ = 0.0;
246  for (auto cell_index : cells_to_sample_) {
247  const ThermLatticeNode cell = (*lat_)[cell_index];
248  const double gamma = 1.0 / std::sqrt(1.0 - cell.v().sqr());
249  const double N_this_cell =
250  cell_volume_ * gamma *
251  HadronGasEos::partial_density(*eos_typelist_[type_index], cell.T(),
252  cell.mub(), cell.mus());
253  N_in_cells_.push_back(N_this_cell);
254  N_total_in_cells_ += N_this_cell;
255  }
256 
257  for (int i = 0; i < mult_int_[type_index]; i++) {
258  // Choose random cell, probability = N_in_cell/N_total
259  double r = random::uniform(0.0, N_total_in_cells_);
260  double partial_sum = 0.0;
261  int index_only_thermalized = -1;
262  while (partial_sum < r) {
263  index_only_thermalized++;
264  partial_sum += N_in_cells_[index_only_thermalized];
265  }
266  const int cell_index = cells_to_sample_[index_only_thermalized];
267  const ThermLatticeNode cell = (*lat_)[cell_index];
268  const ThreeVector cell_center = lat_->cell_center(cell_index);
269 
270  ParticleData particle(*eos_typelist_[type_index]);
271  // Note: it's pole mass for resonances!
272  const double m = eos_typelist_[type_index]->mass();
273  // Position
274  particle.set_4position(FourVector(time, cell_center + uniform_in_cell()));
275  // Momentum
276  double momentum_radial = sample_momenta_from_thermal(cell.T(), m);
277  Angles phitheta;
278  phitheta.distribute_isotropically();
279  particle.set_4momentum(m, phitheta.threevec() * momentum_radial);
280  particle.boost_momentum(-cell.v());
281  particle.set_formation_time(time);
282 
283  plist.push_back(particle);
284  }
285 }
286 
288  double time, int ntest) {
289  const auto &log = logger<LogArea::GrandcanThermalizer>();
290 
291  std::fill(mult_sort_.begin(), mult_sort_.end(), 0.0);
292  for (auto cell_index : cells_to_sample_) {
293  const ThermLatticeNode cell = (*lat_)[cell_index];
294  const double gamma = 1.0 / std::sqrt(1.0 - cell.v().sqr());
295  for (size_t i = 0; i < N_sorts_; i++) {
296  // N_i = n u^mu dsigma_mu = (isochronous hypersurface) n * V * gamma
297  mult_sort_[i] += cell_volume_ * gamma * ntest *
299  *eos_typelist_[i], cell.T(), cell.mub(), cell.mus());
300  }
301  }
302 
303  std::fill(mult_classes_.begin(), mult_classes_.end(), 0.0);
304  for (size_t i = 0; i < N_sorts_; i++) {
305  mult_classes_[static_cast<size_t>(get_class(i))] += mult_sort_[i];
306  }
307 
310  conserved_initial.baryon_number());
311 
312  while (true) {
313  sampled_list_.clear();
314  std::fill(mult_int_.begin(), mult_int_.end(), 0);
315  const auto Nbar_antibar = bessel_sampler_B.sample();
316 
317  sample_multinomial(HadronClass::Baryon, Nbar_antibar.first);
318  sample_multinomial(HadronClass::Antibaryon, Nbar_antibar.second);
319 
320  // Count strangeness of the sampled particles
321  int S_sampled = 0;
322  for (size_t i = 0; i < N_sorts_; i++) {
323  S_sampled += eos_typelist_[i]->strangeness() * mult_int_[i];
324  }
325 
326  std::pair<int, int> NS_antiS;
328  random::BesselSampler bessel_sampler_S(
331  conserved_initial.strangeness() - S_sampled);
332  NS_antiS = bessel_sampler_S.sample();
334  NS_antiS = std::make_pair(
337  if (NS_antiS.first - NS_antiS.second !=
338  conserved_initial.strangeness() - S_sampled) {
339  continue;
340  }
341  }
342 
345  // Count charge of the sampled particles
346  int ch_sampled = 0;
347  for (size_t i = 0; i < N_sorts_; i++) {
348  ch_sampled += eos_typelist_[i]->charge() * mult_int_[i];
349  }
350 
351  std::pair<int, int> NC_antiC;
353  random::BesselSampler bessel_sampler_C(
356  conserved_initial.charge() - ch_sampled);
357  NC_antiC = bessel_sampler_C.sample();
359  NC_antiC = std::make_pair(
362  if (NC_antiC.first - NC_antiC.second !=
363  conserved_initial.charge() - ch_sampled) {
364  continue;
365  }
366  }
367 
373 
374  for (size_t itype = 0; itype < N_sorts_; itype++) {
376  }
377  double e_tot;
378  const double e_init = conserved_initial.momentum().x0();
379  e_tot = 0.0;
380  for (auto &particle : sampled_list_) {
381  e_tot += particle.momentum().x0();
382  }
383  if (std::abs(e_tot - e_init) > 0.01 * e_init) {
384  log.debug("Rejecting: energy ", e_tot, " too far from e_init = ", e_init);
385  continue;
386  }
387  break;
388  }
389 }
390 
392  QuantumNumbers &conserved_initial, double time) {
393  double energy = 0.0;
394  int S_plus = 0, S_minus = 0, B_plus = 0, B_minus = 0, E_plus = 0, E_minus = 0;
395  // Mode 1: sample until energy is conserved, take only strangeness < 0
396  auto condition1 = [](int, int, int) { return true; };
397  compute_N_in_cells_mode_algo(condition1);
398  while (conserved_initial.momentum().x0() > energy ||
399  S_plus < conserved_initial.strangeness()) {
400  ParticleData p = sample_in_random_cell_mode_algo(time, condition1);
401  energy += p.momentum().x0();
402  if (p.pdgcode().strangeness() > 0) {
403  sampled_list_.push_back(p);
404  S_plus += p.pdgcode().strangeness();
405  }
406  }
407 
408  // Mode 2: sample until strangeness is conserved
409  auto condition2 = [](int S, int, int) { return (S < 0); };
410  compute_N_in_cells_mode_algo(condition2);
411  while (S_plus + S_minus > conserved_initial.strangeness()) {
412  ParticleData p = sample_in_random_cell_mode_algo(time, condition2);
413  const int s_part = p.pdgcode().strangeness();
414  // Do not allow particles with S = -2 or -3 spoil the total sum
415  if (S_plus + S_minus + s_part >= conserved_initial.strangeness()) {
416  sampled_list_.push_back(p);
417  S_minus += s_part;
418  }
419  }
420 
421  // Mode 3: sample non-strange baryons
422  auto condition3 = [](int S, int, int) { return (S == 0); };
423  QuantumNumbers conserved_remaining =
424  conserved_initial - QuantumNumbers(sampled_list_);
425  energy = 0.0;
426  compute_N_in_cells_mode_algo(condition3);
427  while (conserved_remaining.momentum().x0() > energy ||
428  B_plus < conserved_remaining.baryon_number()) {
429  ParticleData p = sample_in_random_cell_mode_algo(time, condition3);
430  energy += p.momentum().x0();
431  if (p.pdgcode().baryon_number() > 0) {
432  sampled_list_.push_back(p);
433  B_plus += p.pdgcode().baryon_number();
434  }
435  }
436 
437  // Mode 4: sample non-strange anti-baryons
438  auto condition4 = [](int S, int B, int) { return (S == 0) && (B < 0); };
439  compute_N_in_cells_mode_algo(condition4);
440  while (B_plus + B_minus > conserved_remaining.baryon_number()) {
441  ParticleData p = sample_in_random_cell_mode_algo(time, condition4);
442  const int bar = p.pdgcode().baryon_number();
443  if (B_plus + B_minus + bar >= conserved_remaining.baryon_number()) {
444  sampled_list_.push_back(p);
445  B_minus += bar;
446  }
447  }
448 
449  // Mode 5: sample non_strange mesons, but take only with charge > 0
450  auto condition5 = [](int S, int B, int) { return (S == 0) && (B == 0); };
451  conserved_remaining = conserved_initial - QuantumNumbers(sampled_list_);
452  energy = 0.0;
453  compute_N_in_cells_mode_algo(condition5);
454  while (conserved_remaining.momentum().x0() > energy ||
455  E_plus < conserved_remaining.charge()) {
456  ParticleData p = sample_in_random_cell_mode_algo(time, condition5);
457  energy += p.momentum().x0();
458  if (p.pdgcode().charge() > 0) {
459  sampled_list_.push_back(p);
460  E_plus += p.pdgcode().charge();
461  }
462  }
463 
464  // Mode 6: sample non_strange mesons to conserve charge
465  auto condition6 = [](int S, int B, int C) {
466  return (S == 0) && (B == 0) && (C < 0);
467  };
468  compute_N_in_cells_mode_algo(condition6);
469  while (E_plus + E_minus > conserved_remaining.charge()) {
470  ParticleData p = sample_in_random_cell_mode_algo(time, condition6);
471  const int charge = p.pdgcode().charge();
472  if (E_plus + E_minus + charge >= conserved_remaining.charge()) {
473  sampled_list_.push_back(p);
474  E_minus += charge;
475  }
476  }
477 
478  // Mode 7: sample neutral non-strange mesons to conserve energy
479  auto condition7 = [](int S, int B, int C) {
480  return (S == 0) && (B == 0) && (C == 0);
481  };
482  conserved_remaining = conserved_initial - QuantumNumbers(sampled_list_);
483  energy = 0.0;
484  compute_N_in_cells_mode_algo(condition7);
485  while (conserved_remaining.momentum().x0() > energy) {
486  ParticleData p = sample_in_random_cell_mode_algo(time, condition7);
487  sampled_list_.push_back(p);
488  energy += p.momentum().x0();
489  }
490 }
491 
492 void GrandCanThermalizer::thermalize(const Particles &particles, double time,
493  int ntest) {
494  const auto &log = logger<LogArea::GrandcanThermalizer>();
495  log.info("Starting forced thermalization, time ", time, " fm/c");
496  to_remove_.clear();
497  sampled_list_.clear();
498  /* Remove particles from the cells with e > e_crit_,
499  * sum up their conserved quantities */
500  QuantumNumbers conserved_initial = QuantumNumbers();
501  ThermLatticeNode node;
502  for (auto &particle : particles) {
503  const bool is_on_lattice =
504  lat_->value_at(particle.position().threevec(), node);
505  if (is_on_lattice && node.e() > e_crit_) {
506  to_remove_.push_back(particle);
507  }
508  }
509  /* Do not thermalize too small number of particles: for the number
510  * of particles < 30 the algorithm tends to hang or crash too often. */
511  if (to_remove_.size() > 30) {
512  for (auto &particle : to_remove_) {
513  conserved_initial.add_values(particle);
514  }
515  } else {
516  to_remove_.clear();
517  conserved_initial = QuantumNumbers();
518  }
519  log.info("Removed ", to_remove_.size(), " particles.");
520 
521  // Exit if there is nothing to thermalize
522  if (conserved_initial == QuantumNumbers()) {
523  return;
524  }
525  // Save the indices of cells inside the volume with e > e_crit_
526  cells_to_sample_.clear();
527  const size_t lattice_total_cells = lat_->size();
528  for (size_t i = 0; i < lattice_total_cells; i++) {
529  if ((*lat_)[i].e() > e_crit_) {
530  cells_to_sample_.push_back(i);
531  }
532  }
533  log.info("Number of cells in the thermalization region = ",
534  cells_to_sample_.size(), ", its total volume [fm^3]: ",
535  cells_to_sample_.size() * cell_volume_, ", in % of lattice: ",
536  100.0 * cells_to_sample_.size() / lattice_total_cells);
537 
538  switch (algorithm_) {
541  thermalize_BF_algo(conserved_initial, time, ntest);
542  break;
544  thermalize_mode_algo(conserved_initial, time);
545  break;
546  default:
547  throw std::invalid_argument(
548  "This thermalization algorithm is"
549  " not yet implemented");
550  }
551  log.info("Sampled ", sampled_list_.size(), " particles.");
552 
553  // Adjust momenta
554  renormalize_momenta(sampled_list_, conserved_initial.momentum());
555 }
556 
558  struct to_average {
559  double T;
560  double mub;
561  double mus;
562  double nb;
563  double ns;
564  };
565  struct to_average on_lattice = {0.0, 0.0, 0.0, 0.0, 0.0};
566  struct to_average in_therm_reg = {0.0, 0.0, 0.0, 0.0, 0.0};
567  double e_sum_on_lattice = 0.0, e_sum_in_therm_reg = 0.0;
568  int node_counter = 0;
569  for (const auto &node : *lat_) {
570  const double e = node.e();
571  on_lattice.T += node.T() * e;
572  on_lattice.mub += node.mub() * e;
573  on_lattice.mus += node.mus() * e;
574  on_lattice.nb += node.nb() * e;
575  on_lattice.ns += node.ns() * e;
576  e_sum_on_lattice += e;
577  if (e >= e_crit_) {
578  in_therm_reg.T += node.T() * e;
579  in_therm_reg.mub += node.mub() * e;
580  in_therm_reg.mus += node.mus() * e;
581  in_therm_reg.nb += node.nb() * e;
582  in_therm_reg.ns += node.ns() * e;
583  e_sum_in_therm_reg += e;
584  node_counter++;
585  }
586  }
587  if (e_sum_on_lattice > really_small) {
588  on_lattice.T /= e_sum_on_lattice;
589  on_lattice.mub /= e_sum_on_lattice;
590  on_lattice.mus /= e_sum_on_lattice;
591  on_lattice.nb /= e_sum_on_lattice;
592  on_lattice.ns /= e_sum_on_lattice;
593  }
594  if (e_sum_in_therm_reg > really_small) {
595  in_therm_reg.T /= e_sum_in_therm_reg;
596  in_therm_reg.mub /= e_sum_in_therm_reg;
597  in_therm_reg.mus /= e_sum_in_therm_reg;
598  in_therm_reg.nb /= e_sum_in_therm_reg;
599  in_therm_reg.ns /= e_sum_in_therm_reg;
600  }
601 
602  std::cout << "Current time [fm/c]: " << clock.current_time() << std::endl;
603  std::cout << "Averages on the lattice - T[GeV], mub[GeV], mus[GeV], "
604  << "nb[fm^-3], ns[fm^-3]: " << on_lattice.T << " " << on_lattice.mub
605  << " " << on_lattice.mus << " " << on_lattice.nb << " "
606  << on_lattice.ns << std::endl;
607  std::cout << "Averages in therm. region - T[GeV], mub[GeV], mus[GeV], "
608  << "nb[fm^-3], ns[fm^-3]: " << in_therm_reg.T << " "
609  << in_therm_reg.mub << " " << in_therm_reg.mus << " "
610  << in_therm_reg.nb << " " << in_therm_reg.ns << std::endl;
611  std::cout << "Volume with e > e_crit [fm^3]: " << cell_volume_ * node_counter
612  << std::endl;
613 }
614 
615 } // namespace smash
double p() const
Get pressure in the rest frame.
const double e_crit_
Critical energy density above which cells are thermalized.
void add_particle(const ParticleData &p, double factor)
Add particle contribution to Tmu0, nb and ns May look like unused at first glance, but it is actually used by update_lattice, where the node type of the lattice is templated.
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:103
ThermalizationAlgorithm
Defines the algorithm used for the forced thermalization.
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)
Default constructor for the GranCanThermalizer to allocate the lattice.
const size_t N_sorts_
Number of different species to be sampled.
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:30
void sample_multinomial(HadronClass particle_class, int N)
The sample_multinomial function samples integer numbers n_i distributed according to the multinomial ...
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
ThreeVector velocity() const
Get the velocity (3-vector divided by zero component).
Definition: fourvector.h:310
ThermLatticeNode()
Default constructor of thermal quantities on the lattice returning thermodynamic quantities in comput...
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
double mub() const
Get the net baryon chemical potential.
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
FourVector Tmu0_
Four-momentum flow of the cell.
void thermalize(const Particles &particles, double time, int ntest)
Main thermalize function, that chooses the algorithm to follow (BF or mode sampling).
void update_lattice(RectangularLattice< T > *lat, const LatticeUpdate update, const DensityType dens_type, const DensityParameters &par, const Particles &particles, const bool compute_gradient=false)
Updates the contents on the lattice.
Definition: density.h:386
void thermalize_BF_algo(QuantumNumbers &conserved_initial, double time, int ntest)
Samples particles according to the BF algorithm by making use of the.
LatticeUpdate
Enumerator option for lattice updates.
Definition: lattice.h:35
const FourVector & momentum() const
Get the particle&#39;s 4-momentum.
Definition: particledata.h:139
double ns() const
Get net strangeness density of the cell in the computational frame.
std::pair< int, int > sample()
Sample two numbers from given Poissonians with a fixed difference.
Definition: random.cc:57
double x0() const
Definition: fourvector.h:290
const ThermalizationAlgorithm algorithm_
Algorithm to choose for sampling of particles obeying conservation laws.
void set_formation_time(const double &form_time)
Set the absolute formation time.
Definition: particledata.h:232
double nb() const
Get net baryon density of the cell in the computational frame.
void add_values(const ParticleData &p)
Add the quantum numbers of a single particle to the collection.
void print_statistics(const Clock &clock) const
Generates standard output with information about the thermodynamic properties of the lattice...
void set_rest_frame_quantities(double T0, double mub0, double mus0, const ThreeVector v0)
Set all the rest frame quantities to some values, this is useful for testing.
void update_thermalizer_lattice(const Particles &particles, const DensityParameters &par, bool ignore_cells_under_threshold=true)
Compute all the thermodynamical quantities on the lattice from particles.
ThreeVector v_
Velocity of the rest frame.
double p_
Pressure in the rest frame.
static double net_baryon_density(double T, double mub, double mus)
Compute net baryon density.
Definition: hadgas_eos.cc:272
ThreeVector threevec() const
Definition: fourvector.h:306
HadronClass get_class(size_t typelist_index) const
Defines the class of hadrons by quantum numbers.
double ns_
Net strangeness density of the cell in the computational frame.
int baryon_number() const
Definition: particletype.h:196
double mub_
Net baryon chemical potential.
ParticleList sampled_list_
Newly generated particles by thermalizer.
bool is_tabulated() const
Create an EoS table or not?
Definition: hadgas_eos.h:282
void set_4momentum(const FourVector &momentum_vector)
Set the particle&#39;s 4-momentum directly.
Definition: particledata.h:145
double sqr() const
Definition: threevector.h:249
Non-strange mesons (S = 0) with electric cherge Q < 0.
int strangeness() const
Definition: particletype.h:199
A container for storing conserved values.
void compute_rest_frame_quantities(HadronGasEos &eos)
Temperature, chemical potentials and rest frame velocity are calculated given the hadron gas equation...
double e() const
Get energy density in the rest frame.
double sample_momenta_from_thermal(const double temperature, const double mass)
Samples a momentum from the Maxwell-Boltzmann (thermal) distribution in a faster way, given by Scott Pratt.
void compute_N_in_cells_mode_algo(F &&condition)
Computes average number of particles in each cell for the mode algorithm.
std::vector< size_t > cells_to_sample_
Cells above critical energy density.
Mesons with strangeness S < 0.
The intention of this class is to efficiently sample from the Bessel distribution ...
Definition: random.h:374
T uniform(T min, T max)
Definition: random.h:85
double N_total_in_cells_
Total number of particles over all cells in thermalization region.
void thermalize_mode_algo(QuantumNumbers &conserved_initial, double time)
Samples particles to the according to the mode algorithm.
Define the data structure for one element of the table.
Definition: hadgas_eos.h:55
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.
Clock tracks the time in the simulation.
Definition: clock.h:75
Neutral non-strange mesons.
Non-strange mesons (S = 0) with electric cherge Q > 0.
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...
std::vector< double > mult_sort_
Real number multiplicity for each particle type.
ParticleList to_remove_
Particles to be removed after this thermalization step.
Mesons with strangeness S > 0.
std::vector< double > N_in_cells_
Number of particles to be sampled in one cell.
int binomial(const int N, const T &p)
Returns a binomially distributed random number.
Definition: random.h:235
double nb_
Net baryon density of the cell in the computational frame.
ThreeVector uniform_in_cell() const
constexpr int p
Proton.
const ParticleType & type() const
Get the type of the particle.
Definition: particledata.h:109
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
FourVector Tmu0() const
Get Four-momentum flow of the cell.
void set_4position(const FourVector &pos)
Set the particle&#39;s 4-position directly.
Definition: particledata.h:190
double e_
Energy density in the rest frame.
The ThermLatticeNode class is intended to compute thermodynamical quantities in a cell given a set of...
HadronClass
Specifier to classify the different hadron species according to their quantum numbers.
std::vector< int > mult_int_
Integer multiplicity for each particle type.
double mus_
Net strangeness chemical potential.
int poisson(const T &lam)
Returns a Poisson distributed random number.
Definition: random.h:223
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...
double T() const
Get the temperature.
double mus() const
Get the net strangeness chemical potential.
std::array< double, 7 > mult_classes_
The different hadron species according to the enum defined in.
Angles provides a common interface for generating directions: i.e., two angles that should be interpr...
Definition: angles.h:59
std::unique_ptr< RectangularLattice< ThermLatticeNode > > lat_
The lattice on which the thermodynamic quantities are calculated.
void distribute_isotropically()
Populate the object with a new direction.
Definition: angles.h:188
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
double current_time() const
Definition: clock.h:110
DensityType
Allows to choose which kind of density to calculate.
Definition: density.h:34
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
Definition: action.h:457
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:32
double cell_volume_
Volume of a single cell, necessary to convert thermal densities to actual particle numbers...
double abs() const
calculate the lorentz invariant absolute value
Definition: fourvector.h:441
HadronGasEos eos_
Hadron gas equation of state.
FourVector momentum() const
void from_table(EosTable::table_element &res, double e, double nb) const
Get the element of eos table.
Definition: hadgas_eos.h:272
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:52
void boost_momentum(const ThreeVector &v)
Apply a Lorentz-boost to only the momentum.
Definition: particledata.h:313
const ParticleTypePtrList eos_typelist_
List of particle types from which equation of state is computed.
double mult_class(const HadronClass cl) const
static double pressure(double T, double mub, double mus)
Compute pressure .
Definition: hadgas_eos.h:159
Definition: action.h:24
ThreeVector v() const
Get 3-velocity of the rest frame.
static double energy_density(double T, double mub, double mus)
Compute energy density.
Definition: hadgas_eos.cc:228