Version: SMASH-2.1
experiment.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2012-2021
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/experiment.h"
11 
12 #include <cstdint>
13 
14 #include "smash/boxmodus.h"
15 #include "smash/collidermodus.h"
16 #include "smash/cxx14compat.h"
17 #include "smash/listmodus.h"
18 #include "smash/spheremodus.h"
19 
20 namespace smash {
21 
22 /* ExperimentBase carries everything that is needed for the evolution */
23 ExperimentPtr ExperimentBase::create(Configuration config,
24  const bf::path &output_path) {
49  const std::string modus_chooser = config.read({"General", "Modus"});
50  logg[LExperiment].debug() << "Modus for this calculation: " << modus_chooser;
51 
52  if (modus_chooser == "Box") {
53  return make_unique<Experiment<BoxModus>>(config, output_path);
54  } else if (modus_chooser == "List") {
55  return make_unique<Experiment<ListModus>>(config, output_path);
56  } else if (modus_chooser == "ListBox") {
57  return make_unique<Experiment<ListBoxModus>>(config, output_path);
58  } else if (modus_chooser == "Collider") {
59  return make_unique<Experiment<ColliderModus>>(config, output_path);
60  } else if (modus_chooser == "Sphere") {
61  return make_unique<Experiment<SphereModus>>(config, output_path);
62  } else {
63  throw InvalidModusRequest("Invalid Modus (" + modus_chooser +
64  ") requested from ExperimentBase::create.");
65  }
66 }
67 
476 
477  const int ntest = config.take({"General", "Testparticles"}, 1);
478  if (ntest <= 0) {
479  throw std::invalid_argument("Testparticle number should be positive!");
480  }
481 
482  // sets whether to consider only participants in thermodynamic outputs or not
483  const bool only_participants =
484  config.take({"Output", "Thermodynamics", "Only_Participants"}, false);
485 
486  if (only_participants && config.has_value({"Potentials"})) {
487  throw std::invalid_argument(
488  "Only_Participants option cannot be "
489  "set to True when using Potentials.");
490  }
491 
492  const std::string modus_chooser = config.take({"General", "Modus"});
493  // remove config maps of unused Modi
494  config["Modi"].remove_all_but(modus_chooser);
495 
496  double box_length = -1.0;
497  if (config.has_value({"Modi", "Box", "Length"})) {
498  box_length = config.read({"Modi", "Box", "Length"});
499  }
500 
501  if (config.has_value({"Modi", "ListBox", "Length"})) {
502  box_length = config.read({"Modi", "ListBox", "Length"});
503  }
504 
505  /* If this Delta_Time option is absent (this can be for timestepless mode)
506  * just assign 1.0 fm/c, reasonable value will be set at event initialization
507  */
508  const double dt = config.take({"General", "Delta_Time"}, 1.);
509  const double t_end = config.read({"General", "End_Time"});
510 
511  // Enforce a small time step, if the box modus is used
512  if (box_length > 0.0 && dt > box_length / 10.0) {
513  throw std::invalid_argument(
514  "Please decrease the timestep size. "
515  "A value of (dt < l_box / 10) is recommended in the boxmodus.");
516  }
517 
518  // define output clock
519  std::unique_ptr<Clock> output_clock = nullptr;
520  if (config.has_value({"Output", "Output_Times"})) {
521  if (config.has_value({"Output", "Output_Interval"})) {
522  throw std::invalid_argument(
523  "Please specify either Output_Interval or Output_Times");
524  }
525  std::vector<double> output_times = config.take({"Output", "Output_Times"});
526  // Add an output time larger than the end time so that the next time is
527  // always defined during the time evolution
528  output_times.push_back(t_end + 1.);
529  output_clock = make_unique<CustomClock>(output_times);
530  } else {
531  const double output_dt = config.take({"Output", "Output_Interval"}, t_end);
532  output_clock = make_unique<UniformClock>(0.0, output_dt);
533  }
534 
535  // Add proper error messages if photons are not configured properly.
536  // 1) Missing Photon config section.
537  if (config["Output"].has_value({"Photons"}) &&
538  (!config.has_value({"Collision_Term", "Photons"}))) {
539  throw std::invalid_argument(
540  "Photon output is enabled although photon production is disabled. "
541  "Photon production can be configured in the \"Photon\" subsection "
542  "of the \"Collision_Term\".");
543  }
544 
545  // 2) Missing Photon output section.
546  bool missing_output_2to2 = false;
547  bool missing_output_brems = false;
548  if (!(config["Output"].has_value({"Photons"}))) {
549  if (config.has_value({"Collision_Term", "Photons", "2to2_Scatterings"})) {
550  missing_output_2to2 =
551  config.read({"Collision_Term", "Photons", "2to2_Scatterings"});
552  }
553  if (config.has_value({"Collision_Term", "Photons", "Bremsstrahlung"})) {
554  missing_output_brems =
555  config.read({"Collision_Term", "Photons", "Bremsstrahlung"});
556  }
557 
558  if (missing_output_2to2 || missing_output_brems) {
559  throw std::invalid_argument(
560  "Photon output is disabled although photon production is enabled. "
561  "Please enable the photon output.");
562  }
563  }
564 
565  // Add proper error messages if dileptons are not configured properly.
566  // 1) Missing Dilepton config section.
567  if (config["Output"].has_value({"Dileptons"}) &&
568  (!config.has_value({"Collision_Term", "Dileptons"}))) {
569  throw std::invalid_argument(
570  "Dilepton output is enabled although dilepton production is disabled. "
571  "Dilepton production can be configured in the \"Dileptons\" subsection "
572  "of the \"Collision_Term\".");
573  }
574 
575  // 2) Missing Dilepton output section.
576  bool missing_output_decays = false;
577  if (!(config["Output"].has_value({"Dileptons"}))) {
578  if (config.has_value({"Collision_Term", "Dileptons", "Decays"})) {
579  missing_output_decays =
580  config.read({"Collision_Term", "Dileptons", "Decays"});
581  }
582 
583  if (missing_output_decays) {
584  throw std::invalid_argument(
585  "Dilepton output is disabled although dilepton production is "
586  "enabled. "
587  "Please enable the dilepton output.");
588  }
589  }
590 
591  auto config_coll = config["Collision_Term"];
592  /* Elastic collisions between the nucleons with the square root s
593  * below low_snn_cut are excluded. */
594  const double low_snn_cut =
595  config_coll.take({"Elastic_NN_Cutoff_Sqrts"}, 1.98);
596  const auto proton = ParticleType::try_find(pdg::p);
597  const auto pion = ParticleType::try_find(pdg::pi_z);
598  if (proton && pion &&
599  low_snn_cut > proton->mass() + proton->mass() + pion->mass()) {
600  logg[LExperiment].warn("The cut-off should be below the threshold energy",
601  " of the process: NN to NNpi");
602  }
603  const bool potential_affect_threshold =
604  config.take({"Lattice", "Potentials_Affect_Thresholds"}, false);
605  const double scale_xs = config_coll.take({"Cross_Section_Scaling"}, 1.0);
606 
607  const auto criterion =
608  config_coll.take({"Collision_Criterion"}, CollisionCriterion::Covariant);
609 
610  if (config_coll.has_value({"Fixed_Min_Cell_Length"}) &&
611  criterion != CollisionCriterion::Stochastic) {
612  throw std::invalid_argument(
613  "Only use a fixed minimal cell length with the stochastic collision "
614  "criterion.");
615  }
616  if (config_coll.has_value({"Maximum_Cross_Section"}) &&
617  criterion == CollisionCriterion::Stochastic) {
618  throw std::invalid_argument(
619  "Only use maximum cross section with the "
620  "geometric collision criterion. Use Fixed_Min_Cell_Length to change "
621  "the grid "
622  "size for the stochastic criterion.");
623  }
624 
633  const double maximum_cross_section_default =
634  ParticleType::exists("d'") ? 2000.0 : 200.0;
635 
636  bool cll_in_nucleus =
637  config.take({"Modi", "Collider", "Collisions_Within_Nucleus"}, false);
638  double maximum_cross_section = config_coll.take(
639  {"Maximum_Cross_Section"}, maximum_cross_section_default);
640  maximum_cross_section *= scale_xs;
641  return {make_unique<UniformClock>(0.0, dt),
642  std::move(output_clock),
643  config.take({"General", "Ensembles"}, 1),
644  ntest,
645  config.take({"General", "Derivatives_Mode"},
647  config.has_value({"Potentials", "VDF"})
650  config.take({"General", "Field_Derivatives_Mode"},
652  config.take({"General", "Smearing_Mode"},
654  config.take({"General", "Gaussian_Sigma"}, 1.),
655  config.take({"General", "Gauss_Cutoff_In_Sigma"}, 4.),
656  config.take({"General", "Discrete_Weight"}, 1. / 3.0),
657  config.take({"General", "Triangular_Range"}, 2.0),
658  criterion,
659  config_coll.take({"Two_to_One"}, true),
660  config_coll.take({"Included_2to2"}, ReactionsBitSet().set()),
661  config_coll.take({"Multi_Particle_Reactions"},
662  MultiParticleReactionsBitSet().reset()),
663  config_coll.take({"Strings"}, modus_chooser != "Box"),
664  config_coll.take({"Use_AQM"}, true),
665  config_coll.take({"Resonance_Lifetime_Modifier"}, 1.),
666  config_coll.take({"Strings_with_Probability"}, true),
667  config_coll.take({"NNbar_Treatment"}, NNbarTreatment::Strings),
668  low_snn_cut,
669  potential_affect_threshold,
670  box_length,
671  maximum_cross_section,
672  config_coll.take({"Fixed_Min_Cell_Length"}, 2.5),
673  cll_in_nucleus,
674  scale_xs,
675  config_coll.take({"Additional_Elastic_Cross_Section"}, 0.0),
676  only_participants};
677 }
678 
679 std::string format_measurements(const std::vector<Particles> &ensembles,
680  uint64_t scatterings_this_interval,
681  const QuantumNumbers &conserved_initial,
682  SystemTimePoint time_start, double time,
683  double E_mean_field,
684  double E_mean_field_initial) {
685  const SystemTimeSpan elapsed_seconds = SystemClock::now() - time_start;
686 
687  const QuantumNumbers current_values(ensembles);
688  const QuantumNumbers difference = current_values - conserved_initial;
689  int total_particles = 0;
690  for (const Particles &particles : ensembles) {
691  total_particles += particles.size();
692  }
693 
694  // Make sure there are no FPEs in case of IC output, were there will
695  // eventually be no more particles in the system
696  const double current_energy = current_values.momentum().x0();
697  const double energy_per_part =
698  (total_particles > 0) ? (current_energy + E_mean_field) / total_particles
699  : 0.0;
700 
701  std::ostringstream ss;
702  // clang-format off
703  ss << field<7, 3> << time
704  // total kinetic energy in the system
705  << field<11, 3> << current_energy
706  // total mean field energy in the system
707  << field<11, 3> << E_mean_field
708  // total energy in the system
709  << field<12, 3> << current_energy + E_mean_field
710  // total energy per particle in the system
711  << field<12, 6> << energy_per_part;
712  // change in total energy per particle (unless IC output is enabled)
713  if (total_particles == 0) {
714  ss << field<13, 6> << "N/A";
715  } else {
716  ss << field<13, 6> << (difference.momentum().x0()
717  + E_mean_field - E_mean_field_initial)
718  / total_particles;
719  }
720  ss << field<14, 3> << scatterings_this_interval
721  << field<10, 3> << total_particles
722  << field<9, 3> << elapsed_seconds;
723  // clang-format on
724  return ss.str();
725 }
726 
728  const Potentials &potentials,
730  RectangularLattice<std::pair<ThreeVector, ThreeVector>> *em_lattice,
731  const ExperimentParameters &parameters) {
732  // basic parameters and variables
733  const double V_cell = (jmuB_lat.cell_sizes())[0] *
734  (jmuB_lat.cell_sizes())[1] * (jmuB_lat.cell_sizes())[2];
735 
736  double E_mean_field = 0.0;
737  double density_mean = 0.0;
738  double density_variance = 0.0;
739 
740  /*
741  * We anticipate having other options, like the vector DFT potentials, in the
742  * future, hence we include checking which potentials are used.
743  */
744  if (potentials.use_skyrme()) {
745  /*
746  * Calculating the symmetry energy contribution to the total mean field
747  * energy in the system is not implemented at this time.
748  */
749  if (potentials.use_symmetry() &&
750  parameters.outputclock->current_time() == 0.0) {
751  logg[LExperiment].warn()
752  << "Note:"
753  << "\nSymmetry energy is not included in the mean field calculation."
754  << "\n\n";
755  }
756 
757  /*
758  * Skyrme potential parameters:
759  * C1GeV are the Skyrme coefficients converted to GeV,
760  * b1 are the powers of the baryon number density entering the expression
761  * for the energy density of the system. Note that these exponents are
762  * larger by 1 than those for the energy of a particle (which are used in
763  * Potentials class). The formula for a total mean field energy due to a
764  * Skyrme potential is E_MF = \sum_i (C_i/b_i) ( n_B^b_i )/( n_0^(b_i - 1) )
765  * where nB is the local rest frame baryon number density and n_0 is the
766  * saturation density. Then the single particle potential follows from
767  * V = d E_MF / d n_B .
768  */
769  double C1GeV = (potentials.skyrme_a()) / 1000.0;
770  double C2GeV = (potentials.skyrme_b()) / 1000.0;
771  double b1 = 2.0;
772  double b2 = (potentials.skyrme_tau()) + 1.0;
773 
774  /*
775  * Note: calculating the mean field only works if lattice is used.
776  * We iterate over the nodes of the baryon density lattice to sum their
777  * contributions to the total mean field.
778  */
779  int number_of_nodes = 0;
780  double lattice_mean_field_total = 0.0;
781 
782  for (auto &node : jmuB_lat) {
783  number_of_nodes++;
784  // the rest frame density
785  double rhoB = node.rho();
786  // the computational frame density
787  const double j0B = node.jmu_net().x0();
788 
789  const double abs_rhoB = std::abs(rhoB);
790  if (abs_rhoB < very_small_double) {
791  continue;
792  }
793  density_mean += j0B;
794  density_variance += j0B * j0B;
795 
796  /*
797  * The mean-field energy for the Skyrme potential. Note: this expression
798  * is only exact in the rest frame, and is expected to significantly
799  * deviate from the correct value for systems that are considerably
800  * relativistic. Note: symmetry energy is not taken into the account.
801  *
802  * TODO: Add symmetry energy.
803  */
804  double mean_field_contribution_1 = (C1GeV / b1) * std::pow(abs_rhoB, b1) /
805  std::pow(nuclear_density, b1 - 1);
806  double mean_field_contribution_2 = (C2GeV / b2) * std::pow(abs_rhoB, b2) /
807  std::pow(nuclear_density, b2 - 1);
808 
809  lattice_mean_field_total +=
810  V_cell * (mean_field_contribution_1 + mean_field_contribution_2);
811  }
812 
813  // logging statistical properties of the density calculation
814  density_mean = density_mean / number_of_nodes;
815  density_variance = density_variance / number_of_nodes;
816  double density_scaled_variance =
817  std::sqrt(density_variance - density_mean * density_mean) /
818  density_mean;
819  logg[LExperiment].debug() << "\t\t\t\t\t";
820  logg[LExperiment].debug()
821  << "\n\t\t\t\t\t density mean = " << density_mean;
822  logg[LExperiment].debug()
823  << "\n\t\t\t\t\t density scaled variance = " << density_scaled_variance;
824  logg[LExperiment].debug()
825  << "\n\t\t\t\t\t total mean_field = "
826  << lattice_mean_field_total * parameters.testparticles *
827  parameters.n_ensembles
828  << "\n";
829 
830  E_mean_field = lattice_mean_field_total;
831  } // if (potentials.use_skyrme())
832 
833  if (potentials.use_vdf()) {
834  /*
835  * Safety check:
836  * Calculating the symmetry energy contribution to the total mean field
837  * energy in the system is not implemented at this time.
838  */
839  if (potentials.use_symmetry() &&
840  parameters.outputclock->current_time() == 0.0) {
841  logg[LExperiment].error()
842  << "\nSymmetry energy is not included in the VDF mean-field "
843  "calculation"
844  << "\nas VDF potentials haven't been fitted with symmetry energy."
845  << "\n\n";
846  }
847 
848  /*
849  * The total mean-field energy density due to a VDF potential is
850  * E_MF = \sum_i C_i rho^(b_i - 2) *
851  * * [j_0^2 - rho^2 * (b_i - 1)/b_i] / rho_0^(b_i - 1)
852  * where j_0 is the local computational frame baryon density, rho is the
853  * local rest frame baryon density, and rho_0 is the saturation density.
854  */
855 
856  // saturation density of nuclear matter specified in the VDF parameters
857  double rhoB_0 = potentials.saturation_density();
858 
859  /*
860  * Note: calculating the mean field only works if lattice is used.
861  * We iterate over the nodes of the baryon density lattice to sum their
862  * contributions to the total mean field.
863  */
864  int number_of_nodes = 0;
865  double lattice_mean_field_total = 0.0;
866 
867  for (auto &node : jmuB_lat) {
868  number_of_nodes++;
869  // the rest frame density
870  double rhoB = node.rho();
871  // the computational frame density
872  const double j0B = node.jmu_net().x0();
873  double abs_rhoB = std::abs(rhoB);
874  density_mean += j0B;
875  density_variance += j0B * j0B;
876 
877  /*
878  * The mean-field energy for the VDF potential. This expression is correct
879  * in any frame, and in the rest frame conforms to the Skyrme mean-field
880  * energy (if same coefficients and powers are used).
881  */
882  // in order to prevent dividing by zero in case any b_i < 2.0
883  if (abs_rhoB < very_small_double) {
884  abs_rhoB = very_small_double;
885  }
886  double mean_field_contribution = 0.0;
887  for (int i = 0; i < potentials.number_of_terms(); i++) {
888  mean_field_contribution +=
889  potentials.coeffs()[i] *
890  std::pow(abs_rhoB, potentials.powers()[i] - 2.0) *
891  (j0B * j0B -
892  ((potentials.powers()[i] - 1.0) / potentials.powers()[i]) *
893  abs_rhoB * abs_rhoB) /
894  std::pow(rhoB_0, potentials.powers()[i] - 1.0);
895  }
896  lattice_mean_field_total += V_cell * mean_field_contribution;
897  }
898 
899  // logging statistical properties of the density calculation
900  density_mean = density_mean / number_of_nodes;
901  density_variance = density_variance / number_of_nodes;
902  double density_scaled_variance =
903  std::sqrt(density_variance - density_mean * density_mean) /
904  density_mean;
905  logg[LExperiment].debug() << "\t\t\t\t\t";
906  logg[LExperiment].debug()
907  << "\n\t\t\t\t\t density mean = " << density_mean;
908  logg[LExperiment].debug()
909  << "\n\t\t\t\t\t density scaled variance = " << density_scaled_variance;
910  logg[LExperiment].debug()
911  << "\n\t\t\t\t\t total mean_field = "
912  << lattice_mean_field_total * parameters.testparticles *
913  parameters.n_ensembles
914  << "\n";
915 
916  E_mean_field = lattice_mean_field_total;
917  }
918 
919  double electromagnetic_potential = 0.0;
920  if (potentials.use_coulomb() && em_lattice) {
921  // Use cell volume of electromagnetic fields lattice even though it should
922  // be the same as for net-baryon density
923  double V_cell_em = em_lattice->cell_sizes()[0] *
924  em_lattice->cell_sizes()[1] *
925  em_lattice->cell_sizes()[2];
926  for (auto &fields : *em_lattice) {
927  // Energy is 0.5 * int E^2 + B^2 dV
928  electromagnetic_potential +=
929  hbarc * 0.5 * V_cell_em * (fields.first.sqr() + fields.second.sqr());
930  }
931  }
932  logg[LExperiment].debug() << "Total energy in electromagnetic field = "
933  << electromagnetic_potential;
934  E_mean_field += electromagnetic_potential;
935  /*
936  * E_mean_field is multiplied by the number of testparticles per particle and
937  * the number of parallel ensembles because the total kinetic energy tracked
938  * is that of all particles in the simulation, including test-particles and/or
939  * ensembles, and so this way is more consistent.
940  */
941  E_mean_field =
942  E_mean_field * parameters.testparticles * parameters.n_ensembles;
943 
944  return E_mean_field;
945 }
946 
947 EventInfo fill_event_info(const std::vector<Particles> &ensembles,
948  double E_mean_field, double modus_impact_parameter,
949  const ExperimentParameters &parameters,
950  bool projectile_target_interact) {
951  const QuantumNumbers current_values(ensembles);
952  const double E_kinetic_total = current_values.momentum().x0();
953  const double E_total = E_kinetic_total + E_mean_field;
954 
955  EventInfo event_info{modus_impact_parameter,
956  parameters.box_length,
957  parameters.outputclock->current_time(),
958  E_kinetic_total,
959  E_mean_field,
960  E_total,
961  parameters.testparticles,
962  parameters.n_ensembles,
963  !projectile_target_interact};
964  return event_info;
965 }
966 
967 } // namespace smash
Interface to the SMASH configuration files.
bool has_value(std::initializer_list< const char * > keys) const
Returns whether there is a non-empty value behind the requested keys.
void remove_all_but(const std::string &key)
Removes all entries in the map except for key.
Value take(std::initializer_list< const char * > keys)
The default interface for SMASH to read configuration values.
Value read(std::initializer_list< const char * > keys) const
Additional interface for SMASH to read configuration values without removing them.
static std::unique_ptr< ExperimentBase > create(Configuration config, const bf::path &output_path)
Factory method that creates and initializes a new Experiment<Modus>.
double x0() const
Definition: fourvector.h:308
static const ParticleTypePtr try_find(PdgCode pdgcode)
Returns the ParticleTypePtr for the given pdgcode.
Definition: particletype.cc:89
static bool exists(PdgCode pdgcode)
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
A class that stores parameters of potentials, calculates potentials and their gradients.
Definition: potentials.h:32
const std::vector< double > & powers() const
Definition: potentials.h:327
virtual bool use_symmetry() const
Definition: potentials.h:307
const std::vector< double > & coeffs() const
Definition: potentials.h:325
virtual bool use_skyrme() const
Definition: potentials.h:305
virtual bool use_coulomb() const
Definition: potentials.h:309
double skyrme_a() const
Definition: potentials.h:312
double skyrme_tau() const
Definition: potentials.h:316
int number_of_terms() const
Definition: potentials.h:329
double skyrme_b() const
Definition: potentials.h:314
virtual bool use_vdf() const
Definition: potentials.h:321
double saturation_density() const
Definition: potentials.h:323
A container for storing conserved values.
FourVector momentum() const
A container class to hold all the arrays on the lattice and access them.
Definition: lattice.h:47
const std::array< double, 3 > & cell_sizes() const
Definition: lattice.h:160
std::bitset< 10 > ReactionsBitSet
Container for the 2 to 2 reactions in the code.
@ Strings
Use string fragmentation.
@ Stochastic
Stochastic Criteiron.
@ Covariant
Covariant Criterion.
std::bitset< 3 > MultiParticleReactionsBitSet
Container for the n to m reactions in the code.
#define SMASH_SOURCE_LOCATION
Hackery that is required to output the location in the source code where the log statement occurs.
Definition: logging.h:243
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
constexpr int p
Proton.
constexpr int pi_z
π⁰.
Definition: action.h:24
SystemClock::duration SystemTimeSpan
The time duration type (alias) used for measuring run times.
Definition: chrono.h:28
std::string format_measurements(const std::vector< Particles > &ensembles, uint64_t scatterings_this_interval, const QuantumNumbers &conserved_initial, SystemTimePoint time_start, double time, double E_mean_field, double E_mean_field_initial)
Generate a string which will be printed to the screen when SMASH is running.
Definition: experiment.cc:679
constexpr double very_small_double
A very small double, used to avoid division by zero.
Definition: constants.h:40
double calculate_mean_field_energy(const Potentials &potentials, RectangularLattice< smash::DensityOnLattice > &jmu_B_lat, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *em_lattice, const ExperimentParameters &parameters)
Calculate the total mean field energy of the system; this will be printed to the screen when SMASH is...
Definition: experiment.cc:727
static constexpr int LExperiment
constexpr double nuclear_density
Ground state density of symmetric nuclear matter [fm^-3].
Definition: constants.h:48
EventInfo fill_event_info(const std::vector< Particles > &ensembles, double E_mean_field, double modus_impact_parameter, const ExperimentParameters &parameters, bool projectile_target_interact)
Generate the EventInfo object which is passed to outputs_.
Definition: experiment.cc:947
constexpr double hbarc
GeV <-> fm conversion factor.
Definition: constants.h:25
ExperimentParameters create_experiment_parameters(Configuration config)
Gathers all general Experiment parameters.
Definition: experiment.cc:474
std::chrono::time_point< std::chrono::system_clock > SystemTimePoint
Type (alias) that is used to store the current time.
Definition: chrono.h:22
Structure to contain custom data for output.
Helper structure for Experiment.
double box_length
Length of the box in fm in case of box modus, otherwise -1.
int n_ensembles
Number of parallel ensembles.
std::unique_ptr< Clock > outputclock
Output clock to keep track of the next output time.
int testparticles
Number of test-particles.