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