Version: SMASH-3.4
boxmodus.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2020,2022-2026
3  * SMASH Team
4  *
5  * GNU General Public License (GPLv3 or later)
6  */
7 #include "smash/boxmodus.h"
8 
9 #include <cmath>
10 #include <cstdio>
11 #include <cstdlib>
12 #include <list>
13 #include <map>
14 #include <utility>
15 #include <vector>
16 
17 #include "smash/algorithms.h"
18 #include "smash/angles.h"
19 #include "smash/constants.h"
20 #include "smash/cxx17compat.h"
22 #include "smash/input_keys.h"
23 #include "smash/logging.h"
24 #include "smash/quantumsampling.h"
25 #include "smash/random.h"
26 #include "smash/threevector.h"
28 
29 namespace smash {
30 static constexpr int LBox = LogArea::Box::id;
31 
32 /* console output on startup of box specific parameters */
33 std::ostream &operator<<(std::ostream &out, const BoxModus &m) {
34  out << "-- Box Modus:\nSize of the box: (" << m.length_ << " fm)³\n";
35  if (m.use_thermal_) {
36  out << "Thermal multiplicities "
37  << "(T = " << m.temperature_ << " GeV, muB = " << m.mub_
38  << " GeV, muS = " << m.mus_ << " GeV, muQ = " << m.muq_ << " GeV)\n";
39  } else {
40  for (const auto &p : m.init_multipl_) {
41  ParticleTypePtr ptype = &ParticleType::find(p.first);
42  out << ptype->name() << " initial multiplicity " << p.second << '\n';
43  }
44  }
45  switch (m.initial_condition_) {
47  out << "All initial momenta = 3T = " << 3 * m.temperature_ << " GeV\n";
48  break;
50  out << "Boltzmann momentum distribution with T = " << m.temperature_
51  << " GeV.\n";
52  break;
54  out << "Fermi/Bose momentum distribution with T = " << m.temperature_
55  << " GeV.\n";
56  break;
57  }
58  if (m.jet_pdg_) {
59  ParticleTypePtr ptype = &ParticleType::find(m.jet_pdg_.value());
60  out << "Adding a " << ptype->name() << " as a jet in the middle "
61  << "of the box with " << m.jet_mom_ << " GeV initial momentum.\n";
62  }
63  return out;
64 }
65 
67  const ExperimentParameters &parameters)
68  : initial_condition_(
69  modus_config.take(InputKeys::modi_box_initialCondition)),
70  length_(modus_config.take(InputKeys::modi_box_length)),
71  equilibration_time_(
72  modus_config.take(InputKeys::modi_box_equilibrationTime)),
73  temperature_(modus_config.take(InputKeys::modi_box_temperature)),
74  start_time_(modus_config.take(InputKeys::modi_box_startTime)),
75  use_thermal_(
76  modus_config.take(InputKeys::modi_box_useThermalMultiplicities)),
77  mub_(modus_config.take(InputKeys::modi_box_baryonChemicalPotential)),
78  mus_(modus_config.take(InputKeys::modi_box_strangeChemicalPotential)),
79  muq_(modus_config.take(InputKeys::modi_box_chargeChemicalPotential)),
80  account_for_resonance_widths_(
81  modus_config.take(InputKeys::modi_box_accountResonanceWidths)),
82  init_multipl_(
83  use_thermal_
84  ? std::map<PdgCode, int>()
85  : modus_config.take(InputKeys::modi_box_initialMultiplicities)),
86  /* Note that it is crucial not to take other keys from the Jet section
87  * before Jet_PDG, since we want here the take to throw in case the user
88  * had a Jet section without the mandatory Jet_PDG key. If all other keys
89  * are taken first, the section is removed from the config because empty,
90  * and has_section(InputSections::m_b_jet) method would return false.
91  */
92  jet_pdg_(modus_config.has_section(InputSections::m_b_jet)
93  ? make_optional<PdgCode>(
94  modus_config.take(InputKeys::modi_box_jet_jetPdg))
95  : std::nullopt),
96 
97  jet_mom_(modus_config.take(InputKeys::modi_box_jet_jetMomentum)) {
98  // Check consistency, just in case
99  if (std::abs(length_ - parameters.box_length) > really_small) {
100  throw std::runtime_error("Box length inconsistency");
101  }
102 }
103 
105  const ExperimentParameters &parameters) {
106  double momentum_radial = 0.0, mass = 0.0;
107  Angles phitheta;
108  FourVector momentum_total(0, 0, 0, 0);
109  auto uniform_length = random::make_uniform_distribution(0.0, this->length_);
110  const double T = this->temperature_;
111  const double V = length_ * length_ * length_;
112  /* Create NUMBER OF PARTICLES according to configuration, or thermal case */
113  if (use_thermal_) {
114  if (average_multipl_.empty()) {
115  for (const ParticleType &ptype : ParticleType::list_all()) {
116  if (HadronGasEos::is_eos_particle(ptype)) {
117  const double lifetime_factor =
118  ptype.is_stable() ? 1. : parameters.res_lifetime_factor;
119  const double n = lifetime_factor * HadronGasEos::partial_density(
120  ptype, T, mub_, mus_, muq_,
122  average_multipl_[ptype.pdgcode()] = n * V * parameters.testparticles;
123  }
124  }
125  }
126  double nb_init = 0.0, ns_init = 0.0, nq_init = 0.0;
127  for (const auto &mult : average_multipl_) {
128  const int thermal_mult_int = random::poisson(mult.second);
129  particles->create(thermal_mult_int, mult.first);
130  nb_init += mult.second * mult.first.baryon_number();
131  ns_init += mult.second * mult.first.strangeness();
132  nq_init += mult.second * mult.first.charge();
133  logg[LBox].debug(mult.first, " initial multiplicity ", thermal_mult_int);
134  }
135  logg[LBox].info("Initial hadron gas baryon density ", nb_init);
136  logg[LBox].info("Initial hadron gas strange density ", ns_init);
137  logg[LBox].info("Initial hadron gas charge density ", nq_init);
138  } else {
139  for (const auto &p : init_multipl_) {
140  particles->create(p.second * parameters.testparticles, p.first);
141  logg[LBox].debug("Particle ", p.first, " initial multiplicity ",
142  p.second);
143  }
144  }
145  std::unique_ptr<QuantumSampling> quantum_sampling;
147  quantum_sampling = std::make_unique<QuantumSampling>(init_multipl_, V, T);
148  }
149  for (ParticleData &data : *particles) {
150  /* Set MOMENTUM SPACE distribution */
152  /* initial thermal momentum is the average 3T */
153  momentum_radial = 3.0 * T;
154  mass = data.pole_mass();
155  } else {
156  if (this->initial_condition_ ==
158  /* thermal momentum according Maxwell-Boltzmann distribution */
160  ? data.type().mass()
161  : HadronGasEos::sample_mass_thermal(data.type(), 1.0 / T);
162  momentum_radial = sample_momenta_from_thermal(T, mass);
163  } else if (this->initial_condition_ ==
165  /*
166  * Sampling the thermal momentum according Bose/Fermi/Boltzmann
167  * distribution.
168  * We take the pole mass as the mass.
169  */
170  mass = data.type().mass();
171  momentum_radial = quantum_sampling->sample(data.pdgcode());
172  }
173  }
174  phitheta.distribute_isotropically();
175  logg[LBox].debug(data.type().name(), "(id ", data.id(),
176  ") radial momentum ", momentum_radial, ", direction",
177  phitheta);
178  data.set_4momentum(mass, phitheta.threevec() * momentum_radial);
179  momentum_total += data.momentum();
180 
181  /* Set COORDINATE SPACE distribution */
182  ThreeVector pos{uniform_length(), uniform_length(), uniform_length()};
183  data.set_4position(FourVector(start_time_, pos));
184  /// Initialize formation time
185  data.set_formation_time(start_time_);
186  }
187 
188  /* Make total 3-momentum of the box 0 and initialize an unpolarized spin
189  * vector if spin interactions are enabled
190  */
191  for (ParticleData &data : *particles) {
192  data.set_4momentum(data.momentum().abs(),
193  data.momentum().threevec() -
194  momentum_total.threevec() / particles->size());
195 
196  // Initialize spin vector
198  data.set_unpolarized_spin_vector();
199  }
200  }
201 
202  /* Add a single highly energetic particle in the center of the box (jet) */
203  if (jet_pdg_) {
204  auto &jet_particle = particles->create(jet_pdg_.value());
205  jet_particle.set_formation_time(start_time_);
206  jet_particle.set_4position(FourVector(start_time_, 0., 0., 0.));
207  jet_particle.set_4momentum(ParticleType::find(jet_pdg_.value()).mass(),
208  ThreeVector(jet_mom_, 0., 0.));
210  jet_particle.set_unpolarized_spin_vector();
211  }
212  }
213 
214  /* Recalculate total momentum */
215  momentum_total = FourVector(0, 0, 0, 0);
216  for (ParticleData &data : *particles) {
217  momentum_total += data.momentum();
218  /* IC: debug checks */
219  logg[LBox].debug() << data;
220  }
221  /* allows to check energy conservation */
222  logg[LBox].debug() << "Initial total 4-momentum [GeV]: " << momentum_total;
223  return start_time_;
224 }
225 
227  const OutputsList &output_list) {
228  int wraps = 0;
229 
230  for (ParticleData &data : *particles) {
231  FourVector position = data.position();
232  bool wall_hit = enforce_periodic_boundaries(position.begin() + 1,
233  position.end(), length_);
234  if (wall_hit) {
235  const ParticleData incoming_particle(data);
236  data.set_4position(position);
237  ++wraps;
238  ActionPtr action =
239  std::make_unique<WallcrossingAction>(incoming_particle, data);
240  for (const auto &output : output_list) {
241  if (!output->is_dilepton_output() && !output->is_photon_output()) {
242  output->at_interaction(*action, 0.);
243  }
244  }
245  }
246  }
247  logg[LBox].debug("Moved ", wraps, " particles back into the box.");
248  return wraps;
249 }
250 
251 } // namespace smash
Generic algorithms on containers and ranges.
Angles provides a common interface for generating directions: i.e., two angles that should be interpr...
Definition: angles.h:59
ThreeVector threevec() const
Definition: angles.h:288
void distribute_isotropically()
Populate the object with a new direction.
Definition: angles.h:199
BoxModus: Provides a modus for infinite matter calculations.
Definition: boxmodus.h:46
const std::optional< PdgCode > jet_pdg_
Optional PDG code of the particle to use as a jet.
Definition: boxmodus.h:190
const double muq_
Charge chemical potential for thermal initialization; only used if use_thermal_ is true.
Definition: boxmodus.h:169
const double jet_mom_
Initial momentum of the jet particle; only used if insert_jet_ is true.
Definition: boxmodus.h:194
int impose_boundary_conditions(Particles *particles, const OutputsList &output_list={})
Enforces that all particles are inside the box at the beginning of an event.
Definition: boxmodus.cc:226
BoxModus(Configuration modus_config, const ExperimentParameters &parameters)
Constructor.
Definition: boxmodus.cc:66
const bool use_thermal_
Whether to use a thermal initialization for all particles instead of specific numbers.
Definition: boxmodus.h:154
const double mub_
Baryon chemical potential for thermal initialization; only used if use_thermal_ is true.
Definition: boxmodus.h:159
double initial_conditions(Particles *particles, const ExperimentParameters &parameters)
Generates initial state of the particles in the system according to specified parameters: number of p...
Definition: boxmodus.cc:104
const BoxInitialCondition initial_condition_
Initial momenta distribution: thermal or peaked momenta.
Definition: boxmodus.h:141
const std::map< PdgCode, int > init_multipl_
Particle multiplicities at initialization; required if use_thermal_ is false.
Definition: boxmodus.h:180
const bool account_for_resonance_widths_
In case of thermal initialization: true – account for resonance spectral functions,...
Definition: boxmodus.h:175
const double temperature_
Temperature of the Box in GeV.
Definition: boxmodus.h:147
const double mus_
Strange chemical potential for thermal initialization; only used if use_thermal_ is true.
Definition: boxmodus.h:164
std::map< PdgCode, double > average_multipl_
Average multiplicities in case of thermal initialization.
Definition: boxmodus.h:185
const double start_time_
Initial time of the box.
Definition: boxmodus.h:149
const double length_
Length of the cube's edge in fm.
Definition: boxmodus.h:143
Interface to the SMASH configuration files.
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
ThreeVector threevec() const
Definition: fourvector.h:329
iterator end()
Definition: fourvector.h:294
iterator begin()
Definition: fourvector.h:291
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:273
static double sample_mass_thermal(const ParticleType &ptype, double beta)
Sample resonance mass in a thermal medium.
Definition: hadgas_eos.cc:388
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:354
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:59
A pointer-like interface to global references to ParticleType objects.
Definition: particletype.h:731
Particle type contains the static properties of a particle species.
Definition: particletype.h:100
static const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
Definition: particletype.cc:99
const std::string & name() const
Definition: particletype.h:144
static const ParticleTypeList & list_all()
Definition: particletype.cc:51
double mass() const
Definition: particletype.h:147
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
size_t size() const
Definition: particles.h:87
void create(size_t n, PdgCode pdg)
Add n particles of the same type (pdg) to the list.
Definition: particles.cc:66
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
Definition: pdgcode.h:108
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
Collection of useful constants that are known at compile time.
@ Off
No spin interactions.
@ ThermalMomentaBoltzmann
A thermalized ensemble is generated, with momenta sampled from a Maxwell-Boltzmann distribution.
@ ThermalMomentaQuantum
A thermalized ensemble is generated, with momenta of baryons(mesons) sampled from a Fermi(Bose) distr...
@ PeakedMomenta
All particles have the same momentum with T being the temperature.
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
Definition: action.h:546
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > & logg
An array that stores all pre-configured Logger objects.
Definition: logging.h:245
constexpr Section output
Section for the output information.
Definition: input_keys.h:205
constexpr Section m_b_jet
Subsection for the jet in box modus.
Definition: input_keys.h:159
constexpr int p
Proton.
constexpr int n
Neutron.
int poisson(const T &lam)
Returns a Poisson distributed random number.
Definition: random.h:270
uniform_dist< T > make_uniform_distribution(T min, T max)
Definition: random.h:144
Definition: action.h:24
double sample_momenta_from_thermal(const double temperature, const double mass)
Samples a momentum from the Maxwell-Boltzmann (thermal) distribution in a faster way,...
static constexpr int LBox
Definition: boxmodus.cc:30
static bool enforce_periodic_boundaries(Iterator begin, const Iterator &end, typename std::iterator_traits< Iterator >::value_type length)
Enforces periodic boundaries on the given collection of values.
Definition: algorithms.h:53
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:41
Helper structure for Experiment.
double box_length
Length of the box in fm in case of box modus, otherwise -1.
int testparticles
Number of test-particles.
double res_lifetime_factor
Multiplicative factor to be applied to resonance lifetimes; in the case of thermal multiplicities thi...
SpinInteractionType spin_interaction_type
Whether to include spin interactions.
A container to keep track of all ever existed input keys.
Definition: input_keys.h:1255