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