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;
147 template <
typename Modus>
149 template <
typename Modus>
176 template <
typename Modus>
285 double end_time_propagation);
412 std::unique_ptr<RectangularLattice<FourVector>>
UB_lat_ =
nullptr;
418 std::unique_ptr<RectangularLattice<FourVector>>
UI3_lat_ =
nullptr;
424 std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
428 std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
432 std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
436 std::unique_ptr<RectangularLattice<EnergyMomentumTensor>>
Tmn_;
443 std::unique_ptr<RectangularLattice<std::array<FourVector, 4>>>
451 std::unique_ptr<RectangularLattice<std::array<FourVector, 4>>>
629 friend std::ostream &operator<<<>(std::ostream &out,
const Experiment &e);
633 template <
typename Modus>
635 out <<
"End time: " << e.
end_time_ <<
" fm/c\n";
640 template <
typename Modus>
642 const std::string &content,
643 const bf::path &output_path,
645 logg[
LExperiment].info() <<
"Adding output " << content <<
" of format "
648 if (
format ==
"VTK" && content ==
"Particles") {
649 outputs_.emplace_back(
650 make_unique<VtkOutput>(output_path, content, out_par));
651 }
else if (
format ==
"Root") {
652 #ifdef SMASH_USE_ROOT
653 if (content ==
"Initial_Conditions") {
654 outputs_.emplace_back(
655 make_unique<RootOutput>(output_path,
"SMASH_IC", out_par));
657 outputs_.emplace_back(
658 make_unique<RootOutput>(output_path, content, out_par));
662 "Root output requested, but Root support not compiled in");
664 }
else if (
format ==
"Binary") {
665 if (content ==
"Collisions" || content ==
"Dileptons" ||
666 content ==
"Photons") {
667 outputs_.emplace_back(
668 make_unique<BinaryOutputCollisions>(output_path, content, out_par));
669 }
else if (content ==
"Particles") {
670 outputs_.emplace_back(
671 make_unique<BinaryOutputParticles>(output_path, content, out_par));
672 }
else if (content ==
"Initial_Conditions") {
673 outputs_.emplace_back(make_unique<BinaryOutputInitialConditions>(
674 output_path, content, out_par));
676 }
else if (
format ==
"Oscar1999" ||
format ==
"Oscar2013") {
677 outputs_.emplace_back(
679 }
else if (content ==
"Thermodynamics" &&
format ==
"ASCII") {
680 outputs_.emplace_back(
681 make_unique<ThermodynamicOutput>(output_path, content, out_par));
682 }
else if (content ==
"Thermodynamics" &&
683 (
format ==
"Lattice_ASCII" ||
format ==
"Lattice_Binary")) {
684 printout_full_lattice_any_td_ =
true;
685 if (
format ==
"Lattice_ASCII") {
686 printout_full_lattice_ascii_td_ =
true;
688 if (
format ==
"Lattice_Binary") {
689 printout_full_lattice_binary_td_ =
true;
691 outputs_.emplace_back(make_unique<ThermodynamicLatticeOutput>(
692 output_path, content, out_par, printout_full_lattice_ascii_td_,
693 printout_full_lattice_binary_td_));
694 }
else if (content ==
"Thermodynamics" &&
format ==
"VTK") {
695 printout_lattice_td_ =
true;
696 outputs_.emplace_back(
697 make_unique<VtkOutput>(output_path, content, out_par));
698 }
else if (content ==
"Initial_Conditions" &&
format ==
"ASCII") {
699 outputs_.emplace_back(
700 make_unique<ICOutput>(output_path,
"SMASH_IC", out_par));
701 }
else if (
format ==
"HepMC") {
702 #ifdef SMASH_USE_HEPMC
703 if (content ==
"Particles") {
704 outputs_.emplace_back(make_unique<HepMcOutput>(
705 output_path,
"SMASH_HepMC_particles",
false));
706 }
else if (content ==
"Collisions") {
707 outputs_.emplace_back(make_unique<HepMcOutput>(
708 output_path,
"SMASH_HepMC_collisions",
true));
711 "HepMC only available for Particles and "
712 "Collisions content. Requested for " +
717 "HepMC output requested, but HepMC support not compiled in");
719 }
else if (content ==
"Coulomb" &&
format ==
"VTK") {
720 outputs_.emplace_back(
721 make_unique<VtkOutput>(output_path,
"Fields", out_par));
722 }
else if (content ==
"Rivet") {
723 #ifdef SMASH_USE_RIVET
725 static bool rivet_format_already_selected =
false;
727 if (rivet_format_already_selected) {
729 "Rivet output format can only be one, either YODA or YODA-full. "
730 "Only your first valid choice will be used.");
734 outputs_.emplace_back(
735 make_unique<RivetOutput>(output_path,
"SMASH_Rivet",
false, out_par));
736 rivet_format_already_selected =
true;
737 }
else if (
format ==
"YODA-full") {
738 outputs_.emplace_back(make_unique<RivetOutput>(
739 output_path,
"SMASH_Rivet_full",
true, out_par));
740 rivet_format_already_selected =
true;
743 "not one of YODA or YODA-full");
747 "Rivet output requested, but Rivet support not compiled in");
751 <<
"Unknown combination of format (" <<
format <<
") and content ("
752 << content <<
"). Fix the config.";
932 template <
typename Modus>
936 modus_(config[
"Modi"], parameters_),
937 ensembles_(parameters_.n_ensembles),
938 nevents_(config.take({
"General",
"Nevents"})),
939 end_time_(config.take({
"General",
"End_Time"})),
940 delta_time_startup_(parameters_.labclock->timestep_duration()),
942 config.take({
"Collision_Term",
"Force_Decays_At_End"},
true)),
943 use_grid_(config.take({
"General",
"Use_Grid"},
true)),
946 config.take({
"General",
"Expansion_Rate"}, 0.1)),
948 config.take({
"Collision_Term",
"Dileptons",
"Decays"},
false)),
949 photons_switch_(config.take(
950 {
"Collision_Term",
"Photons",
"2to2_Scatterings"},
false)),
951 bremsstrahlung_switch_(
952 config.take({
"Collision_Term",
"Photons",
"Bremsstrahlung"},
false)),
953 IC_output_switch_(config.has_value({
"Output",
"Initial_Conditions"})),
961 throw std::invalid_argument(
962 "Covariant Gaussian derivatives only make sense for Covariant Gaussian "
970 parameters_.discrete_weight < (1. / 7.)) {
971 throw std::invalid_argument(
972 "The central weight for discrete smearing should be >= 1./7.");
977 throw std::invalid_argument(
978 "The stochastic criterion can only be employed for fixed time step "
979 "mode and with a grid!");
983 " testparticles per particle.");
985 " parallel ensembles.");
988 if (dileptons_switch_) {
989 dilepton_finder_ = make_unique<DecayActionsFinderDilepton>();
991 if (photons_switch_ || bremsstrahlung_switch_) {
992 n_fractional_photons_ =
993 config.take({
"Collision_Term",
"Photons",
"Fractional_Photons"}, 100);
995 if (parameters_.two_to_one) {
996 if (parameters_.res_lifetime_factor < 0.) {
997 throw std::invalid_argument(
998 "Resonance lifetime modifier cannot be negative!");
1002 "Resonance lifetime set to zero. Make sure resonances cannot "
1004 "inelastically (e.g. resonance chains), else SMASH is known to "
1007 action_finders_.emplace_back(
1008 make_unique<DecayActionsFinder>(parameters_.res_lifetime_factor));
1010 bool no_coll = config.take({
"Collision_Term",
"No_Collisions"},
false);
1011 if ((parameters_.two_to_one || parameters_.included_2to2.any() ||
1012 parameters_.included_multi.any() || parameters_.strings_switch) &&
1014 auto scat_finder = make_unique<ScatterActionsFinder>(config, parameters_);
1015 max_transverse_distance_sqr_ =
1016 scat_finder->max_transverse_distance_sqr(parameters_.testparticles);
1017 process_string_ptr_ = scat_finder->get_process_string_ptr();
1018 action_finders_.emplace_back(std::move(scat_finder));
1020 max_transverse_distance_sqr_ =
1021 parameters_.maximum_cross_section / M_PI *
fm2_mb;
1022 process_string_ptr_ = NULL;
1024 if (modus_.is_box()) {
1025 action_finders_.emplace_back(
1026 make_unique<WallCrossActionsFinder>(parameters_.box_length));
1028 if (IC_output_switch_) {
1029 if (!modus_.is_collider()) {
1030 throw std::runtime_error(
1031 "Initial conditions can only be extracted in collider modus.");
1034 if (config.has_value({
"Output",
"Initial_Conditions",
"Proper_Time"})) {
1037 config.take({
"Output",
"Initial_Conditions",
"Proper_Time"});
1040 double default_proper_time = modus_.nuclei_passing_time();
1041 double lower_bound =
1042 config.take({
"Output",
"Initial_Conditions",
"Lower_Bound"}, 0.5);
1043 if (default_proper_time >= lower_bound) {
1044 proper_time = default_proper_time;
1047 <<
"Nuclei passing time is too short, hypersurface proper time set "
1049 << lower_bound <<
" fm.";
1050 proper_time = lower_bound;
1053 action_finders_.emplace_back(
1054 make_unique<HyperSurfaceCrossActionsFinder>(proper_time));
1057 if (config.has_value({
"Collision_Term",
"Pauli_Blocking"})) {
1059 pauli_blocker_ = make_unique<PauliBlocker>(
1060 config[
"Collision_Term"][
"Pauli_Blocking"], parameters_);
1064 config.take({
"Collision_Term",
"Power_Particle_Formation"},
1065 modus_.sqrt_s_NN() >= 200. ? -1. : 1.);
1101 " create OutputInterface objects");
1103 auto output_conf = config[
"Output"];
1333 <<
"Density type printed to headers: " << dens_type_;
1335 const OutputParameters output_parameters(std::move(output_conf));
1337 std::vector<std::string> output_contents = output_conf.list_upmost_nodes();
1338 for (
const auto &content : output_contents) {
1339 auto this_output_conf = output_conf[content.c_str()];
1340 const std::vector<std::string> formats = this_output_conf.take({
"Format"});
1341 if (output_path ==
"") {
1344 for (
const auto &
format : formats) {
1345 create_output(
format, content, output_path, output_parameters);
1356 if (config.has_value({
"Potentials"})) {
1359 throw std::invalid_argument(
"Can't use potentials without time steps!");
1363 <<
"Potentials don't work with frozen Fermi momenta! "
1364 "Use normal Fermi motion instead.";
1365 throw std::invalid_argument(
1366 "Can't use potentials "
1367 "with frozen Fermi momenta!");
1370 << parameters_.labclock->timestep_duration();
1372 potentials_ = make_unique<Potentials>(config[
"Potentials"], parameters_);
1375 if (potentials_->use_skyrme() && potentials_->use_vdf()) {
1376 throw std::runtime_error(
1377 "Can't use Skyrme and VDF potentials at the same time!");
1379 if (potentials_->use_symmetry() && potentials_->use_vdf()) {
1380 throw std::runtime_error(
1381 "Can't use symmetry and VDF potentials at the same time!");
1383 if (potentials_->use_skyrme()) {
1386 <<
"\t\tSkyrme_A [MeV] = " << potentials_->skyrme_a() <<
"\n";
1388 <<
"\t\tSkyrme_B [MeV] = " << potentials_->skyrme_b() <<
"\n";
1390 <<
"\t\t Skyrme_tau = " << potentials_->skyrme_tau() <<
"\n";
1392 if (potentials_->use_symmetry()) {
1394 <<
"Symmetry potential is:"
1395 <<
"\n S_pot [MeV] = " << potentials_->symmetry_S_pot() <<
"\n";
1397 if (potentials_->use_vdf()) {
1400 << potentials_->saturation_density() <<
"\n";
1401 for (
int i = 0; i < potentials_->number_of_terms(); i++) {
1403 <<
"\t\tCoefficient_" << i + 1 <<
" = "
1404 << 1000.0 * (potentials_->coeffs())[i] <<
" [MeV] \t Power_"
1405 << i + 1 <<
" = " << (potentials_->powers())[i] <<
"\n";
1411 throw std::invalid_argument(
1412 "Derivatives are necessary for running with potentials.\n"
1413 "Derivatives_Mode: \"Off\" only makes sense for "
1414 "Field_Derivatives_Mode: \"Direct\"!\nUse \"Covariant Gaussian\" or "
1415 "\"Finite difference\".");
1423 switch (parameters_.derivatives_mode) {
1434 switch (parameters_.rho_derivatives_mode) {
1443 if (potentials_->use_vdf()) {
1444 switch (parameters_.field_derivatives_mode) {
1457 if (potentials_->use_vdf() && (parameters_.rho_derivatives_mode ==
1459 parameters_.field_derivatives_mode ==
1461 throw std::runtime_error(
1462 "Can't use VDF potentials without rest frame density derivatives or "
1463 "direct field derivatives!");
1468 throw std::runtime_error(
1469 "Can't use potentials without gradients of baryon current (Skyrme, "
1471 " or direct field derivatives (VDF)!");
1474 if (!(potentials_->use_vdf()) &&
1476 throw std::invalid_argument(
1477 "Field_Derivatives_Mode: \"Direct\" only makes sense for the VDF "
1478 "potentials!\nUse Field_Derivatives_Mode: \"Chain Rule\" or comment "
1479 "this option out (Chain Rule is default)");
1484 switch (parameters_.smearing_mode) {
1490 << parameters_.discrete_weight;
1494 << parameters_.triangular_range;
1578 if (config.has_value({
"Lattice"})) {
1579 std::array<double, 3> l_default{20., 20., 20.};
1580 std::array<int, 3> n_default{10, 10, 10};
1581 std::array<double, 3> origin_default{-20., -20., -20.};
1582 bool periodic_default =
false;
1583 if (modus_.is_collider()) {
1585 const double gam = modus_.sqrt_s_NN() / (2.0 *
nucleon_mass);
1586 const double max_z = 5.0 / gam + end_time_;
1587 const double estimated_max_transverse_velocity = 0.7;
1588 const double max_xy = 5.0 + estimated_max_transverse_velocity * end_time_;
1589 origin_default = {-max_xy, -max_xy, -max_z};
1590 l_default = {2 * max_xy, 2 * max_xy, 2 * max_z};
1593 const int n_xy = std::ceil(2 * max_xy / 0.8);
1594 int nz = std::ceil(2 * max_z / 0.8);
1599 nz =
static_cast<int>(std::ceil(2 * max_z / 0.8 * gam));
1601 n_default = {n_xy, n_xy, nz};
1602 }
else if (modus_.is_box()) {
1603 periodic_default =
true;
1604 origin_default = {0., 0., 0.};
1605 const double bl = modus_.length();
1606 l_default = {bl, bl, bl};
1607 const int n_xyz = std::ceil(bl / 0.5);
1608 n_default = {n_xyz, n_xyz, n_xyz};
1609 }
else if (modus_.is_sphere()) {
1612 const double max_d = modus_.radius() + end_time_;
1613 origin_default = {-max_d, -max_d, -max_d};
1614 l_default = {2 * max_d, 2 * max_d, 2 * max_d};
1616 const int n_xyz = std::ceil(2 * max_d / 0.8);
1617 n_default = {n_xyz, n_xyz, n_xyz};
1620 const std::array<double, 3> l =
1621 config.take({
"Lattice",
"Sizes"}, l_default);
1622 const std::array<int, 3>
n =
1623 config.take({
"Lattice",
"Cell_Number"}, n_default);
1624 const std::array<double, 3> origin =
1625 config.take({
"Lattice",
"Origin"}, origin_default);
1626 const bool periodic =
1627 config.take({
"Lattice",
"Periodic"}, periodic_default);
1630 <<
"Lattice is ON. Origin = (" << origin[0] <<
"," << origin[1] <<
","
1631 << origin[2] <<
"), sizes = (" << l[0] <<
"," << l[1] <<
"," << l[2]
1632 <<
"), number of cells = (" <<
n[0] <<
"," <<
n[1] <<
"," <<
n[2]
1635 if (printout_lattice_td_ || printout_full_lattice_any_td_) {
1636 dens_type_lattice_printout_ = output_parameters.td_dens_type;
1637 printout_tmn_ = output_parameters.td_tmn;
1638 printout_tmn_landau_ = output_parameters.td_tmn_landau;
1639 printout_v_landau_ = output_parameters.td_v_landau;
1640 printout_j_QBS_ = output_parameters.td_jQBS;
1642 if (printout_tmn_ || printout_tmn_landau_ || printout_v_landau_) {
1643 Tmn_ = make_unique<RectangularLattice<EnergyMomentumTensor>>(
1646 if (printout_j_QBS_) {
1647 j_QBS_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1655 old_jmu_auxiliary_ = make_unique<RectangularLattice<FourVector>>(
1657 new_jmu_auxiliary_ = make_unique<RectangularLattice<FourVector>>(
1659 four_gradient_auxiliary_ =
1660 make_unique<RectangularLattice<std::array<FourVector, 4>>>(
1663 if (potentials_->use_skyrme()) {
1664 jmu_B_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1666 UB_lat_ = make_unique<RectangularLattice<FourVector>>(
1669 RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
1672 if (potentials_->use_symmetry()) {
1673 jmu_I3_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1675 UI3_lat_ = make_unique<RectangularLattice<FourVector>>(
1678 RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
1681 if (potentials_->use_coulomb()) {
1682 jmu_el_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1685 RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
1688 if (potentials_->use_vdf()) {
1689 jmu_B_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1691 UB_lat_ = make_unique<RectangularLattice<FourVector>>(
1694 RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
1699 old_fields_auxiliary_ = make_unique<RectangularLattice<FourVector>>(
1701 new_fields_auxiliary_ = make_unique<RectangularLattice<FourVector>>(
1703 fields_four_gradient_auxiliary_ =
1704 make_unique<RectangularLattice<std::array<FourVector, 4>>>(
1708 fields_lat_ = make_unique<FieldsLattice>(l,
n, origin, periodic,
1713 jmu_B_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1717 jmu_I3_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1724 jmu_custom_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1727 }
else if (printout_lattice_td_ || printout_full_lattice_any_td_) {
1729 "If you want Therm. VTK or Lattice output, configure a lattice for "
1731 }
else if (potentials_ && potentials_->use_coulomb()) {
1733 "Coulomb potential requires a lattice. Please add one to the "
1738 if ((potentials_ !=
nullptr) && (jmu_B_lat_ ==
nullptr)) {
1739 logg[
LExperiment].warn() <<
"Lattice is NOT used. Mean-field energy is "
1740 <<
"not going to be calculated.";
1744 if (parameters_.potential_affect_threshold) {
1752 (jmu_B_lat_ ==
nullptr)) {
1753 throw std::runtime_error(
1754 "Lattice is necessary to calculate finite difference gradients.");
1758 if (config.has_value({
"Forced_Thermalization"})) {
1759 Configuration &&th_conf = config[
"Forced_Thermalization"];
1760 thermalizer_ = modus_.create_grandcan_thermalizer(th_conf);
1765 seed_ = config.take({
"General",
"Randomseed"});
1796 uint64_t scatterings_this_interval,
1799 double E_mean_field,
1800 double E_mean_field_initial);
1835 double E_mean_field,
double modus_impact_parameter,
1837 bool projectile_target_interact);
1839 template <
typename Modus>
1849 while (r == INT64_MIN) {
1852 seed_ = std::abs(r);
1857 if (process_string_ptr_ != NULL) {
1858 process_string_ptr_->init_pythia_hadron_rndm();
1861 for (
Particles &particles : ensembles_) {
1866 double start_time = -1.0;
1870 if (modus_.is_collider()) {
1871 modus_.sample_impact();
1872 logg[
LExperiment].info(
"Impact parameter = ", modus_.impact_parameter(),
1875 for (
Particles &particles : ensembles_) {
1876 start_time = modus_.initial_conditions(&particles, parameters_);
1881 for (
Particles &particles : ensembles_) {
1882 modus_.impose_boundary_conditions(&particles, outputs_);
1885 double timestep = delta_time_startup_;
1887 switch (time_step_mode_) {
1891 timestep = end_time_ - start_time;
1893 const double max_dt = modus_.max_timestep(max_transverse_distance_sqr_);
1894 if (max_dt > 0. && max_dt < timestep) {
1899 std::unique_ptr<UniformClock> clock_for_this_event;
1900 if (modus_.is_list() && (timestep < 0.0)) {
1901 throw std::runtime_error(
1902 "Timestep for the given event is negative. \n"
1903 "This might happen if the formation times of the input particles are "
1904 "larger than the specified end time of the simulation.");
1906 clock_for_this_event = make_unique<UniformClock>(start_time, timestep);
1907 parameters_.labclock = std::move(clock_for_this_event);
1910 parameters_.outputclock->reset(start_time,
true);
1912 parameters_.outputclock->remove_times_in_past(start_time);
1915 "Lab clock: t_start = ", parameters_.labclock->current_time(),
1916 ", dt = ", parameters_.labclock->timestep_duration());
1921 wall_actions_total_ = 0;
1922 previous_wall_actions_total_ = 0;
1923 interactions_total_ = 0;
1924 previous_interactions_total_ = 0;
1925 discarded_interactions_total_ = 0;
1926 total_pauli_blocked_ = 0;
1927 projectile_target_interact_.resize(parameters_.n_ensembles,
false);
1928 total_hypersurface_crossing_actions_ = 0;
1929 total_energy_removed_ = 0.0;
1932 logg[
LExperiment].info() <<
"Time[fm] Ekin[GeV] E_MF[GeV] ETotal[GeV] "
1933 <<
"ETot/N[GeV] D(ETot/N)[GeV] Scatt&Decays "
1934 <<
"Particles Comp.Time";
1936 double E_mean_field = 0.0;
1941 if ((jmu_B_lat_ !=
nullptr)) {
1943 new_jmu_auxiliary_.get(), four_gradient_auxiliary_.get(),
1945 density_param_, ensembles_,
1946 parameters_.labclock->timestep_duration(),
true);
1950 for (
auto &node : *jmu_B_lat_) {
1951 node.overwrite_drho_dt_to_zero();
1952 node.overwrite_djmu_dt_to_zero();
1955 EM_lat_.get(), parameters_);
1958 initial_mean_field_energy_ = E_mean_field;
1960 ensembles_, 0u, conserved_initial_, time_start_,
1961 parameters_.labclock->current_time(), E_mean_field,
1962 initial_mean_field_energy_);
1965 for (
const auto &output : outputs_) {
1966 for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
1969 parameters_, projectile_target_interact_[i_ens]);
1970 output->at_eventstart(ensembles_[i_ens],
1972 event_ * parameters_.n_ensembles + i_ens,
1976 output->at_eventstart(ensembles_, event_);
1978 if (printout_full_lattice_any_td_) {
1979 switch (dens_type_lattice_printout_) {
1994 if (printout_tmn_) {
1996 dens_type_lattice_printout_, *Tmn_);
1998 if (printout_tmn_landau_) {
2000 dens_type_lattice_printout_, *Tmn_);
2002 if (printout_v_landau_) {
2004 dens_type_lattice_printout_, *Tmn_);
2006 if (printout_j_QBS_) {
2008 dens_type_lattice_printout_, *j_QBS_lat_);
2020 const double m = particle.effective_mass();
2021 double v_beam = 0.0;
2023 v_beam = modus_.velocity_projectile();
2025 v_beam = modus_.velocity_target();
2027 const double gamma = 1.0 / std::sqrt(1.0 - v_beam * v_beam);
2028 beam_momentum_.emplace_back(
2029 FourVector(gamma * m, 0.0, 0.0, gamma * v_beam * m));
2034 template <
typename Modus>
2036 Particles &particles = ensembles_[i_ensemble];
2039 discarded_interactions_total_++;
2041 " (discarded: invalid)");
2046 if (pauli_blocker_ && action.
is_pauli_blocked(ensembles_, *pauli_blocker_)) {
2047 total_pauli_blocked_++;
2053 if (modus_.is_collider()) {
2054 int count_target = 0, count_projectile = 0;
2062 if (count_target > 0 && count_projectile > 0) {
2063 projectile_target_interact_[i_ensemble] =
true;
2069 const auto id_process =
static_cast<uint32_t
>(interactions_total_ + 1);
2070 action.
perform(&particles, id_process);
2071 interactions_total_++;
2073 wall_actions_total_++;
2076 total_hypersurface_crossing_actions_++;
2083 constexpr
bool compute_grad =
false;
2084 const bool smearing =
true;
2087 rho = std::get<0>(
current_eckart(r_interaction.threevec(), particles,
2088 density_param_, dens_type_, compute_grad,
2106 for (
const auto &output : outputs_) {
2107 if (!output->is_dilepton_output() && !output->is_photon_output()) {
2108 if (output->is_IC_output() &&
2110 output->at_interaction(action, rho);
2111 }
else if (!output->is_IC_output()) {
2112 output->at_interaction(action, rho);
2122 if (photons_switch_ &&
2128 constexpr
double action_time = 0.;
2130 n_fractional_photons_,
2146 photon_act.add_single_process();
2148 photon_act.perform_photons(outputs_);
2151 if (bremsstrahlung_switch_ &&
2156 constexpr
double action_time = 0.;
2159 n_fractional_photons_,
2176 brems_act.add_single_process();
2178 brems_act.perform_bremsstrahlung(outputs_);
2185 template <
typename Modus>
2187 while (parameters_.labclock->current_time() < end_time_) {
2188 const double t = parameters_.labclock->current_time();
2190 std::min(parameters_.labclock->timestep_duration(), end_time_ - t);
2191 logg[
LExperiment].debug(
"Timestepless propagation for next ", dt,
" fm/c.");
2195 thermalizer_->is_time_to_thermalize(parameters_.labclock)) {
2196 const bool ignore_cells_under_treshold =
true;
2199 thermalizer_->update_thermalizer_lattice(ensembles_, density_param_,
2200 ignore_cells_under_treshold);
2201 const double current_t = parameters_.labclock->current_time();
2202 for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2203 thermalizer_->thermalize(ensembles_[i_ens], current_t,
2204 parameters_.testparticles);
2207 perform_action(th_act, i_ens);
2212 std::vector<Actions> actions(parameters_.n_ensembles);
2213 for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2214 actions[i_ens].clear();
2215 if (ensembles_[i_ens].size() > 0 && action_finders_.size() > 0) {
2217 const double min_cell_length = compute_min_cell_length(dt);
2221 use_grid_ ? modus_.create_grid(ensembles_[i_ens], min_cell_length,
2222 dt, parameters_.coll_crit)
2223 : modus_.create_grid(ensembles_[i_ens], min_cell_length,
2224 dt, parameters_.coll_crit,
2227 const double gcell_vol = grid.cell_volume();
2230 [&](
const ParticleList &search_list) {
2231 for (
const auto &finder : action_finders_) {
2232 actions[i_ens].insert(finder->find_actions_in_cell(
2233 search_list, dt, gcell_vol, beam_momentum_));
2236 [&](
const ParticleList &search_list,
2237 const ParticleList &neighbors_list) {
2238 for (
const auto &finder : action_finders_) {
2239 actions[i_ens].insert(finder->find_actions_with_neighbors(
2240 search_list, neighbors_list, dt, beam_momentum_));
2249 const double end_timestep_time =
2250 std::min(parameters_.labclock->next_time(), end_time_);
2251 while (next_output_time() <= end_timestep_time) {
2252 for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2253 run_time_evolution_timestepless(actions[i_ens], i_ens,
2254 next_output_time());
2256 ++(*parameters_.outputclock);
2259 if (parameters_.outputclock->current_time() < end_time_) {
2260 intermediate_output();
2263 for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2264 run_time_evolution_timestepless(actions[i_ens], i_ens, end_timestep_time);
2270 update_potentials();
2271 update_momenta(ensembles_, parameters_.labclock->timestep_duration(),
2272 *potentials_, FB_lat_.get(), FI3_lat_.get(),
2279 for (
Particles &particles : ensembles_) {
2284 ++(*parameters_.labclock);
2292 if (!potentials_ && !parameters_.strings_switch &&
2294 std::string err_msg = conserved_initial_.report_deviations(ensembles_);
2295 if (!err_msg.empty()) {
2297 throw std::runtime_error(
"Violation of conserved quantities!");
2302 if (pauli_blocker_) {
2304 "Interactions: Pauli-blocked/performed = ", total_pauli_blocked_,
"/",
2305 interactions_total_ - wall_actions_total_);
2309 template <
typename Modus>
2314 if (dilepton_finder_ !=
nullptr) {
2315 for (
const auto &output : outputs_) {
2316 dilepton_finder_->shine(particles, output.get(), dt);
2329 constexpr uint64_t max_uint32 = std::numeric_limits<uint32_t>::max();
2330 if (interactions_total >= max_uint32) {
2331 throw std::runtime_error(
"Integer overflow in total interaction number!");
2335 template <
typename Modus>
2337 Actions &actions,
int i_ensemble,
double end_time_propagation) {
2338 Particles &particles = ensembles_[i_ensemble];
2340 "Timestepless propagation: ",
"Actions size = ", actions.
size(),
2341 ", end time = ", end_time_propagation);
2349 ActionPtr act = actions.
pop();
2350 if (!act->is_valid(particles)) {
2351 discarded_interactions_total_++;
2353 " (discarded: invalid)");
2357 ", action time = ", act->time_of_execution());
2360 propagate_and_shine(act->time_of_execution(), particles);
2367 act->update_incoming(particles);
2368 const bool performed = perform_action(*act, i_ensemble);
2378 const double end_time_timestep =
2379 std::min(parameters_.labclock->next_time(), end_time_);
2380 assert(!(end_time_propagation > end_time_timestep));
2382 const double time_left = end_time_timestep - act->time_of_execution();
2383 const ParticleList &outgoing_particles = act->outgoing_particles();
2385 const double gcell_vol = 0.0;
2386 for (
const auto &finder : action_finders_) {
2388 actions.
insert(finder->find_actions_in_cell(outgoing_particles, time_left,
2389 gcell_vol, beam_momentum_));
2391 actions.
insert(finder->find_actions_with_surrounding_particles(
2392 outgoing_particles, particles, time_left, beam_momentum_));
2398 propagate_and_shine(end_time_propagation, particles);
2401 template <
typename Modus>
2403 const uint64_t wall_actions_this_interval =
2404 wall_actions_total_ - previous_wall_actions_total_;
2405 previous_wall_actions_total_ = wall_actions_total_;
2406 const uint64_t interactions_this_interval = interactions_total_ -
2407 previous_interactions_total_ -
2408 wall_actions_this_interval;
2409 previous_interactions_total_ = interactions_total_;
2410 double E_mean_field = 0.0;
2413 double computational_frame_time = 0.0;
2416 if ((jmu_B_lat_ !=
nullptr)) {
2418 EM_lat_.get(), parameters_);
2425 if (modus_.is_box()) {
2426 double tmp = (E_mean_field - initial_mean_field_energy_) /
2427 (E_mean_field + initial_mean_field_energy_);
2433 if (std::abs(tmp) > 0.01) {
2435 <<
"\n\n\n\t The mean field at t = "
2436 << parameters_.outputclock->current_time()
2437 <<
" [fm/c] differs from the mean field at t = 0:"
2438 <<
"\n\t\t initial_mean_field_energy_ = "
2439 << initial_mean_field_energy_ <<
" [GeV]"
2440 <<
"\n\t\t abs[(E_MF - E_MF(t=0))/(E_MF + E_MF(t=0))] = "
2442 <<
"\n\t\t E_MF/E_MF(t=0) = "
2443 << E_mean_field / initial_mean_field_energy_ <<
"\n\n";
2450 ensembles_, interactions_this_interval, conserved_initial_, time_start_,
2451 parameters_.outputclock->current_time(), E_mean_field,
2452 initial_mean_field_energy_);
2456 if (!(modus_.is_box() && parameters_.outputclock->current_time() <
2457 modus_.equilibration_time())) {
2458 for (
const auto &output : outputs_) {
2459 if (output->is_dilepton_output() || output->is_photon_output() ||
2460 output->is_IC_output()) {
2463 for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2466 parameters_, projectile_target_interact_[i_ens]);
2468 output->at_intermediate_time(ensembles_[i_ens], parameters_.outputclock,
2469 density_param_, event_info);
2470 computational_frame_time = event_info.current_time;
2473 output->at_intermediate_time(ensembles_, parameters_.outputclock,
2477 switch (dens_type_lattice_printout_) {
2480 density_param_, ensembles_,
false);
2483 output->thermodynamics_lattice_output(*jmu_B_lat_,
2484 computational_frame_time);
2493 output->thermodynamics_lattice_output(*jmu_I3_lat_,
2494 computational_frame_time);
2500 dens_type_lattice_printout_, density_param_,
2503 dens_type_lattice_printout_,
2505 output->thermodynamics_lattice_output(*jmu_custom_lat_,
2506 computational_frame_time);
2508 if (printout_tmn_ || printout_tmn_landau_ || printout_v_landau_) {
2510 density_param_, ensembles_,
false);
2511 if (printout_tmn_) {
2513 dens_type_lattice_printout_, *Tmn_);
2514 output->thermodynamics_lattice_output(
2517 if (printout_tmn_landau_) {
2519 dens_type_lattice_printout_, *Tmn_);
2520 output->thermodynamics_lattice_output(
2522 computational_frame_time);
2524 if (printout_v_landau_) {
2526 dens_type_lattice_printout_, *Tmn_);
2527 output->thermodynamics_lattice_output(
2529 computational_frame_time);
2533 output->fields_output(
"Efield",
"Bfield", *EM_lat_);
2535 if (printout_j_QBS_) {
2536 output->thermodynamics_lattice_output(
2537 *j_QBS_lat_, computational_frame_time, ensembles_, density_param_);
2541 output->thermodynamics_output(*thermalizer_);
2547 template <
typename Modus>
2550 if (potentials_->use_symmetry() && jmu_I3_lat_ !=
nullptr) {
2552 new_jmu_auxiliary_.get(), four_gradient_auxiliary_.get(),
2554 density_param_, ensembles_,
2555 parameters_.labclock->timestep_duration(),
true);
2557 if ((potentials_->use_skyrme() || potentials_->use_symmetry()) &&
2558 jmu_B_lat_ !=
nullptr) {
2560 new_jmu_auxiliary_.get(), four_gradient_auxiliary_.get(),
2562 density_param_, ensembles_,
2563 parameters_.labclock->timestep_duration(),
true);
2564 const size_t UBlattice_size = UB_lat_->size();
2565 for (
size_t i = 0; i < UBlattice_size; i++) {
2566 auto jB = (*jmu_B_lat_)[i];
2570 double baryon_density = jB.rho();
2574 if (potentials_->use_skyrme()) {
2576 flow_four_velocity_B * potentials_->skyrme_pot(baryon_density);
2578 potentials_->skyrme_force(baryon_density, baryon_grad_j0,
2579 baryon_dvecj_dt, baryon_curl_vecj);
2581 if (potentials_->use_symmetry() && jmu_I3_lat_ !=
nullptr) {
2582 auto jI3 = (*jmu_I3_lat_)[i];
2585 ? jI3.jmu_net() / jI3.rho()
2587 (*UI3_lat_)[i] = flow_four_velocity_I3 *
2588 potentials_->symmetry_pot(jI3.rho(), baryon_density);
2589 (*FI3_lat_)[i] = potentials_->symmetry_force(
2590 jI3.rho(), jI3.grad_j0(), jI3.dvecj_dt(), jI3.curl_vecj(),
2591 baryon_density, baryon_grad_j0, baryon_dvecj_dt,
2596 if (potentials_->use_coulomb()) {
2599 for (
size_t i = 0; i < EM_lat_->size(); i++) {
2601 ThreeVector position = jmu_el_lat_->cell_center(i);
2602 jmu_el_lat_->integrate_volume(electric_field,
2604 potentials_->coulomb_r_cut(), position);
2606 jmu_el_lat_->integrate_volume(magnetic_field,
2608 potentials_->coulomb_r_cut(), position);
2609 (*EM_lat_)[i] = std::make_pair(electric_field, magnetic_field);
2612 if (potentials_->use_vdf() && jmu_B_lat_ !=
nullptr) {
2614 new_jmu_auxiliary_.get(), four_gradient_auxiliary_.get(),
2616 density_param_, ensembles_,
2617 parameters_.labclock->timestep_duration(),
true);
2620 fields_lat_.get(), old_fields_auxiliary_.get(),
2621 new_fields_auxiliary_.get(), fields_four_gradient_auxiliary_.get(),
2623 parameters_.labclock->timestep_duration());
2625 const size_t UBlattice_size = UB_lat_->size();
2626 for (
size_t i = 0; i < UBlattice_size; i++) {
2627 auto jB = (*jmu_B_lat_)[i];
2628 (*UB_lat_)[i] = potentials_->vdf_pot(jB.rho(), jB.jmu_net());
2629 switch (parameters_.field_derivatives_mode) {
2631 (*FB_lat_)[i] = potentials_->vdf_force(
2632 jB.rho(), jB.drho_dxnu().x0(), jB.drho_dxnu().threevec(),
2633 jB.grad_rho_cross_vecj(), jB.jmu_net().x0(), jB.grad_j0(),
2634 jB.jmu_net().threevec(), jB.dvecj_dt(), jB.curl_vecj());
2637 auto Amu = (*fields_lat_)[i];
2638 (*FB_lat_)[i] = potentials_->vdf_force(
2639 Amu.grad_A0(), Amu.dvecA_dt(), Amu.curl_vecA());
2647 template <
typename Modus>
2651 uint64_t interactions_old = 0;
2653 interactions_old = interactions_total_;
2655 for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2659 if (dilepton_finder_ !=
nullptr) {
2660 for (
const auto &output : outputs_) {
2661 dilepton_finder_->shine_final(ensembles_[i_ens], output.get(),
true);
2665 for (
const auto &finder : action_finders_) {
2666 actions.
insert(finder->find_final_actions(ensembles_[i_ens]));
2670 perform_action(*actions.
pop(), i_ens);
2674 }
while (interactions_total_ > interactions_old);
2677 if (dilepton_finder_ !=
nullptr) {
2678 for (
const auto &output : outputs_) {
2679 for (
Particles &particles : ensembles_) {
2680 dilepton_finder_->shine_final(particles, output.get(),
false);
2686 template <
typename Modus>
2691 double E_mean_field = 0.0;
2692 if (
likely(parameters_.labclock > 0)) {
2693 const uint64_t wall_actions_this_interval =
2694 wall_actions_total_ - previous_wall_actions_total_;
2695 const uint64_t interactions_this_interval = interactions_total_ -
2696 previous_interactions_total_ -
2697 wall_actions_this_interval;
2700 if ((jmu_B_lat_ !=
nullptr)) {
2702 EM_lat_.get(), parameters_);
2706 ensembles_, interactions_this_interval, conserved_initial_, time_start_,
2707 end_time_, E_mean_field, initial_mean_field_energy_);
2708 int total_particles = 0;
2709 for (
const Particles &particles : ensembles_) {
2710 total_particles += particles.
size();
2712 if (IC_output_switch_ && (total_particles == 0)) {
2715 const double remaining_energy =
2716 conserved_initial_.momentum().x0() - total_energy_removed_;
2718 throw std::runtime_error(
2719 "There is remaining energy in the system although all particles "
2722 std::to_string(remaining_energy) +
" [GeV]");
2726 <<
"Time real: " << SystemClock::now() - time_start_;
2728 <<
"Interactions before reaching hypersurface: "
2729 << interactions_total_ - wall_actions_total_ -
2730 total_hypersurface_crossing_actions_;
2732 <<
"Total number of particles removed on hypersurface: "
2733 << total_hypersurface_crossing_actions_;
2736 const double precent_discarded =
2737 interactions_total_ > 0
2738 ?
static_cast<double>(discarded_interactions_total_) * 100.0 /
2741 std::stringstream msg_discarded;
2743 <<
"Discarded interaction number: " << discarded_interactions_total_
2744 <<
" (" << precent_discarded
2745 <<
"% of the total interaction number including wall crossings)";
2749 <<
"Time real: " << SystemClock::now() - time_start_;
2753 precent_discarded > 1.0) {
2756 << msg_discarded.str()
2757 <<
"\nThe number of discarded interactions is large, which means "
2758 "the assumption for the stochastic criterion of\n1 interaction "
2759 "per particle per timestep is probably violated. Consider "
2760 "reducing the timestep size.";
2764 << interactions_total_ - wall_actions_total_;
2768 int unformed_particles_count = 0;
2769 for (
const Particles &particles : ensembles_) {
2771 if (particle.formation_time() > end_time_) {
2772 unformed_particles_count++;
2776 if (unformed_particles_count > 0) {
2778 "End time might be too small. ", unformed_particles_count,
2779 " unformed particles were found at the end of the evolution.");
2783 for (
const auto &output : outputs_) {
2784 for (
int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2787 parameters_, projectile_target_interact_[i_ens]);
2788 output->at_eventend(ensembles_[i_ens],
2790 event_ * parameters_.n_ensembles + i_ens, event_info);
2793 output->at_eventend(ensembles_, event_);
2798 dens_type_lattice_printout_);
2801 if (printout_tmn_) {
2803 dens_type_lattice_printout_);
2806 if (printout_tmn_landau_) {
2808 dens_type_lattice_printout_);
2811 if (printout_v_landau_) {
2813 dens_type_lattice_printout_);
2816 if (printout_j_QBS_) {
2822 template <
typename Modus>
2825 for (event_ = 0; event_ < nevents_; event_++) {
2826 mainlog.info() <<
"Event " << event_;
2829 initialize_new_event();
2831 run_time_evolution();
2833 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.
bool perform_action(Action &action, int i_ensemble)
Perform the given action.
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.
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.
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
void run_time_evolution()
Runs the time evolution of an event with fixed-sized time steps or without timesteps,...
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.
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.
OutputPtr photon_output_
The Photon output.
void run_time_evolution_timestepless(Actions &actions, int i_ensemble, double end_time_propagation)
Performs all the propagations and actions during a certain time interval neglecting the influence of ...
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.
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.
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.
#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
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)
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.
EventInfo fill_event_info(const std::vector< Particles > &ensembles, double E_mean_field, double modus_impact_parameter, const ExperimentParameters ¶meters, bool projectile_target_interact)
Generate the EventInfo object which is passed to outputs_.
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.
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.