7 #ifndef SRC_INCLUDE_SMASH_EXPERIMENT_H_ 
    8 #define SRC_INCLUDE_SMASH_EXPERIMENT_H_ 
   41 #ifdef SMASH_USE_HEPMC 
   44 #ifdef SMASH_USE_RIVET 
   68 template <
typename T, 
typename Ratio>
 
   70                            const chrono::duration<T, Ratio> &seconds) {
 
   71   using Seconds = chrono::duration<double>;
 
   72   using Minutes = chrono::duration<double, std::ratio<60>>;
 
   73   using Hours = chrono::duration<double, std::ratio<60 * 60>>;
 
   74   constexpr Minutes threshold_for_minutes{10};
 
   75   constexpr Hours threshold_for_hours{3};
 
   76   if (seconds < threshold_for_minutes) {
 
   77     return out << Seconds(seconds).count() << 
" [s]";
 
   79   if (seconds < threshold_for_hours) {
 
   80     return out << Minutes(seconds).count() << 
" [min]";
 
   82   return out << Hours(seconds).count() << 
" [h]";
 
   87 static constexpr 
int LMain = LogArea::Main::id;
 
  127                                                 const bf::path &output_path);
 
  143     using std::invalid_argument::invalid_argument;
 
  152     using std::invalid_argument::invalid_argument;
 
  156 template <
typename Modus>
 
  158 template <
typename Modus>
 
  185 template <
typename Modus>
 
  272                       bool include_pauli_blocking = 
true);
 
  307                                        const double end_time_propagation,
 
  308                                        const double end_time_run);
 
  448   std::unique_ptr<RectangularLattice<FourVector>> 
UB_lat_ = 
nullptr;
 
  454   std::unique_ptr<RectangularLattice<FourVector>> 
UI3_lat_ = 
nullptr;
 
  460   std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
 
  464   std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
 
  468   std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
 
  472   std::unique_ptr<RectangularLattice<EnergyMomentumTensor>> 
Tmn_;
 
  479   std::unique_ptr<RectangularLattice<std::array<FourVector, 4>>>
 
  487   std::unique_ptr<RectangularLattice<std::array<FourVector, 4>>>
 
  695   friend std::ostream &operator<<<>(std::ostream &out, 
const Experiment &e);
 
  699 template <
typename Modus>
 
  701   out << 
"End time: " << e.
end_time_ << 
" fm/c\n";
 
  706 template <
typename Modus>
 
  708                                       const std::string &content,
 
  709                                       const bf::path &output_path,
 
  711   logg[
LExperiment].info() << 
"Adding output " << content << 
" of format " 
  714   if (
format == 
"VTK" && content == 
"Particles") {
 
  715     outputs_.emplace_back(
 
  716         make_unique<VtkOutput>(output_path, content, out_par));
 
  717   } 
else if (
format == 
"Root") {
 
  718 #ifdef SMASH_USE_ROOT 
  719     if (content == 
"Initial_Conditions") {
 
  720       outputs_.emplace_back(
 
  721           make_unique<RootOutput>(output_path, 
"SMASH_IC", out_par));
 
  723       outputs_.emplace_back(
 
  724           make_unique<RootOutput>(output_path, content, out_par));
 
  728         "Root output requested, but Root support not compiled in");
 
  730   } 
else if (
format == 
"Binary") {
 
  731     if (content == 
"Collisions" || content == 
"Dileptons" ||
 
  732         content == 
"Photons") {
 
  733       outputs_.emplace_back(
 
  734           make_unique<BinaryOutputCollisions>(output_path, content, out_par));
 
  735     } 
else if (content == 
"Particles") {
 
  736       outputs_.emplace_back(
 
  737           make_unique<BinaryOutputParticles>(output_path, content, out_par));
 
  738     } 
else if (content == 
"Initial_Conditions") {
 
  739       outputs_.emplace_back(make_unique<BinaryOutputInitialConditions>(
 
  740           output_path, content, out_par));
 
  742   } 
else if (
format == 
"Oscar1999" || 
format == 
"Oscar2013") {
 
  743     outputs_.emplace_back(
 
  745   } 
else if (content == 
"Thermodynamics" && 
format == 
"ASCII") {
 
  746     outputs_.emplace_back(
 
  747         make_unique<ThermodynamicOutput>(output_path, content, out_par));
 
  748   } 
else if (content == 
"Thermodynamics" &&
 
  749              (
format == 
"Lattice_ASCII" || 
format == 
"Lattice_Binary")) {
 
  750     printout_full_lattice_any_td_ = 
true;
 
  751     if (
format == 
"Lattice_ASCII") {
 
  752       printout_full_lattice_ascii_td_ = 
true;
 
  754     if (
format == 
"Lattice_Binary") {
 
  755       printout_full_lattice_binary_td_ = 
true;
 
  757     outputs_.emplace_back(make_unique<ThermodynamicLatticeOutput>(
 
  758         output_path, content, out_par, printout_full_lattice_ascii_td_,
 
  759         printout_full_lattice_binary_td_));
 
  760   } 
else if (content == 
"Thermodynamics" && 
format == 
"VTK") {
 
  761     printout_lattice_td_ = 
true;
 
  762     outputs_.emplace_back(
 
  763         make_unique<VtkOutput>(output_path, content, out_par));
 
  764   } 
else if (content == 
"Initial_Conditions" && 
format == 
"ASCII") {
 
  765     outputs_.emplace_back(
 
  766         make_unique<ICOutput>(output_path, 
"SMASH_IC", out_par));
 
  767   } 
else if ((
format == 
"HepMC") || (
format == 
"HepMC_asciiv3") ||
 
  768              (
format == 
"HepMC_treeroot")) {
 
  769 #ifdef SMASH_USE_HEPMC 
  770     if (content == 
"Particles") {
 
  771       if ((
format == 
"HepMC") || (
format == 
"HepMC_asciiv3")) {
 
  772         outputs_.emplace_back(make_unique<HepMcOutput>(
 
  773             output_path, 
"SMASH_HepMC_particles", 
false, 
"asciiv3"));
 
  774       } 
else if (
format == 
"HepMC_treeroot") {
 
  775 #ifdef SMASH_USE_HEPMC_ROOTIO 
  776         outputs_.emplace_back(make_unique<HepMcOutput>(
 
  777             output_path, 
"SMASH_HepMC_particles", 
false, 
"root"));
 
  780             "Requested HepMC_treeroot output not available, " 
  781             "ROOT or HepMC3 ROOTIO missing or not found by cmake.");
 
  784     } 
else if (content == 
"Collisions") {
 
  785       if ((
format == 
"HepMC") || (
format == 
"HepMC_asciiv3")) {
 
  786         outputs_.emplace_back(make_unique<HepMcOutput>(
 
  787             output_path, 
"SMASH_HepMC_collisions", 
true, 
"asciiv3"));
 
  788       } 
else if (
format == 
"HepMC_treeroot") {
 
  789 #ifdef SMASH_USE_HEPMC_ROOTIO 
  790         outputs_.emplace_back(make_unique<HepMcOutput>(
 
  791             output_path, 
"SMASH_HepMC_collisions", 
true, 
"root"));
 
  794             "Requested HepMC_treeroot output not available, " 
  795             "ROOT or HepMC3 ROOTIO missing or not found by cmake.");
 
  800           "HepMC only available for Particles and " 
  801           "Collisions content. Requested for " +
 
  806         "HepMC output requested, but HepMC support not compiled in");
 
  808   } 
else if (content == 
"Coulomb" && 
format == 
"VTK") {
 
  809     outputs_.emplace_back(
 
  810         make_unique<VtkOutput>(output_path, 
"Fields", out_par));
 
  811   } 
else if (content == 
"Rivet") {
 
  812 #ifdef SMASH_USE_RIVET 
  814     static bool rivet_format_already_selected = 
false;
 
  816     if (rivet_format_already_selected) {
 
  818           "Rivet output format can only be one, either YODA or YODA-full. " 
  819           "Only your first valid choice will be used.");
 
  823       outputs_.emplace_back(
 
  824           make_unique<RivetOutput>(output_path, 
"SMASH_Rivet", 
false, out_par));
 
  825       rivet_format_already_selected = 
true;
 
  826     } 
else if (
format == 
"YODA-full") {
 
  827       outputs_.emplace_back(make_unique<RivetOutput>(
 
  828           output_path, 
"SMASH_Rivet_full", 
true, out_par));
 
  829       rivet_format_already_selected = 
true;
 
  832                               "not one of YODA or YODA-full");
 
  836         "Rivet output requested, but Rivet support not compiled in");
 
  840         << 
"Unknown combination of format (" << 
format << 
") and content (" 
  841         << content << 
"). Fix the config.";
 
 1072 template <
typename Modus>
 
 1076       modus_(config[
"Modi"], parameters_),
 
 1077       ensembles_(parameters_.n_ensembles),
 
 1078       nevents_(config.take({
"General", 
"Nevents"}, 0)),
 
 1079       end_time_(config.take({
"General", 
"End_Time"})),
 
 1080       delta_time_startup_(parameters_.labclock->timestep_duration()),
 
 1082           config.take({
"Collision_Term", 
"Force_Decays_At_End"}, 
true)),
 
 1083       use_grid_(config.take({
"General", 
"Use_Grid"}, 
true)),
 
 1086           config.take({
"General", 
"Expansion_Rate"}, 0.1)),
 
 1088           config.take({
"Collision_Term", 
"Dileptons", 
"Decays"}, 
false)),
 
 1089       photons_switch_(config.take(
 
 1090           {
"Collision_Term", 
"Photons", 
"2to2_Scatterings"}, 
false)),
 
 1091       bremsstrahlung_switch_(
 
 1092           config.take({
"Collision_Term", 
"Photons", 
"Bremsstrahlung"}, 
false)),
 
 1093       IC_output_switch_(config.has_value({
"Output", 
"Initial_Conditions"})),
 
 1098   if (config.has_value({
"General", 
"Minimum_Nonempty_Ensembles"})) {
 
 1099     if (config.has_value({
"General", 
"Nevents"})) {
 
 1100       throw std::invalid_argument(
 
 1101           "Please specify either Nevents or Minimum_Nonempty_Ensembles.");
 
 1104     minimum_nonempty_ensembles_ =
 
 1105         config.take({
"General", 
"Minimum_Nonempty_Ensembles", 
"Number"});
 
 1106     int max_ensembles = config.take(
 
 1107         {
"General", 
"Minimum_Nonempty_Ensembles", 
"Maximum_Ensembles_Run"});
 
 1109         std::ceil(
static_cast<double>(max_ensembles) / parameters_.n_ensembles);
 
 1117     throw std::invalid_argument(
 
 1118         "Covariant Gaussian derivatives only make sense for Covariant Gaussian " 
 1126       parameters_.discrete_weight < (1. / 7.)) {
 
 1127     throw std::invalid_argument(
 
 1128         "The central weight for discrete smearing should be >= 1./7.");
 
 1133     throw std::invalid_argument(
 
 1134         "The stochastic criterion can only be employed for fixed time step " 
 1135         "mode and with a grid!");
 
 1139                          " testparticles per particle.");
 
 1141                          " parallel ensembles.");
 
 1144   if (dileptons_switch_) {
 
 1145     dilepton_finder_ = make_unique<DecayActionsFinderDilepton>();
 
 1147   if (photons_switch_ || bremsstrahlung_switch_) {
 
 1148     n_fractional_photons_ =
 
 1149         config.take({
"Collision_Term", 
"Photons", 
"Fractional_Photons"}, 100);
 
 1151   if (parameters_.two_to_one) {
 
 1152     if (parameters_.res_lifetime_factor < 0.) {
 
 1153       throw std::invalid_argument(
 
 1154           "Resonance lifetime modifier cannot be negative!");
 
 1158           "Resonance lifetime set to zero. Make sure resonances cannot " 
 1160           "inelastically (e.g. resonance chains), else SMASH is known to " 
 1163     action_finders_.emplace_back(make_unique<DecayActionsFinder>(
 
 1164         parameters_.res_lifetime_factor, parameters_.do_weak_decays));
 
 1166   bool no_coll = config.take({
"Collision_Term", 
"No_Collisions"}, 
false);
 
 1167   if ((parameters_.two_to_one || parameters_.included_2to2.any() ||
 
 1168        parameters_.included_multi.any() || parameters_.strings_switch) &&
 
 1170     auto scat_finder = make_unique<ScatterActionsFinder>(config, parameters_);
 
 1171     max_transverse_distance_sqr_ =
 
 1172         scat_finder->max_transverse_distance_sqr(parameters_.testparticles);
 
 1173     process_string_ptr_ = scat_finder->get_process_string_ptr();
 
 1174     action_finders_.emplace_back(std::move(scat_finder));
 
 1176     max_transverse_distance_sqr_ =
 
 1177         parameters_.maximum_cross_section / M_PI * 
fm2_mb;
 
 1178     process_string_ptr_ = NULL;
 
 1180   if (modus_.is_box()) {
 
 1181     action_finders_.emplace_back(
 
 1182         make_unique<WallCrossActionsFinder>(parameters_.box_length));
 
 1184   if (IC_output_switch_) {
 
 1185     if (!modus_.is_collider()) {
 
 1186       throw std::runtime_error(
 
 1187           "Initial conditions can only be extracted in collider modus.");
 
 1190     if (config.has_value({
"Output", 
"Initial_Conditions", 
"Proper_Time"})) {
 
 1193           config.take({
"Output", 
"Initial_Conditions", 
"Proper_Time"});
 
 1196       double default_proper_time = modus_.nuclei_passing_time();
 
 1197       double lower_bound =
 
 1198           config.take({
"Output", 
"Initial_Conditions", 
"Lower_Bound"}, 0.5);
 
 1199       if (default_proper_time >= lower_bound) {
 
 1200         proper_time = default_proper_time;
 
 1203             << 
"Nuclei passing time is too short, hypersurface proper time set " 
 1205             << lower_bound << 
" fm.";
 
 1206         proper_time = lower_bound;
 
 1210     double rapidity_cut = 0.0;
 
 1211     if (config.has_value({
"Output", 
"Initial_Conditions", 
"Rapidity_Cut"})) {
 
 1213           config.take({
"Output", 
"Initial_Conditions", 
"Rapidity_Cut"});
 
 1214       if (rapidity_cut <= 0.0) {
 
 1216             << 
"Rapidity cut for initial conditions configured as abs(y) < " 
 1217             << rapidity_cut << 
" is unreasonable. \nPlease choose a positive, " 
 1218             << 
"non-zero value or employ SMASH without rapidity cut.";
 
 1219         throw std::runtime_error(
 
 1220             "Kinematic cut for initial conditions malconfigured.");
 
 1224     if (modus_.calculation_frame_is_fixed_target() && rapidity_cut != 0.0) {
 
 1225       throw std::runtime_error(
 
 1226           "Rapidity cut for initial conditions output is not implemented " 
 1227           "in the fixed target calculation frame. \nPlease use " 
 1228           "\"center of velocity\" or \"center of mass\" as a " 
 1229           "\"Calculation_Frame\" instead.");
 
 1232     double transverse_momentum_cut = 0.0;
 
 1233     if (config.has_value({
"Output", 
"Initial_Conditions", 
"pT_Cut"})) {
 
 1234       transverse_momentum_cut =
 
 1235           config.take({
"Output", 
"Initial_Conditions", 
"pT_Cut"});
 
 1236       if (transverse_momentum_cut <= 0.0) {
 
 1238             << 
"transverse momentum cut for initial conditions configured as " 
 1240             << rapidity_cut << 
" is unreasonable. \nPlease choose a positive, " 
 1241             << 
"non-zero value or employ SMASH without pT cut.";
 
 1242         throw std::runtime_error(
 
 1243             "Kinematic cut for initial conditions malconfigured.");
 
 1247     if (rapidity_cut > 0.0 || transverse_momentum_cut > 0.0) {
 
 1248       kinematic_cuts_for_IC_output_ = 
true;
 
 1251     if (rapidity_cut > 0.0 && transverse_momentum_cut > 0.0) {
 
 1253           << 
"Extracting initial conditions in kinematic range: " 
 1254           << -rapidity_cut << 
" <= y <= " << rapidity_cut
 
 1255           << 
"; pT <= " << transverse_momentum_cut << 
" GeV.";
 
 1256     } 
else if (rapidity_cut > 0.0) {
 
 1258           << 
"Extracting initial conditions in kinematic range: " 
 1259           << -rapidity_cut << 
" <= y <= " << rapidity_cut << 
".";
 
 1260     } 
else if (transverse_momentum_cut > 0.0) {
 
 1262           << 
"Extracting initial conditions in kinematic range: pT <= " 
 1263           << transverse_momentum_cut << 
" GeV.";
 
 1266           << 
"Extracting initial conditions without kinematic cuts.";
 
 1269     action_finders_.emplace_back(make_unique<HyperSurfaceCrossActionsFinder>(
 
 1270         proper_time, rapidity_cut, transverse_momentum_cut));
 
 1273   if (config.has_value({
"Collision_Term", 
"Pauli_Blocking"})) {
 
 1275     pauli_blocker_ = make_unique<PauliBlocker>(
 
 1276         config[
"Collision_Term"][
"Pauli_Blocking"], parameters_);
 
 1280       config.take({
"Collision_Term", 
"Power_Particle_Formation"},
 
 1281                   modus_.sqrt_s_NN() >= 200. ? -1. : 1.);
 
 1317                           " create OutputInterface objects");
 
 1319   auto output_conf = config[
"Output"];
 
 1549       << 
"Density type printed to headers: " << dens_type_;
 
 1551   const OutputParameters output_parameters(std::move(output_conf));
 
 1553   std::vector<std::string> output_contents = output_conf.list_upmost_nodes();
 
 1554   for (
const auto &content : output_contents) {
 
 1555     auto this_output_conf = output_conf[content.c_str()];
 
 1556     const std::vector<std::string> formats = this_output_conf.take({
"Format"});
 
 1557     if (output_path == 
"") {
 
 1560     for (
const auto &
format : formats) {
 
 1561       create_output(
format, content, output_path, output_parameters);
 
 1572   if (config.has_value({
"Potentials"})) {
 
 1575       throw std::invalid_argument(
"Can't use potentials without time steps!");
 
 1579           << 
"Potentials don't work with frozen Fermi momenta! " 
 1580              "Use normal Fermi motion instead.";
 
 1581       throw std::invalid_argument(
 
 1582           "Can't use potentials " 
 1583           "with frozen Fermi momenta!");
 
 1586                              << parameters_.labclock->timestep_duration();
 
 1588     potentials_ = make_unique<Potentials>(config[
"Potentials"], parameters_);
 
 1591     if (potentials_->use_skyrme() && potentials_->use_vdf()) {
 
 1592       throw std::runtime_error(
 
 1593           "Can't use Skyrme and VDF potentials at the same time!");
 
 1595     if (potentials_->use_symmetry() && potentials_->use_vdf()) {
 
 1596       throw std::runtime_error(
 
 1597           "Can't use symmetry and VDF potentials at the same time!");
 
 1599     if (potentials_->use_skyrme()) {
 
 1602           << 
"\t\tSkyrme_A [MeV] = " << potentials_->skyrme_a() << 
"\n";
 
 1604           << 
"\t\tSkyrme_B [MeV] = " << potentials_->skyrme_b() << 
"\n";
 
 1606           << 
"\t\t    Skyrme_tau = " << potentials_->skyrme_tau() << 
"\n";
 
 1608     if (potentials_->use_symmetry()) {
 
 1610           << 
"Symmetry potential is:" 
 1611           << 
"\n   S_pot [MeV] = " << potentials_->symmetry_S_pot() << 
"\n";
 
 1613     if (potentials_->use_vdf()) {
 
 1616                                << potentials_->saturation_density() << 
"\n";
 
 1617       for (
int i = 0; i < potentials_->number_of_terms(); i++) {
 
 1619             << 
"\t\tCoefficient_" << i + 1 << 
" = " 
 1620             << 1000.0 * (potentials_->coeffs())[i] << 
" [MeV]   \t Power_" 
 1621             << i + 1 << 
" = " << (potentials_->powers())[i] << 
"\n";
 
 1627       throw std::invalid_argument(
 
 1628           "Derivatives are necessary for running with potentials.\n" 
 1629           "Derivatives_Mode: \"Off\" only makes sense for " 
 1630           "Field_Derivatives_Mode: \"Direct\"!\nUse \"Covariant Gaussian\" or " 
 1631           "\"Finite difference\".");
 
 1639     switch (parameters_.derivatives_mode) {
 
 1650     switch (parameters_.rho_derivatives_mode) {
 
 1659     if (potentials_->use_vdf()) {
 
 1660       switch (parameters_.field_derivatives_mode) {
 
 1673     if (potentials_->use_vdf() && (parameters_.rho_derivatives_mode ==
 
 1675                                    parameters_.field_derivatives_mode ==
 
 1677       throw std::runtime_error(
 
 1678           "Can't use VDF potentials without rest frame density derivatives or " 
 1679           "direct field derivatives!");
 
 1684       throw std::runtime_error(
 
 1685           "Can't use potentials without gradients of baryon current (Skyrme, " 
 1687           " or direct field derivatives (VDF)!");
 
 1690     if (!(potentials_->use_vdf()) &&
 
 1692       throw std::invalid_argument(
 
 1693           "Field_Derivatives_Mode: \"Direct\" only makes sense for the VDF " 
 1694           "potentials!\nUse Field_Derivatives_Mode: \"Chain Rule\" or comment " 
 1695           "this option out (Chain Rule is default)");
 
 1700   switch (parameters_.smearing_mode) {
 
 1706                                << parameters_.discrete_weight;
 
 1710                                << parameters_.triangular_range;
 
 1794   if (config.has_value({
"Lattice"})) {
 
 1795     std::array<double, 3> l_default{20., 20., 20.};
 
 1796     std::array<int, 3> n_default{10, 10, 10};
 
 1797     std::array<double, 3> origin_default{-20., -20., -20.};
 
 1798     bool periodic_default = 
false;
 
 1799     if (modus_.is_collider()) {
 
 1801       const double gam = modus_.sqrt_s_NN() / (2.0 * 
nucleon_mass);
 
 1802       const double max_z = 5.0 / gam + end_time_;
 
 1803       const double estimated_max_transverse_velocity = 0.7;
 
 1804       const double max_xy = 5.0 + estimated_max_transverse_velocity * end_time_;
 
 1805       origin_default = {-max_xy, -max_xy, -max_z};
 
 1806       l_default = {2 * max_xy, 2 * max_xy, 2 * max_z};
 
 1809       const int n_xy = std::ceil(2 * max_xy / 0.8);
 
 1810       int nz = std::ceil(2 * max_z / 0.8);
 
 1815         nz = 
static_cast<int>(std::ceil(2 * max_z / 0.8 * gam));
 
 1817       n_default = {n_xy, n_xy, nz};
 
 1818     } 
else if (modus_.is_box()) {
 
 1819       periodic_default = 
true;
 
 1820       origin_default = {0., 0., 0.};
 
 1821       const double bl = modus_.length();
 
 1822       l_default = {bl, bl, bl};
 
 1823       const int n_xyz = std::ceil(bl / 0.5);
 
 1824       n_default = {n_xyz, n_xyz, n_xyz};
 
 1825     } 
else if (modus_.is_sphere()) {
 
 1828       const double max_d = modus_.radius() + end_time_;
 
 1829       origin_default = {-max_d, -max_d, -max_d};
 
 1830       l_default = {2 * max_d, 2 * max_d, 2 * max_d};
 
 1832       const int n_xyz = std::ceil(2 * max_d / 0.8);
 
 1833       n_default = {n_xyz, n_xyz, n_xyz};
 
 1836     const std::array<double, 3> l =
 
 1837         config.take({
"Lattice", 
"Sizes"}, l_default);
 
 1838     const std::array<int, 3> 
n =
 
 1839         config.take({
"Lattice", 
"Cell_Number"}, n_default);
 
 1840     const std::array<double, 3> origin =
 
 1841         config.take({
"Lattice", 
"Origin"}, origin_default);
 
 1842     const bool periodic =
 
 1843         config.take({
"Lattice", 
"Periodic"}, periodic_default);
 
 1846         << 
"Lattice is ON. Origin = (" << origin[0] << 
"," << origin[1] << 
"," 
 1847         << origin[2] << 
"), sizes = (" << l[0] << 
"," << l[1] << 
"," << l[2]
 
 1848         << 
"), number of cells = (" << 
n[0] << 
"," << 
n[1] << 
"," << 
n[2]
 
 1851     if (printout_lattice_td_ || printout_full_lattice_any_td_) {
 
 1852       dens_type_lattice_printout_ = output_parameters.td_dens_type;
 
 1853       printout_tmn_ = output_parameters.td_tmn;
 
 1854       printout_tmn_landau_ = output_parameters.td_tmn_landau;
 
 1855       printout_v_landau_ = output_parameters.td_v_landau;
 
 1856       printout_j_QBS_ = output_parameters.td_jQBS;
 
 1858     if (printout_tmn_ || printout_tmn_landau_ || printout_v_landau_) {
 
 1859       Tmn_ = make_unique<RectangularLattice<EnergyMomentumTensor>>(
 
 1862     if (printout_j_QBS_) {
 
 1863       j_QBS_lat_ = make_unique<DensityLattice>(l, 
n, origin, periodic,
 
 1871       old_jmu_auxiliary_ = make_unique<RectangularLattice<FourVector>>(
 
 1873       new_jmu_auxiliary_ = make_unique<RectangularLattice<FourVector>>(
 
 1875       four_gradient_auxiliary_ =
 
 1876           make_unique<RectangularLattice<std::array<FourVector, 4>>>(
 
 1879       if (potentials_->use_skyrme()) {
 
 1880         jmu_B_lat_ = make_unique<DensityLattice>(l, 
n, origin, periodic,
 
 1882         UB_lat_ = make_unique<RectangularLattice<FourVector>>(
 
 1885             RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
 
 1888       if (potentials_->use_symmetry()) {
 
 1889         jmu_I3_lat_ = make_unique<DensityLattice>(l, 
n, origin, periodic,
 
 1891         UI3_lat_ = make_unique<RectangularLattice<FourVector>>(
 
 1894             RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
 
 1897       if (potentials_->use_coulomb()) {
 
 1898         jmu_el_lat_ = make_unique<DensityLattice>(l, 
n, origin, periodic,
 
 1901             RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
 
 1904       if (potentials_->use_vdf()) {
 
 1905         jmu_B_lat_ = make_unique<DensityLattice>(l, 
n, origin, periodic,
 
 1907         UB_lat_ = make_unique<RectangularLattice<FourVector>>(
 
 1910             RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
 
 1915         old_fields_auxiliary_ = make_unique<RectangularLattice<FourVector>>(
 
 1917         new_fields_auxiliary_ = make_unique<RectangularLattice<FourVector>>(
 
 1919         fields_four_gradient_auxiliary_ =
 
 1920             make_unique<RectangularLattice<std::array<FourVector, 4>>>(
 
 1924         fields_lat_ = make_unique<FieldsLattice>(l, 
n, origin, periodic,
 
 1929         jmu_B_lat_ = make_unique<DensityLattice>(l, 
n, origin, periodic,
 
 1933         jmu_I3_lat_ = make_unique<DensityLattice>(l, 
n, origin, periodic,
 
 1940       jmu_custom_lat_ = make_unique<DensityLattice>(l, 
n, origin, periodic,
 
 1943   } 
else if (printout_lattice_td_ || printout_full_lattice_any_td_) {
 
 1945         "If you want Therm. VTK or Lattice output, configure a lattice for " 
 1947   } 
else if (potentials_ && potentials_->use_coulomb()) {
 
 1949         "Coulomb potential requires a lattice. Please add one to the " 
 1954   if ((potentials_ != 
nullptr) && (jmu_B_lat_ == 
nullptr)) {
 
 1955     logg[
LExperiment].warn() << 
"Lattice is NOT used. Mean-field energy is " 
 1956                              << 
"not going to be calculated.";
 
 1960   if (parameters_.potential_affect_threshold) {
 
 1968       (jmu_B_lat_ == 
nullptr)) {
 
 1969     throw std::runtime_error(
 
 1970         "Lattice is necessary to calculate finite difference gradients.");
 
 1974   if (config.has_value({
"Forced_Thermalization"})) {
 
 1975     Configuration &&th_conf = config[
"Forced_Thermalization"];
 
 1976     thermalizer_ = modus_.create_grandcan_thermalizer(th_conf);
 
 1981   seed_ = config.take({
"General", 
"Randomseed"});
 
 2012                                 uint64_t scatterings_this_interval,
 
 2015                                 double E_mean_field,
 
 2016                                 double E_mean_field_initial);
 
 2053                           double E_mean_field, 
double modus_impact_parameter,
 
 2055                           bool projectile_target_interact,
 
 2056                           bool kinematic_cut_for_SMASH_IC);
 
 2058 template <
typename Modus>
 
 2068   while (r == INT64_MIN) {
 
 2071   seed_ = std::abs(r);
 
 2076   if (process_string_ptr_ != NULL) {
 
 2077     process_string_ptr_->init_pythia_hadron_rndm();
 
 2080   for (
Particles &particles : ensembles_) {
 
 2085   double start_time = -1.0;
 
 2089   if (modus_.is_collider()) {
 
 2090     modus_.sample_impact();
 
 2091     logg[
LExperiment].info(
"Impact parameter = ", modus_.impact_parameter(),
 
 2094   for (
Particles &particles : ensembles_) {
 
 2095     start_time = modus_.initial_conditions(&particles, parameters_);
 
 2100   for (
Particles &particles : ensembles_) {
 
 2101     modus_.impose_boundary_conditions(&particles, outputs_);
 
 2104   double timestep = delta_time_startup_;
 
 2106   switch (time_step_mode_) {
 
 2110       timestep = end_time_ - start_time;
 
 2112       const double max_dt = modus_.max_timestep(max_transverse_distance_sqr_);
 
 2113       if (max_dt > 0. && max_dt < timestep) {
 
 2118   std::unique_ptr<UniformClock> clock_for_this_event;
 
 2119   if (modus_.is_list() && (timestep < 0.0)) {
 
 2120     throw std::runtime_error(
 
 2121         "Timestep for the given event is negative. \n" 
 2122         "This might happen if the formation times of the input particles are " 
 2123         "larger than the specified end time of the simulation.");
 
 2125   clock_for_this_event = make_unique<UniformClock>(start_time, timestep);
 
 2126   parameters_.labclock = std::move(clock_for_this_event);
 
 2129   parameters_.outputclock->reset(start_time, 
true);
 
 2131   parameters_.outputclock->remove_times_in_past(start_time);
 
 2134       "Lab clock: t_start = ", parameters_.labclock->current_time(),
 
 2135       ", dt = ", parameters_.labclock->timestep_duration());
 
 2140   wall_actions_total_ = 0;
 
 2141   previous_wall_actions_total_ = 0;
 
 2142   interactions_total_ = 0;
 
 2143   previous_interactions_total_ = 0;
 
 2144   discarded_interactions_total_ = 0;
 
 2145   total_pauli_blocked_ = 0;
 
 2146   projectile_target_interact_.assign(parameters_.n_ensembles, 
false);
 
 2147   total_hypersurface_crossing_actions_ = 0;
 
 2148   total_energy_removed_ = 0.0;
 
 2151   logg[
LExperiment].info() << 
"Time[fm]   Ekin[GeV]   E_MF[GeV]  ETotal[GeV]  " 
 2152                            << 
"ETot/N[GeV]  D(ETot/N)[GeV] Scatt&Decays  " 
 2153                            << 
"Particles     Comp.Time";
 
 2155   double E_mean_field = 0.0;
 
 2160     if ((jmu_B_lat_ != 
nullptr)) {
 
 2162                      new_jmu_auxiliary_.get(), four_gradient_auxiliary_.get(),
 
 2164                      density_param_, ensembles_,
 
 2165                      parameters_.labclock->timestep_duration(), 
true);
 
 2169       for (
auto &node : *jmu_B_lat_) {
 
 2170         node.overwrite_drho_dt_to_zero();
 
 2171         node.overwrite_djmu_dt_to_zero();
 
 2174                                                  EM_lat_.get(), parameters_);
 
 2177   initial_mean_field_energy_ = E_mean_field;
 
 2179       ensembles_, 0u, conserved_initial_, time_start_,
 
 2180       parameters_.labclock->current_time(), E_mean_field,
 
 2181       initial_mean_field_energy_);
 
 2184   for (
const auto &output : outputs_) {
 
 2185     for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
 
 2187           ensembles_, E_mean_field, modus_.impact_parameter(), parameters_,
 
 2188           projectile_target_interact_[i_ens], kinematic_cuts_for_IC_output_);
 
 2189       output->at_eventstart(ensembles_[i_ens],
 
 2191                             event_ * parameters_.n_ensembles + i_ens,
 
 2195     output->at_eventstart(ensembles_, event_);
 
 2197     if (printout_full_lattice_any_td_) {
 
 2198       switch (dens_type_lattice_printout_) {
 
 2213       if (printout_tmn_) {
 
 2215                               dens_type_lattice_printout_, *Tmn_);
 
 2217       if (printout_tmn_landau_) {
 
 2219                               dens_type_lattice_printout_, *Tmn_);
 
 2221       if (printout_v_landau_) {
 
 2223                               dens_type_lattice_printout_, *Tmn_);
 
 2225       if (printout_j_QBS_) {
 
 2227                               dens_type_lattice_printout_, *j_QBS_lat_);
 
 2239       const double m = particle.effective_mass();
 
 2240       double v_beam = 0.0;
 
 2242         v_beam = modus_.velocity_projectile();
 
 2244         v_beam = modus_.velocity_target();
 
 2246       const double gamma = 1.0 / std::sqrt(1.0 - v_beam * v_beam);
 
 2247       beam_momentum_.emplace_back(
 
 2248           FourVector(gamma * m, 0.0, 0.0, gamma * v_beam * m));
 
 2253 template <
typename Modus>
 
 2255                                        bool include_pauli_blocking) {
 
 2256   Particles &particles = ensembles_[i_ensemble];
 
 2259     discarded_interactions_total_++;
 
 2261                             " (discarded: invalid)");
 
 2266   if (include_pauli_blocking && pauli_blocker_ &&
 
 2268     total_pauli_blocked_++;
 
 2274   if (modus_.is_collider()) {
 
 2275     int count_target = 0, count_projectile = 0;
 
 2283     if (count_target > 0 && count_projectile > 0) {
 
 2284       projectile_target_interact_[i_ensemble] = 
true;
 
 2290   const auto id_process = 
static_cast<uint32_t
>(interactions_total_ + 1);
 
 2291   action.
perform(&particles, id_process);
 
 2292   interactions_total_++;
 
 2294     wall_actions_total_++;
 
 2297     total_hypersurface_crossing_actions_++;
 
 2304     constexpr 
bool compute_grad = 
false;
 
 2305     const bool smearing = 
true;
 
 2308     rho = std::get<0>(
current_eckart(r_interaction.threevec(), particles,
 
 2309                                      density_param_, dens_type_, compute_grad,
 
 2327   for (
const auto &output : outputs_) {
 
 2328     if (!output->is_dilepton_output() && !output->is_photon_output()) {
 
 2329       if (output->is_IC_output() &&
 
 2331         output->at_interaction(action, rho);
 
 2332       } 
else if (!output->is_IC_output()) {
 
 2333         output->at_interaction(action, rho);
 
 2343   if (photons_switch_ &&
 
 2349     constexpr 
double action_time = 0.;
 
 2351                                    n_fractional_photons_,
 
 2367     photon_act.add_single_process();
 
 2369     photon_act.perform_photons(outputs_);
 
 2372   if (bremsstrahlung_switch_ &&
 
 2377     constexpr 
double action_time = 0.;
 
 2380                                    n_fractional_photons_,
 
 2397     brems_act.add_single_process();
 
 2399     brems_act.perform_bremsstrahlung(outputs_);
 
 2406 template <
typename Modus>
 
 2408   while (parameters_.labclock->current_time() < t_end) {
 
 2409     const double t = parameters_.labclock->current_time();
 
 2411         std::min(parameters_.labclock->timestep_duration(), t_end - t);
 
 2412     logg[
LExperiment].debug(
"Timestepless propagation for next ", dt, 
" fm/c.");
 
 2416         thermalizer_->is_time_to_thermalize(parameters_.labclock)) {
 
 2417       const bool ignore_cells_under_treshold = 
true;
 
 2420       thermalizer_->update_thermalizer_lattice(ensembles_, density_param_,
 
 2421                                                ignore_cells_under_treshold);
 
 2422       const double current_t = parameters_.labclock->current_time();
 
 2423       for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
 
 2424         thermalizer_->thermalize(ensembles_[i_ens], current_t,
 
 2425                                  parameters_.testparticles);
 
 2428           perform_action(th_act, i_ens);
 
 2433     std::vector<Actions> actions(parameters_.n_ensembles);
 
 2434     for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
 
 2435       actions[i_ens].clear();
 
 2436       if (ensembles_[i_ens].size() > 0 && action_finders_.size() > 0) {
 
 2438         const double min_cell_length = compute_min_cell_length(dt);
 
 2443         const bool include_unformed_particles = IC_output_switch_;
 
 2445             use_grid_ ? modus_.create_grid(ensembles_[i_ens], min_cell_length,
 
 2446                                            dt, parameters_.coll_crit,
 
 2447                                            include_unformed_particles)
 
 2448                       : modus_.create_grid(ensembles_[i_ens], min_cell_length,
 
 2449                                            dt, parameters_.coll_crit,
 
 2450                                            include_unformed_particles,
 
 2453         const double gcell_vol = grid.cell_volume();
 
 2456             [&](
const ParticleList &search_list) {
 
 2457               for (
const auto &finder : action_finders_) {
 
 2458                 actions[i_ens].insert(finder->find_actions_in_cell(
 
 2459                     search_list, dt, gcell_vol, beam_momentum_));
 
 2462             [&](
const ParticleList &search_list,
 
 2463                 const ParticleList &neighbors_list) {
 
 2464               for (
const auto &finder : action_finders_) {
 
 2465                 actions[i_ens].insert(finder->find_actions_with_neighbors(
 
 2466                     search_list, neighbors_list, dt, beam_momentum_));
 
 2475     const double end_timestep_time =
 
 2476         std::min(parameters_.labclock->next_time(), t_end);
 
 2477     while (next_output_time() <= end_timestep_time) {
 
 2478       for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
 
 2479         run_time_evolution_timestepless(actions[i_ens], i_ens,
 
 2480                                         next_output_time(), t_end);
 
 2482       ++(*parameters_.outputclock);
 
 2485       if (parameters_.outputclock->current_time() < t_end) {
 
 2486         intermediate_output();
 
 2489     for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
 
 2490       run_time_evolution_timestepless(actions[i_ens], i_ens, end_timestep_time,
 
 2497       update_potentials();
 
 2498       update_momenta(ensembles_, parameters_.labclock->timestep_duration(),
 
 2499                      *potentials_, FB_lat_.get(), FI3_lat_.get(),
 
 2506       for (
Particles &particles : ensembles_) {
 
 2511     ++(*parameters_.labclock);
 
 2519     if (!potentials_ && !parameters_.strings_switch &&
 
 2521       std::string err_msg = conserved_initial_.report_deviations(ensembles_);
 
 2522       if (!err_msg.empty()) {
 
 2524         throw std::runtime_error(
"Violation of conserved quantities!");
 
 2529   if (pauli_blocker_) {
 
 2531         "Interactions: Pauli-blocked/performed = ", total_pauli_blocked_, 
"/",
 
 2532         interactions_total_ - wall_actions_total_);
 
 2536 template <
typename Modus>
 
 2541   if (dilepton_finder_ != 
nullptr) {
 
 2542     for (
const auto &output : outputs_) {
 
 2543       dilepton_finder_->shine(particles, output.get(), dt);
 
 2556   constexpr uint64_t max_uint32 = std::numeric_limits<uint32_t>::max();
 
 2557   if (interactions_total >= max_uint32) {
 
 2558     throw std::runtime_error(
"Integer overflow in total interaction number!");
 
 2562 template <
typename Modus>
 
 2564     Actions &actions, 
int i_ensemble, 
const double end_time_propagation,
 
 2565     const double end_time_run) {
 
 2566   Particles &particles = ensembles_[i_ensemble];
 
 2568       "Timestepless propagation: ", 
"Actions size = ", actions.
size(),
 
 2569       ", end time = ", end_time_propagation);
 
 2577     ActionPtr act = actions.
pop();
 
 2578     if (!act->is_valid(particles)) {
 
 2579       discarded_interactions_total_++;
 
 2581                               " (discarded: invalid)");
 
 2585                             ", action time = ", act->time_of_execution());
 
 2588     propagate_and_shine(act->time_of_execution(), particles);
 
 2595     act->update_incoming(particles);
 
 2596     const bool performed = perform_action(*act, i_ensemble);
 
 2606     const double end_time_timestep =
 
 2607         std::min(parameters_.labclock->next_time(), end_time_run);
 
 2608     assert(!(end_time_propagation > end_time_timestep));
 
 2610     const double time_left = end_time_timestep - act->time_of_execution();
 
 2611     const ParticleList &outgoing_particles = act->outgoing_particles();
 
 2613     const double gcell_vol = 0.0;
 
 2614     for (
const auto &finder : action_finders_) {
 
 2616       actions.
insert(finder->find_actions_in_cell(outgoing_particles, time_left,
 
 2617                                                   gcell_vol, beam_momentum_));
 
 2619       actions.
insert(finder->find_actions_with_surrounding_particles(
 
 2620           outgoing_particles, particles, time_left, beam_momentum_));
 
 2626   propagate_and_shine(end_time_propagation, particles);
 
 2629 template <
typename Modus>
 
 2631   const uint64_t wall_actions_this_interval =
 
 2632       wall_actions_total_ - previous_wall_actions_total_;
 
 2633   previous_wall_actions_total_ = wall_actions_total_;
 
 2634   const uint64_t interactions_this_interval = interactions_total_ -
 
 2635                                               previous_interactions_total_ -
 
 2636                                               wall_actions_this_interval;
 
 2637   previous_interactions_total_ = interactions_total_;
 
 2638   double E_mean_field = 0.0;
 
 2641   double computational_frame_time = 0.0;
 
 2644     if ((jmu_B_lat_ != 
nullptr)) {
 
 2646                                                  EM_lat_.get(), parameters_);
 
 2653       if (modus_.is_box()) {
 
 2654         double tmp = (E_mean_field - initial_mean_field_energy_) /
 
 2655                      (E_mean_field + initial_mean_field_energy_);
 
 2661         if (std::abs(tmp) > 0.01) {
 
 2663               << 
"\n\n\n\t The mean field at t = " 
 2664               << parameters_.outputclock->current_time()
 
 2665               << 
" [fm/c] differs from the mean field at t = 0:" 
 2666               << 
"\n\t\t                 initial_mean_field_energy_ = " 
 2667               << initial_mean_field_energy_ << 
" [GeV]" 
 2668               << 
"\n\t\t abs[(E_MF - E_MF(t=0))/(E_MF + E_MF(t=0))] = " 
 2670               << 
"\n\t\t                             E_MF/E_MF(t=0) = " 
 2671               << E_mean_field / initial_mean_field_energy_ << 
"\n\n";
 
 2678       ensembles_, interactions_this_interval, conserved_initial_, time_start_,
 
 2679       parameters_.outputclock->current_time(), E_mean_field,
 
 2680       initial_mean_field_energy_);
 
 2684   if (!(modus_.is_box() && parameters_.outputclock->current_time() <
 
 2685                                modus_.equilibration_time())) {
 
 2686     for (
const auto &output : outputs_) {
 
 2687       if (output->is_dilepton_output() || output->is_photon_output() ||
 
 2688           output->is_IC_output()) {
 
 2691       for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
 
 2693             ensembles_, E_mean_field, modus_.impact_parameter(), parameters_,
 
 2694             projectile_target_interact_[i_ens], kinematic_cuts_for_IC_output_);
 
 2696         output->at_intermediate_time(ensembles_[i_ens], parameters_.outputclock,
 
 2697                                      density_param_, event_info);
 
 2698         computational_frame_time = event_info.current_time;
 
 2701       output->at_intermediate_time(ensembles_, parameters_.outputclock,
 
 2705       switch (dens_type_lattice_printout_) {
 
 2708                          density_param_, ensembles_, 
false);
 
 2711           output->thermodynamics_lattice_output(*jmu_B_lat_,
 
 2712                                                 computational_frame_time);
 
 2721           output->thermodynamics_lattice_output(*jmu_I3_lat_,
 
 2722                                                 computational_frame_time);
 
 2728                          dens_type_lattice_printout_, density_param_,
 
 2731                                         dens_type_lattice_printout_,
 
 2733           output->thermodynamics_lattice_output(*jmu_custom_lat_,
 
 2734                                                 computational_frame_time);
 
 2736       if (printout_tmn_ || printout_tmn_landau_ || printout_v_landau_) {
 
 2738                        density_param_, ensembles_, 
false);
 
 2739         if (printout_tmn_) {
 
 2741                                         dens_type_lattice_printout_, *Tmn_);
 
 2742           output->thermodynamics_lattice_output(
 
 2745         if (printout_tmn_landau_) {
 
 2747                                         dens_type_lattice_printout_, *Tmn_);
 
 2748           output->thermodynamics_lattice_output(
 
 2750               computational_frame_time);
 
 2752         if (printout_v_landau_) {
 
 2754                                         dens_type_lattice_printout_, *Tmn_);
 
 2755           output->thermodynamics_lattice_output(
 
 2757               computational_frame_time);
 
 2761         output->fields_output(
"Efield", 
"Bfield", *EM_lat_);
 
 2763       if (printout_j_QBS_) {
 
 2764         output->thermodynamics_lattice_output(
 
 2765             *j_QBS_lat_, computational_frame_time, ensembles_, density_param_);
 
 2769         output->thermodynamics_output(*thermalizer_);
 
 2775 template <
typename Modus>
 
 2778     if (potentials_->use_symmetry() && jmu_I3_lat_ != 
nullptr) {
 
 2780                      new_jmu_auxiliary_.get(), four_gradient_auxiliary_.get(),
 
 2782                      density_param_, ensembles_,
 
 2783                      parameters_.labclock->timestep_duration(), 
true);
 
 2785     if ((potentials_->use_skyrme() || potentials_->use_symmetry()) &&
 
 2786         jmu_B_lat_ != 
nullptr) {
 
 2788                      new_jmu_auxiliary_.get(), four_gradient_auxiliary_.get(),
 
 2790                      density_param_, ensembles_,
 
 2791                      parameters_.labclock->timestep_duration(), 
true);
 
 2792       const size_t UBlattice_size = UB_lat_->size();
 
 2793       for (
size_t i = 0; i < UBlattice_size; i++) {
 
 2794         auto jB = (*jmu_B_lat_)[i];
 
 2798         double baryon_density = jB.rho();
 
 2802         if (potentials_->use_skyrme()) {
 
 2804               flow_four_velocity_B * potentials_->skyrme_pot(baryon_density);
 
 2806               potentials_->skyrme_force(baryon_density, baryon_grad_j0,
 
 2807                                         baryon_dvecj_dt, baryon_curl_vecj);
 
 2809         if (potentials_->use_symmetry() && jmu_I3_lat_ != 
nullptr) {
 
 2810           auto jI3 = (*jmu_I3_lat_)[i];
 
 2813                   ? jI3.jmu_net() / jI3.rho()
 
 2815           (*UI3_lat_)[i] = flow_four_velocity_I3 *
 
 2816                            potentials_->symmetry_pot(jI3.rho(), baryon_density);
 
 2817           (*FI3_lat_)[i] = potentials_->symmetry_force(
 
 2818               jI3.rho(), jI3.grad_j0(), jI3.dvecj_dt(), jI3.curl_vecj(),
 
 2819               baryon_density, baryon_grad_j0, baryon_dvecj_dt,
 
 2824     if (potentials_->use_coulomb()) {
 
 2827       for (
size_t i = 0; i < EM_lat_->size(); i++) {
 
 2829         ThreeVector position = jmu_el_lat_->cell_center(i);
 
 2830         jmu_el_lat_->integrate_volume(electric_field,
 
 2832                                       potentials_->coulomb_r_cut(), position);
 
 2834         jmu_el_lat_->integrate_volume(magnetic_field,
 
 2836                                       potentials_->coulomb_r_cut(), position);
 
 2837         (*EM_lat_)[i] = std::make_pair(electric_field, magnetic_field);
 
 2840     if (potentials_->use_vdf() && jmu_B_lat_ != 
nullptr) {
 
 2842                      new_jmu_auxiliary_.get(), four_gradient_auxiliary_.get(),
 
 2844                      density_param_, ensembles_,
 
 2845                      parameters_.labclock->timestep_duration(), 
true);
 
 2848             fields_lat_.get(), old_fields_auxiliary_.get(),
 
 2849             new_fields_auxiliary_.get(), fields_four_gradient_auxiliary_.get(),
 
 2851             parameters_.labclock->timestep_duration());
 
 2853       const size_t UBlattice_size = UB_lat_->size();
 
 2854       for (
size_t i = 0; i < UBlattice_size; i++) {
 
 2855         auto jB = (*jmu_B_lat_)[i];
 
 2856         (*UB_lat_)[i] = potentials_->vdf_pot(jB.rho(), jB.jmu_net());
 
 2857         switch (parameters_.field_derivatives_mode) {
 
 2859             (*FB_lat_)[i] = potentials_->vdf_force(
 
 2860                 jB.rho(), jB.drho_dxnu().x0(), jB.drho_dxnu().threevec(),
 
 2861                 jB.grad_rho_cross_vecj(), jB.jmu_net().x0(), jB.grad_j0(),
 
 2862                 jB.jmu_net().threevec(), jB.dvecj_dt(), jB.curl_vecj());
 
 2865             auto Amu = (*fields_lat_)[i];
 
 2866             (*FB_lat_)[i] = potentials_->vdf_force(
 
 2867                 Amu.grad_A0(), Amu.dvecA_dt(), Amu.curl_vecA());
 
 2875 template <
typename Modus>
 
 2879   bool actions_performed, decays_found;
 
 2880   uint64_t interactions_old;
 
 2882     decays_found = 
false;
 
 2883     interactions_old = interactions_total_;
 
 2884     for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
 
 2888       if (dilepton_finder_ != 
nullptr) {
 
 2889         for (
const auto &output : outputs_) {
 
 2890           dilepton_finder_->shine_final(ensembles_[i_ens], output.get(), 
true);
 
 2894       for (
const auto &finder : action_finders_) {
 
 2895         auto found_actions = finder->find_final_actions(ensembles_[i_ens]);
 
 2896         if (!found_actions.empty()) {
 
 2897           actions.
insert(std::move(found_actions));
 
 2898           decays_found = 
true;
 
 2903         perform_action(*actions.
pop(), i_ens, 
false);
 
 2906     actions_performed = interactions_total_ > interactions_old;
 
 2908     if (decays_found && !actions_performed) {
 
 2909       throw std::runtime_error(
"Final decays were found but not performed.");
 
 2912   } 
while (actions_performed);
 
 2915   if (dilepton_finder_ != 
nullptr) {
 
 2916     for (
const auto &output : outputs_) {
 
 2917       for (
Particles &particles : ensembles_) {
 
 2918         dilepton_finder_->shine_final(particles, output.get(), 
false);
 
 2924 template <
typename Modus>
 
 2929   double E_mean_field = 0.0;
 
 2930   if (
likely(parameters_.labclock > 0)) {
 
 2931     const uint64_t wall_actions_this_interval =
 
 2932         wall_actions_total_ - previous_wall_actions_total_;
 
 2933     const uint64_t interactions_this_interval = interactions_total_ -
 
 2934                                                 previous_interactions_total_ -
 
 2935                                                 wall_actions_this_interval;
 
 2938       if ((jmu_B_lat_ != 
nullptr)) {
 
 2940                                                    EM_lat_.get(), parameters_);
 
 2944         ensembles_, interactions_this_interval, conserved_initial_, time_start_,
 
 2945         end_time_, E_mean_field, initial_mean_field_energy_);
 
 2946     int total_particles = 0;
 
 2947     for (
const Particles &particles : ensembles_) {
 
 2948       total_particles += particles.
size();
 
 2950     if (IC_output_switch_ && (total_particles == 0)) {
 
 2953       const double remaining_energy =
 
 2954           conserved_initial_.momentum().x0() - total_energy_removed_;
 
 2956         throw std::runtime_error(
 
 2957             "There is remaining energy in the system although all particles " 
 2960             std::to_string(remaining_energy) + 
" [GeV]");
 
 2964             << 
"Time real: " << SystemClock::now() - time_start_;
 
 2966             << 
"Interactions before reaching hypersurface: " 
 2967             << interactions_total_ - wall_actions_total_ -
 
 2968                    total_hypersurface_crossing_actions_;
 
 2970             << 
"Total number of particles removed on hypersurface: " 
 2971             << total_hypersurface_crossing_actions_;
 
 2974       const double precent_discarded =
 
 2975           interactions_total_ > 0
 
 2976               ? 
static_cast<double>(discarded_interactions_total_) * 100.0 /
 
 2979       std::stringstream msg_discarded;
 
 2981           << 
"Discarded interaction number: " << discarded_interactions_total_
 
 2982           << 
" (" << precent_discarded
 
 2983           << 
"% of the total interaction number including wall crossings)";
 
 2987           << 
"Time real: " << SystemClock::now() - time_start_;
 
 2991           precent_discarded > 1.0) {
 
 2994             << msg_discarded.str()
 
 2995             << 
"\nThe number of discarded interactions is large, which means " 
 2996                "the assumption for the stochastic criterion of\n1 interaction " 
 2997                "per particle per timestep is probably violated. Consider " 
 2998                "reducing the timestep size.";
 
 3002                                << interactions_total_ - wall_actions_total_;
 
 3006     int unformed_particles_count = 0;
 
 3007     for (
const Particles &particles : ensembles_) {
 
 3009         if (particle.formation_time() > end_time_) {
 
 3010           unformed_particles_count++;
 
 3014     if (unformed_particles_count > 0) {
 
 3016           "End time might be too small. ", unformed_particles_count,
 
 3017           " unformed particles were found at the end of the evolution.");
 
 3022   count_nonempty_ensembles();
 
 3024   for (
const auto &output : outputs_) {
 
 3025     for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
 
 3027           ensembles_, E_mean_field, modus_.impact_parameter(), parameters_,
 
 3028           projectile_target_interact_[i_ens], kinematic_cuts_for_IC_output_);
 
 3029       output->at_eventend(ensembles_[i_ens],
 
 3031                           event_ * parameters_.n_ensembles + i_ens, event_info);
 
 3034     output->at_eventend(ensembles_, event_);
 
 3039                           dens_type_lattice_printout_);
 
 3042     if (printout_tmn_) {
 
 3044                           dens_type_lattice_printout_);
 
 3047     if (printout_tmn_landau_) {
 
 3049                           dens_type_lattice_printout_);
 
 3052     if (printout_v_landau_) {
 
 3054                           dens_type_lattice_printout_);
 
 3057     if (printout_j_QBS_) {
 
 3063 template <
typename Modus>
 
 3065   for (
bool has_interaction : projectile_target_interact_) {
 
 3066     if (has_interaction) {
 
 3067       nonempty_ensembles_++;
 
 3072 template <
typename Modus>
 
 3075     return event_ >= nevents_;
 
 3078     if (nonempty_ensembles_ >= minimum_nonempty_ensembles_) {
 
 3081     if (event_ >= max_events_) {
 
 3083           << 
"Maximum number of events (" << max_events_
 
 3084           << 
") exceeded. Stopping calculation. " 
 3085           << 
"The fraction of empty ensembles is " 
 3086           << (1.0 - 
static_cast<double>(nonempty_ensembles_) /
 
 3087                         (event_ * parameters_.n_ensembles))
 
 3088           << 
". If this fraction is expected, try increasing the " 
 3089              "Maximum_Ensembles_Run.";
 
 3094   throw std::runtime_error(
"Event counting option is invalid");
 
 3098 template <
typename Modus>
 
 3101   for (event_ = 0; !is_finished(); event_++) {
 
 3102     mainlog.info() << 
"Event " << event_;
 
 3105     initialize_new_event();
 
 3107     run_time_evolution(end_time_);
 
 3109     if (force_decays_) {
 
Collection of useful type aliases to measure and output the (real) runtime.
A stream modifier that allows to colorize the log output.
Action is the base class for a generic process that takes a number of incoming particles and transfor...
virtual ProcessType get_type() const
Get the process type.
virtual double get_total_weight() const =0
Return the total weight value, which is mainly used for the weight output entry.
const ParticleList & incoming_particles() const
Get the list of particles that go into the action.
virtual void perform(Particles *particles, uint32_t id_process)
Actually perform the action, e.g.
virtual void generate_final_state()=0
Generate the final state for this action.
double sqrt_s() const
Determine the total energy in the center-of-mass frame [GeV].
FourVector get_interaction_point() const
Get the interaction point.
bool is_valid(const Particles &particles) const
Check whether the action still applies.
bool is_pauli_blocked(const std::vector< Particles > &ensembles, const PauliBlocker &p_bl) const
Check if the action is Pauli-blocked.
The Actions class abstracts the storage and manipulation of actions.
ActionPtr pop()
Return the first action in the list and removes it from the list.
double earliest_time() const
Return time of execution of earliest action.
ActionList::size_type size() const
void insert(ActionList &&new_acts)
Insert a list of actions into this object.
static bool is_bremsstrahlung_reaction(const ParticleList &in)
Check if particles can undergo an implemented photon process.
Interface to the SMASH configuration files.
A class to pre-calculate and store parameters relevant for density calculation.
Non-template interface to Experiment<Modus>.
static std::unique_ptr< ExperimentBase > create(Configuration config, const bf::path &output_path)
Factory method that creates and initializes a new Experiment<Modus>.
virtual ~ExperimentBase()=default
The virtual destructor avoids undefined behavior when destroying derived objects.
virtual void run()=0
Runs the experiment.
The main class, where the simulation of an experiment is executed.
const bool bremsstrahlung_switch_
This indicates whether bremsstrahlung is switched on.
void propagate_and_shine(double to_time, Particles &particles)
Propagate all particles until time to_time without any interactions and shine dileptons.
const ExpansionProperties metric_
This struct contains information on the metric to be used.
std::unique_ptr< ActionFinderInterface > photon_finder_
The (Scatter) Actions Finder for Direct Photons.
const bool force_decays_
This indicates whether we force all resonances to decay in the last timestep.
double initial_mean_field_energy_
The initial total mean field energy in the system.
std::vector< std::unique_ptr< ActionFinderInterface > > action_finders_
The Action finder objects.
bool printout_tmn_
Whether to print the energy-momentum tensor.
QuantumNumbers conserved_initial_
The conserved quantities of the system.
DensityParameters density_param_
Structure to precalculate and hold parameters for density computations.
double next_output_time() const
Shortcut for next output time.
bool printout_full_lattice_ascii_td_
Whether to print the thermodynamics quantities evaluated on the lattices, point by point,...
double total_energy_removed_
Total energy removed from the system in hypersurface crossing actions.
DensityType dens_type_lattice_printout_
Type of density for lattice printout.
double max_transverse_distance_sqr_
Maximal distance at which particles can interact in case of the geometric criterion,...
bool printout_j_QBS_
Whether to print the Q, B, S 4-currents.
std::unique_ptr< GrandCanThermalizer > thermalizer_
Instance of class used for forced thermalization.
void count_nonempty_ensembles()
Counts the number of ensembles in wich interactions took place at the end of an event.
const TimeStepMode time_step_mode_
This indicates whether to use time steps.
std::unique_ptr< DensityLattice > jmu_custom_lat_
Custom density on the lattices.
bool printout_full_lattice_any_td_
Whether to print the thermodynamics quantities evaluated on the lattices, point by point,...
Particles * first_ensemble()
Provides external access to SMASH particles.
int minimum_nonempty_ensembles_
The number of ensembles, in which interactions take place, to be calculated.
void run_time_evolution_timestepless(Actions &actions, int i_ensemble, const double end_time_propagation, const double end_time_run)
Performs all the propagations and actions during a certain time interval neglecting the influence of ...
std::unique_ptr< DensityLattice > jmu_B_lat_
Baryon density on the lattice.
void create_output(const std::string &format, const std::string &content, const bf::path &output_path, const OutputParameters &par)
Create a list of output files.
DensityType dens_type_
Type of density to be written to collision headers.
const int nevents_
Number of events.
void intermediate_output()
Intermediate output during an event.
std::vector< FourVector > beam_momentum_
The initial nucleons in the ColliderModus propagate with beam_momentum_, if Fermi motion is frozen.
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > FI3_lat_
Lattices for the electric and magnetic component of the symmetry force.
std::unique_ptr< RectangularLattice< FourVector > > new_jmu_auxiliary_
Auxiliary lattice for values of jmu at a time step t0 + dt.
double compute_min_cell_length(double dt) const
Calculate the minimal size for the grid cells such that the ScatterActionsFinder will find all collis...
void initialize_new_event()
This is called in the beginning of each event.
bool is_finished()
Checks wether the desired number events have been calculated.
int n_fractional_photons_
Number of fractional photons produced per single reaction.
const double delta_time_startup_
The clock's timestep size at start up.
std::unique_ptr< RectangularLattice< EnergyMomentumTensor > > Tmn_
Lattices of energy-momentum tensors for printout.
std::vector< Particles > ensembles_
Complete particle list, all ensembles in one vector.
std::unique_ptr< RectangularLattice< FourVector > > new_fields_auxiliary_
Auxiliary lattice for values of Amu at a time step t0 + dt.
SystemTimePoint time_start_
system starting time of the simulation
uint64_t previous_wall_actions_total_
Total number of wall-crossings for previous timestep.
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > FB_lat_
Lattices for the electric and magnetic components of the Skyrme or VDF force.
OutputsList outputs_
A list of output formaters.
std::unique_ptr< RectangularLattice< std::array< FourVector, 4 > > > fields_four_gradient_auxiliary_
Auxiliary lattice for calculating the four-gradient of Amu.
void do_final_decays()
Performs the final decays of an event.
std::unique_ptr< PauliBlocker > pauli_blocker_
An instance of PauliBlocker class that stores parameters needed for Pauli blocking calculations and c...
bool printout_v_landau_
Whether to print the 4-velocity in Landau frame.
bool perform_action(Action &action, int i_ensemble, bool include_pauli_blocking=true)
Perform the given action.
std::unique_ptr< RectangularLattice< FourVector > > UI3_lat_
Lattices for symmetry potentials (evaluated in the local rest frame) times the isospin flow 4-velocit...
bool printout_lattice_td_
Whether to print the thermodynamics quantities evaluated on the lattices.
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > EM_lat_
Lattices for electric and magnetic field in fm^-2.
std::unique_ptr< FieldsLattice > fields_lat_
Mean-field A^mu on the lattice.
int max_events_
Maximum number of events to be calculated in order obtain the desired number of non-empty events usin...
int nonempty_ensembles_
Number of ensembles containing an interaction.
OutputPtr photon_output_
The Photon output.
EventCounting event_counting_
The way in which the number of calculated events is specified.
const bool dileptons_switch_
This indicates whether dileptons are switched on.
Modus modus_
Instance of the Modus template parameter.
std::unique_ptr< RectangularLattice< FourVector > > old_jmu_auxiliary_
Auxiliary lattice for values of jmu at a time step t0.
std::unique_ptr< DecayActionsFinderDilepton > dilepton_finder_
The Dilepton Action Finder.
std::unique_ptr< DensityLattice > j_QBS_lat_
4-current for j_QBS lattice output
bool printout_tmn_landau_
Whether to print the energy-momentum tensor in Landau frame.
Experiment(Configuration config, const bf::path &output_path)
Create a new Experiment.
bool printout_full_lattice_binary_td_
Whether to print the thermodynamics quantities evaluated on the lattices, point by point,...
std::unique_ptr< RectangularLattice< std::array< FourVector, 4 > > > four_gradient_auxiliary_
Auxiliary lattice for calculating the four-gradient of jmu.
const bool photons_switch_
This indicates whether photons are switched on.
StringProcess * process_string_ptr_
Pointer to the string process class object, which is used to set the random seed for PYTHIA objects i...
std::unique_ptr< RectangularLattice< FourVector > > UB_lat_
Lattices for Skyrme or VDF potentials (evaluated in the local rest frame) times the baryon flow 4-vel...
ExperimentParameters parameters_
Struct of several member variables.
std::unique_ptr< RectangularLattice< FourVector > > old_fields_auxiliary_
Auxiliary lattice for values of Amu at a time step t0.
void run_time_evolution(const double t_end)
Runs the time evolution of an event with fixed-sized time steps or without timesteps,...
std::unique_ptr< DensityLattice > jmu_el_lat_
Electric charge density on the lattice.
std::unique_ptr< Potentials > potentials_
An instance of potentials class, that stores parameters of potentials, calculates them and their grad...
uint64_t wall_actions_total_
Total number of wall-crossings for current timestep.
uint64_t total_hypersurface_crossing_actions_
Total number of particles removed from the evolution in hypersurface crossing actions.
uint64_t interactions_total_
Total number of interactions for current timestep.
const bool use_grid_
This indicates whether to use the grid.
std::unique_ptr< DensityLattice > jmu_I3_lat_
Isospin projection density on the lattice.
uint64_t total_pauli_blocked_
Total number of Pauli-blockings for current timestep.
void final_output()
Output at the end of an event.
std::vector< bool > projectile_target_interact_
Whether the projectile and the target collided.
Modus * modus()
Provides external access to SMASH calculation modus.
void update_potentials()
Recompute potentials on lattices if necessary.
const bool IC_output_switch_
This indicates whether the IC output is enabled.
OutputPtr dilepton_output_
The Dilepton output.
int64_t seed_
random seed for the next event.
std::vector< Particles > * all_ensembles()
Getter for all ensembles.
uint64_t previous_interactions_total_
Total number of interactions for previous timestep.
uint64_t discarded_interactions_total_
Total number of discarded interactions, because they were invalidated before they could be performed.
void run() override
Runs the experiment.
bool kinematic_cuts_for_IC_output_
This indicates whether kinematic cuts are enabled for the IC output.
const double end_time_
simulation time at which the evolution is stopped.
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
ParticleData contains the dynamic information of a certain particle.
static double formation_power_
Power with which the cross section scaling factor grows in time.
The Particles class abstracts the storage and manipulation of particles.
A class that stores parameters of potentials, calculates potentials and their gradients.
static ThreeVector B_field_integrand(ThreeVector pos, DensityOnLattice &charge_density, ThreeVector point)
Integrand for calculating the magnetic field using the Biot-Savart formula.
static ThreeVector E_field_integrand(ThreeVector pos, DensityOnLattice &charge_density, ThreeVector point)
Integrand for calculating the electric field.
A container for storing conserved values.
A container class to hold all the arrays on the lattice and access them.
static bool is_photon_reaction(const ParticleList &in)
Check if particles can undergo an implemented photon process.
static bool is_kinematically_possible(const double s_sqrt, const ParticleList &in)
Check if CM-energy is sufficient to produce hadron in final state.
String excitation processes used in SMASH.
ThermalizationAction implements forced thermalization as an Action class.
bool any_particles_thermalized() const
This method checks, if there are particles in the region to be thermalized.
The ThreeVector class represents a physical three-vector  with the components .
FermiMotion
Option to use Fermi Motion.
@ Frozen
Use fermi motion without potentials.
@ Off
Don't use fermi motion.
TimeStepMode
The time step mode.
@ Fixed
Use fixed time step.
@ None
Don't use time steps; propagate from action to action.
@ Stochastic
Stochastic Criteiron.
EventCounting
Defines how the number of events is determined.
#define SMASH_SOURCE_LOCATION
Hackery that is required to output the location in the source code where the log statement occurs.
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
FormattingHelper< T > format(const T &value, const char *unit, int width=-1, int precision=-1)
Acts as a stream modifier for std::ostream to output an object with an optional suffix string and wit...
std::unique_ptr< OutputInterface > create_oscar_output(const std::string &format, const std::string &content, const bf::path &path, const OutputParameters &out_par)
#define likely(x)
Tell the branch predictor that this expression is likely true.
Engine::result_type advance()
Advance the engine's state and return the generated value.
void set_seed(T &&seed)
Sets the seed of the random number engine.
void update_momenta(std::vector< Particles > &particles, double dt, const Potentials &pot, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *FB_lat, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *FI3_lat, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *EM_lat)
Updates the momenta of all particles at the current time step according to the equations of motion:
static constexpr int LInitialConditions
EventInfo fill_event_info(const std::vector< Particles > &ensembles, double E_mean_field, double modus_impact_parameter, const ExperimentParameters ¶meters, bool projectile_target_interact, bool kinematic_cut_for_SMASH_IC)
Generate the EventInfo object which is passed to outputs_.
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.
void expand_space_time(Particles *particles, const ExperimentParameters ¶meters, const ExpansionProperties &metric)
Modifies positions and momentum of all particles to account for space-time deformation.
void update_lattice(RectangularLattice< T > *lat, const LatticeUpdate update, const DensityType dens_type, const DensityParameters &par, const std::vector< Particles > &ensembles, const bool compute_gradient)
Updates the contents on the lattice.
void check_interactions_total(uint64_t interactions_total)
Make sure interactions_total can be represented as a 32-bit integer.
@ HyperSurfaceCrossing
Hypersurface crossing Particles are removed from the evolution and printed to a separate output to se...
std::tuple< double, FourVector, ThreeVector, ThreeVector, FourVector, FourVector, FourVector, FourVector > current_eckart(const ThreeVector &r, const ParticleList &plist, const DensityParameters &par, DensityType dens_type, bool compute_gradient, bool smearing)
Calculates Eckart rest frame density and 4-current of a given density type and optionally the gradien...
double propagate_straight_line(Particles *particles, double to_time, const std::vector< FourVector > &beam_momentum)
Propagates the positions of all particles on a straight line to a given moment.
constexpr double very_small_double
A very small double, used to avoid division by zero.
double calculate_mean_field_energy(const Potentials &potentials, RectangularLattice< smash::DensityOnLattice > &jmu_B_lat, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *em_lattice, const ExperimentParameters ¶meters)
Calculate the total mean field energy of the system; this will be printed to the screen when SMASH is...
static constexpr int LExperiment
void update_fields_lattice(RectangularLattice< FieldsOnLattice > *fields_lat, RectangularLattice< FourVector > *old_fields, RectangularLattice< FourVector > *new_fields, RectangularLattice< std::array< FourVector, 4 >> *fields_four_grad_lattice, DensityLattice *jmu_B_lat, const LatticeUpdate fields_lat_update, const Potentials &potentials, const double time_step)
Updates the contents on the lattice of FieldsOnLattice type.
constexpr double nucleon_mass
Nucleon mass in GeV.
LatticeUpdate
Enumerator option for lattice updates.
std::ostream & operator<<(std::ostream &out, const Experiment< Modus > &e)
Creates a verbose textual description of the setup of the Experiment.
Potentials * pot_pointer
Pointer to a Potential class.
static constexpr int LMain
constexpr double really_small
Numerical error tolerance.
DensityType
Allows to choose which kind of density to calculate.
RectangularLattice< FourVector > * UB_lat_pointer
Pointer to the skyrme potential on the lattice.
ExperimentParameters create_experiment_parameters(Configuration config)
Gathers all general Experiment parameters.
std::unique_ptr< T > make_unique(Args &&... args)
Definition for make_unique Is in C++14's standard library; necessary for older compilers.
@ Largest
Make cells as large as possible.
std::chrono::time_point< std::chrono::system_clock > SystemTimePoint
Type (alias) that is used to store the current time.
const std::string hline(113, '-')
String representing a horizontal line.
RectangularLattice< FourVector > * UI3_lat_pointer
Pointer to the symmmetry potential on the lattice.
constexpr double fm2_mb
mb <-> fm^2 conversion factor.
Structure to contain custom data for output.
Struct containing the type of the metric and the expansion parameter of the metric.
Exception class that is thrown if an invalid modus is requested from the Experiment factory.
Exception class that is thrown if the requested output path in the Experiment factory is not existing...
Helper structure for Experiment.
double fixed_min_cell_length
Fixed minimal grid cell length (in fm).
const CollisionCriterion coll_crit
Employed collision criterion.
std::unique_ptr< Clock > outputclock
Output clock to keep track of the next output time.
Helper structure for Experiment to hold output options and parameters.