Version: SMASH-2.0
boxmodus.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2020
3  * SMASH Team
4  *
5  * GNU General Public License (GPLv3 or later)
6  */
7 #include <cmath>
8 #include <cstdio>
9 #include <cstdlib>
10 #include <list>
11 #include <map>
12 #include <utility>
13 #include <vector>
14 
15 #include "smash/algorithms.h"
16 #include "smash/angles.h"
17 #include "smash/boxmodus.h"
18 #include "smash/constants.h"
19 #include "smash/cxx14compat.h"
21 #include "smash/logging.h"
22 #include "smash/quantumsampling.h"
23 #include "smash/random.h"
24 #include "smash/threevector.h"
26 
27 namespace smash {
28 static constexpr int LBox = LogArea::Box::id;
29 
30 /* console output on startup of box specific parameters */
31 std::ostream &operator<<(std::ostream &out, const BoxModus &m) {
32  out << "-- Box Modus:\nSize of the box: (" << m.length_ << " fm)³\n";
33  if (m.use_thermal_) {
34  out << "Thermal multiplicities "
35  << "(T = " << m.temperature_ << " GeV, muB = " << m.mub_
36  << " GeV, muS = " << m.mus_ << " GeV, muQ = " << m.muq_ << " GeV)\n";
37  } else {
38  for (const auto &p : m.init_multipl_) {
39  ParticleTypePtr ptype = &ParticleType::find(p.first);
40  out << ptype->name() << " initial multiplicity " << p.second << '\n';
41  }
42  }
43  switch (m.initial_condition_) {
45  out << "All initial momenta = 3T = " << 3 * m.temperature_ << " GeV\n";
46  break;
48  out << "Boltzmann momentum distribution with T = " << m.temperature_
49  << " GeV.\n";
50  break;
52  out << "Fermi/Bose momentum distribution with T = " << m.temperature_
53  << " GeV.\n";
54  break;
55  }
56  if (m.insert_jet_) {
58  out << "Adding a " << ptype->name() << " as a jet in the middle "
59  << "of the box with " << m.jet_mom_ << " GeV initial momentum.\n";
60  }
61  return out;
62 }
63 
220  const ExperimentParameters &parameters)
221  : initial_condition_(modus_config.take({"Box", "Initial_Condition"})),
222  length_(modus_config.take({"Box", "Length"})),
223  equilibration_time_(
224  modus_config.take({"Box", "Equilibration_Time"}, -1.)),
225  temperature_(modus_config.take({"Box", "Temperature"})),
226  start_time_(modus_config.take({"Box", "Start_Time"}, 0.)),
227  use_thermal_(
228  modus_config.take({"Box", "Use_Thermal_Multiplicities"}, false)),
229  mub_(modus_config.take({"Box", "Baryon_Chemical_Potential"}, 0.)),
230  mus_(modus_config.take({"Box", "Strange_Chemical_Potential"}, 0.)),
231  muq_(modus_config.take({"Box", "Charge_Chemical_Potential"}, 0.)),
232  account_for_resonance_widths_(
233  modus_config.take({"Box", "Account_Resonance_Widths"}, true)),
234  init_multipl_(use_thermal_
235  ? std::map<PdgCode, int>()
236  : modus_config.take({"Box", "Init_Multiplicities"})
237  .convert_for(init_multipl_)),
238  insert_jet_(modus_config.has_value({"Box", "Jet", "Jet_PDG"})),
239  jet_pdg_(insert_jet_ ? modus_config.take({"Box", "Jet", "Jet_PDG"})
240  .convert_for(jet_pdg_)
241  : pdg::p), // dummy default; never used
242  jet_mom_(modus_config.take({"Box", "Jet", "Jet_Momentum"}, 20.)) {
243  if (parameters.res_lifetime_factor < 0.) {
244  throw std::invalid_argument(
245  "Resonance lifetime modifier cannot be negative!");
246  }
247  // Check consistency, just in case
248  if (std::abs(length_ - parameters.box_length) > really_small) {
249  throw std::runtime_error("Box length inconsistency");
250  }
251 }
252 
254  const ExperimentParameters &parameters) {
255  double momentum_radial = 0.0, mass = 0.0;
256  Angles phitheta;
257  FourVector momentum_total(0, 0, 0, 0);
258  auto uniform_length = random::make_uniform_distribution(0.0, this->length_);
259  const double T = this->temperature_;
260  const double V = length_ * length_ * length_;
261  /* Create NUMBER OF PARTICLES according to configuration, or thermal case */
262  if (use_thermal_) {
263  if (average_multipl_.empty()) {
264  for (const ParticleType &ptype : ParticleType::list_all()) {
265  if (HadronGasEos::is_eos_particle(ptype)) {
266  const double lifetime_factor =
267  ptype.is_stable() ? 1. : parameters.res_lifetime_factor;
268  const double n = lifetime_factor * HadronGasEos::partial_density(
269  ptype, T, mub_, mus_, muq_,
271  average_multipl_[ptype.pdgcode()] = n * V * parameters.testparticles;
272  }
273  }
274  }
275  double nb_init = 0.0, ns_init = 0.0, nq_init = 0.0;
276  for (const auto &mult : average_multipl_) {
277  const int thermal_mult_int = random::poisson(mult.second);
278  particles->create(thermal_mult_int, mult.first);
279  nb_init += mult.second * mult.first.baryon_number();
280  ns_init += mult.second * mult.first.strangeness();
281  nq_init += mult.second * mult.first.charge();
282  logg[LBox].debug(mult.first, " initial multiplicity ", thermal_mult_int);
283  }
284  logg[LBox].info("Initial hadron gas baryon density ", nb_init);
285  logg[LBox].info("Initial hadron gas strange density ", ns_init);
286  logg[LBox].info("Initial hadron gas charge density ", nq_init);
287  } else {
288  for (const auto &p : init_multipl_) {
289  particles->create(p.second * parameters.testparticles, p.first);
290  logg[LBox].debug("Particle ", p.first, " initial multiplicity ",
291  p.second);
292  }
293  }
294  std::unique_ptr<QuantumSampling> quantum_sampling;
296  quantum_sampling = make_unique<QuantumSampling>(init_multipl_, V, T);
297  }
298  for (ParticleData &data : *particles) {
299  /* Set MOMENTUM SPACE distribution */
301  /* initial thermal momentum is the average 3T */
302  momentum_radial = 3.0 * T;
303  mass = data.pole_mass();
304  } else {
305  if (this->initial_condition_ ==
307  /* thermal momentum according Maxwell-Boltzmann distribution */
309  ? data.type().mass()
310  : HadronGasEos::sample_mass_thermal(data.type(), 1.0 / T);
311  momentum_radial = sample_momenta_from_thermal(T, mass);
312  } else if (this->initial_condition_ ==
314  /*
315  * Sampling the thermal momentum according Bose/Fermi/Boltzmann
316  * distribution.
317  * We take the pole mass as the mass.
318  */
319  mass = data.type().mass();
320  momentum_radial = quantum_sampling->sample(data.pdgcode());
321  }
322  }
323  phitheta.distribute_isotropically();
324  logg[LBox].debug(data.type().name(), "(id ", data.id(),
325  ") radial momentum ", momentum_radial, ", direction",
326  phitheta);
327  data.set_4momentum(mass, phitheta.threevec() * momentum_radial);
328  momentum_total += data.momentum();
329 
330  /* Set COORDINATE SPACE distribution */
331  ThreeVector pos{uniform_length(), uniform_length(), uniform_length()};
332  data.set_4position(FourVector(start_time_, pos));
334  data.set_formation_time(start_time_);
335  }
336 
337  /* Make total 3-momentum 0 */
338  for (ParticleData &data : *particles) {
339  data.set_4momentum(data.momentum().abs(),
340  data.momentum().threevec() -
341  momentum_total.threevec() / particles->size());
342  }
343 
344  /* Add a single highly energetic particle in the center of the box (jet) */
345  if (insert_jet_) {
346  auto &jet_particle = particles->create(jet_pdg_);
347  jet_particle.set_formation_time(start_time_);
348  jet_particle.set_4position(FourVector(start_time_, 0., 0., 0.));
349  jet_particle.set_4momentum(ParticleType::find(jet_pdg_).mass(),
350  ThreeVector(jet_mom_, 0., 0.));
351  }
352 
353  /* Recalculate total momentum */
354  momentum_total = FourVector(0, 0, 0, 0);
355  for (ParticleData &data : *particles) {
356  momentum_total += data.momentum();
357  /* IC: debug checks */
358  logg[LBox].debug() << data;
359  }
360  /* allows to check energy conservation */
361  logg[LBox].debug() << "Initial total 4-momentum [GeV]: " << momentum_total;
362  return start_time_;
363 }
364 
366  const OutputsList &output_list) {
367  int wraps = 0;
368 
369  for (ParticleData &data : *particles) {
370  FourVector position = data.position();
371  bool wall_hit = enforce_periodic_boundaries(position.begin() + 1,
372  position.end(), length_);
373  if (wall_hit) {
374  const ParticleData incoming_particle(data);
375  data.set_4position(position);
376  ++wraps;
377  ActionPtr action =
378  make_unique<WallcrossingAction>(incoming_particle, data);
379  for (const auto &output : output_list) {
380  if (!output->is_dilepton_output() && !output->is_photon_output()) {
381  output->at_interaction(*action, 0.);
382  }
383  }
384  }
385  }
386  logg[LBox].debug("Moved ", wraps, " particles back into the box.");
387  return wraps;
388 }
389 
390 } // namespace smash
smash
Definition: action.h:24
smash::BoxModus::account_for_resonance_widths_
const bool account_for_resonance_widths_
In case of thermal initialization: true – account for resonance spectral functions,...
Definition: boxmodus.h:166
smash::BoxModus::muq_
const double muq_
Charge chemical potential for thermal initialization; only used if use_thermal_ is true.
Definition: boxmodus.h:160
algorithms.h
smash::ParticleData
Definition: particledata.h:52
smash::BoxModus::mub_
const double mub_
Baryon chemical potential for thermal initialization; only used if use_thermal_ is true.
Definition: boxmodus.h:150
smash::BoxModus::init_multipl_
const std::map< PdgCode, int > init_multipl_
Particle multiplicities at initialization; required if use_thermal_ is false.
Definition: boxmodus.h:171
smash::BoxModus::length_
const double length_
Length of the cube's edge in fm/c.
Definition: boxmodus.h:134
cxx14compat.h
smash::BoxModus::use_thermal_
const bool use_thermal_
Whether to use a thermal initialization for all particles instead of specific numbers.
Definition: boxmodus.h:145
smash::BoxModus::jet_pdg_
const PdgCode jet_pdg_
Pdg of the particle to use as a jet; necessary if insert_jet_ is true, unused otherwise.
Definition: boxmodus.h:187
smash::BoxModus::temperature_
const double temperature_
Temperature of the Box in GeV.
Definition: boxmodus.h:138
smash::enforce_periodic_boundaries
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
smash::BoxModus::insert_jet_
const bool insert_jet_
Whether to insert a single high energy particle at the center of the box (0,0,0).
Definition: boxmodus.h:182
smash::operator<<
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Definition: action.h:518
smash::BoxModus
Definition: boxmodus.h:46
smash::Angles::distribute_isotropically
void distribute_isotropically()
Populate the object with a new direction.
Definition: angles.h:188
experimentparameters.h
smash::BoxModus::initial_condition_
const BoxInitialCondition initial_condition_
Initial momenta distribution: thermal or peaked momenta.
Definition: boxmodus.h:132
smash::FourVector::begin
iterator begin()
Definition: fourvector.h:281
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::ExperimentParameters::res_lifetime_factor
double res_lifetime_factor
Multiplicative factor to be applied to resonance lifetimes; in the case of thermal multiplicities thi...
Definition: experimentparameters.h:64
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
smash::really_small
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
smash::ParticleType::find
static const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
Definition: particletype.cc:99
random.h
smash::BoxModus::mus_
const double mus_
Strange chemical potential for thermal initialization; only used if use_thermal_ is true.
Definition: boxmodus.h:155
angles.h
smash::Configuration
Interface to the SMASH configuration files.
Definition: configuration.h:464
smash::Particles::create
void create(size_t n, PdgCode pdg)
Add n particles of the same type (pdg) to the list.
Definition: particles.cc:66
wallcrossingaction.h
smash::ParticleTypePtr
Definition: particletype.h:665
smash::ThreeVector
Definition: threevector.h:31
boxmodus.h
smash::HadronGasEos::sample_mass_thermal
static double sample_mass_thermal(const ParticleType &ptype, double beta)
Sample resonance mass in a thermal medium.
Definition: hadgas_eos.cc:385
threevector.h
smash::BoxModus::average_multipl_
std::map< PdgCode, double > average_multipl_
Average multiplicities in case of thermal initialization.
Definition: boxmodus.h:176
quantumsampling.h
smash::ParticleType
Definition: particletype.h:97
smash::ParticleType::name
const std::string & name() const
Definition: particletype.h:141
BoxInitialCondition::ThermalMomentaQuantum
smash::random::poisson
int poisson(const T &lam)
Returns a Poisson distributed random number.
Definition: random.h:226
smash::random::make_uniform_distribution
uniform_dist< T > make_uniform_distribution(T min, T max)
Definition: random.h:135
BoxInitialCondition::ThermalMomentaBoltzmann
smash::FourVector::end
iterator end()
Definition: fourvector.h:284
smash::LBox
static constexpr int LBox
Definition: boxmodus.cc:28
smash::Angles::threevec
ThreeVector threevec() const
Definition: angles.h:268
smash::BoxModus::initial_conditions
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:253
smash::Particles
Definition: particles.h:33
smash::BoxModus::BoxModus
BoxModus(Configuration modus_config, const ExperimentParameters &parameters)
Constructor.
Definition: boxmodus.cc:219
smash::HadronGasEos::is_eos_particle
static bool is_eos_particle(const ParticleType &ptype)
Check if a particle belongs to the EoS.
Definition: hadgas_eos.h:355
constants.h
logging.h
BoxInitialCondition::PeakedMomenta
smash::ExperimentParameters
Helper structure for Experiment.
Definition: experimentparameters.h:24
smash::FourVector
Definition: fourvector.h:33
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::pdg::n
constexpr int n
Neutron.
Definition: pdgcode_constants.h:30
smash::BoxModus::impose_boundary_conditions
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:365
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::ExperimentParameters::testparticles
int testparticles
Number of test particle.
Definition: experimentparameters.h:32
smash::FourVector::threevec
ThreeVector threevec() const
Definition: fourvector.h:319
smash::BoxModus::start_time_
const double start_time_
Initial time of the box.
Definition: boxmodus.h:140
smash::ParticleType::list_all
static const ParticleTypeList & list_all()
Definition: particletype.cc:51
smash::BoxModus::jet_mom_
const double jet_mom_
Initial momentum of the jet particle; only used if insert_jet_ is true.
Definition: boxmodus.h:191