7 #ifndef SRC_INCLUDE_SMASH_EXPERIMENT_H_
8 #define SRC_INCLUDE_SMASH_EXPERIMENT_H_
40 #ifdef SMASH_USE_HEPMC
43 #ifdef SMASH_USE_RIVET
66 template <
typename T,
typename Ratio>
68 const chrono::duration<T, Ratio> &seconds) {
69 using Seconds = chrono::duration<double>;
70 using Minutes = chrono::duration<double, std::ratio<60>>;
71 using Hours = chrono::duration<double, std::ratio<60 * 60>>;
72 constexpr Minutes threshold_for_minutes{10};
73 constexpr Hours threshold_for_hours{3};
74 if (seconds < threshold_for_minutes) {
75 return out << Seconds(seconds).count() <<
" [s]";
77 if (seconds < threshold_for_hours) {
78 return out << Minutes(seconds).count() <<
" [min]";
80 return out << Hours(seconds).count() <<
" [h]";
85 static constexpr
int LMain = LogArea::Main::id;
125 const bf::path &output_path);
133 virtual void run() = 0;
141 using std::invalid_argument::invalid_argument;
145 template <
typename Modus>
147 template <
typename Modus>
174 template <
typename Modus>
250 for (
size_t i = 0; i < this->
modus_.proj_N_number(); i++)
266 for (
size_t i = this->
modus_.proj_N_number();
267 i < this->
modus_.total_N_number(); i++)
288 template <
typename Container>
290 const Container &particles_before_actions);
442 std::unique_ptr<RectangularLattice<FourVector>>
UB_lat_ =
nullptr;
448 std::unique_ptr<RectangularLattice<FourVector>>
UI3_lat_ =
nullptr;
451 std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
455 std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
459 std::unique_ptr<RectangularLattice<EnergyMomentumTensor>>
Tmn_;
615 friend std::ostream &operator<<<>(std::ostream &out,
const Experiment &e);
619 template <
typename Modus>
621 out <<
"End time: " << e.
end_time_ <<
" fm/c\n";
626 template <
typename Modus>
628 const std::string &content,
629 const bf::path &output_path,
631 logg[
LExperiment].info() <<
"Adding output " << content <<
" of format "
634 if (
format ==
"VTK" && content ==
"Particles") {
635 outputs_.emplace_back(
636 make_unique<VtkOutput>(output_path, content, out_par));
637 }
else if (
format ==
"Root") {
638 #ifdef SMASH_USE_ROOT
639 if (content ==
"Initial_Conditions") {
640 outputs_.emplace_back(
641 make_unique<RootOutput>(output_path,
"SMASH_IC", out_par));
643 outputs_.emplace_back(
644 make_unique<RootOutput>(output_path, content, out_par));
648 "Root output requested, but Root support not compiled in");
650 }
else if (
format ==
"Binary") {
651 if (content ==
"Collisions" || content ==
"Dileptons" ||
652 content ==
"Photons") {
653 outputs_.emplace_back(
654 make_unique<BinaryOutputCollisions>(output_path, content, out_par));
655 }
else if (content ==
"Particles") {
656 outputs_.emplace_back(
657 make_unique<BinaryOutputParticles>(output_path, content, out_par));
658 }
else if (content ==
"Initial_Conditions") {
659 outputs_.emplace_back(make_unique<BinaryOutputInitialConditions>(
660 output_path, content, out_par));
662 }
else if (
format ==
"Oscar1999" ||
format ==
"Oscar2013") {
663 outputs_.emplace_back(
665 }
else if (content ==
"Thermodynamics" &&
format ==
"ASCII") {
666 outputs_.emplace_back(
667 make_unique<ThermodynamicOutput>(output_path, content, out_par));
668 }
else if (content ==
"Thermodynamics" &&
format ==
"VTK") {
669 printout_lattice_td_ =
true;
670 outputs_.emplace_back(
671 make_unique<VtkOutput>(output_path, content, out_par));
672 }
else if (content ==
"Initial_Conditions" &&
format ==
"ASCII") {
673 outputs_.emplace_back(
674 make_unique<ICOutput>(output_path,
"SMASH_IC", out_par));
675 }
else if (
format ==
"HepMC") {
676 #ifdef SMASH_USE_HEPMC
677 if (content ==
"Particles") {
678 outputs_.emplace_back(make_unique<HepMcOutput>(
679 output_path,
"SMASH_HepMC_particles",
false, modus_.total_N_number(),
680 modus_.proj_N_number()));
681 }
else if (content ==
"Collisions") {
682 outputs_.emplace_back(make_unique<HepMcOutput>(
683 output_path,
"SMASH_HepMC_collisions",
true, modus_.total_N_number(),
684 modus_.proj_N_number()));
687 "HepMC only available for Particles and "
688 "Collisions content. Requested for " +
693 "HepMC output requested, but HepMC support not compiled in");
695 }
else if (content ==
"Rivet") {
696 #ifdef SMASH_USE_RIVET
698 static bool rivet_format_already_selected =
false;
700 if (rivet_format_already_selected) {
702 "Rivet output format can only be one, either YODA or YODA-full. "
703 "Only your first valid choice will be used.");
707 outputs_.emplace_back(make_unique<RivetOutput>(
708 output_path,
"SMASH_Rivet",
false, modus_.total_N_number(),
709 modus_.proj_N_number(), out_par));
710 rivet_format_already_selected =
true;
711 }
else if (
format ==
"YODA-full") {
712 outputs_.emplace_back(make_unique<RivetOutput>(
713 output_path,
"SMASH_Rivet_full",
true, modus_.total_N_number(),
714 modus_.proj_N_number(), out_par));
715 rivet_format_already_selected =
true;
718 "not one of YODA or YODA-full");
722 "Rivet output requested, but Rivet support not compiled in");
726 <<
"Unknown combination of format (" <<
format <<
") and content ("
727 << content <<
"). Fix the config.";
901 template <
typename Modus>
905 modus_(config[
"Modi"], parameters_),
907 nevents_(config.take({
"General",
"Nevents"})),
908 end_time_(config.take({
"General",
"End_Time"})),
909 delta_time_startup_(parameters_.labclock->timestep_duration()),
911 config.take({
"Collision_Term",
"Force_Decays_At_End"},
true)),
912 use_grid_(config.take({
"General",
"Use_Grid"},
true)),
915 config.take({
"General",
"Expansion_Rate"}, 0.1)),
917 config.take({
"Collision_Term",
"Dileptons",
"Decays"},
false)),
918 photons_switch_(config.take(
919 {
"Collision_Term",
"Photons",
"2to2_Scatterings"},
false)),
920 bremsstrahlung_switch_(
921 config.take({
"Collision_Term",
"Photons",
"Bremsstrahlung"},
false)),
922 IC_output_switch_(config.has_value({
"Output",
"Initial_Conditions"})),
929 throw std::invalid_argument(
930 "The stochastic criterion can only be employed for fixed time step "
935 if (dileptons_switch_) {
936 dilepton_finder_ = make_unique<DecayActionsFinderDilepton>();
938 if (photons_switch_ || bremsstrahlung_switch_) {
939 n_fractional_photons_ =
940 config.take({
"Collision_Term",
"Photons",
"Fractional_Photons"}, 100);
942 if (parameters_.two_to_one) {
943 if (parameters_.res_lifetime_factor < 0.) {
944 throw std::invalid_argument(
945 "Resonance lifetime modifier cannot be negative!");
949 "Resonance lifetime set to zero. Make sure resonances cannot "
951 "inelastically (e.g. resonance chains), else SMASH is known to "
954 action_finders_.emplace_back(
955 make_unique<DecayActionsFinder>(parameters_.res_lifetime_factor));
957 bool no_coll = config.take({
"Collision_Term",
"No_Collisions"},
false);
958 if ((parameters_.two_to_one || parameters_.included_2to2.any() ||
959 parameters_.included_multi.any() || parameters_.strings_switch) &&
961 auto scat_finder = make_unique<ScatterActionsFinder>(
962 config, parameters_, nucleon_has_interacted_, modus_.total_N_number(),
963 modus_.proj_N_number());
964 max_transverse_distance_sqr_ =
965 scat_finder->max_transverse_distance_sqr(parameters_.testparticles);
966 process_string_ptr_ = scat_finder->get_process_string_ptr();
967 action_finders_.emplace_back(std::move(scat_finder));
969 max_transverse_distance_sqr_ =
970 parameters_.maximum_cross_section / M_PI *
fm2_mb;
971 process_string_ptr_ = NULL;
973 if (modus_.is_box()) {
974 action_finders_.emplace_back(
975 make_unique<WallCrossActionsFinder>(parameters_.box_length));
977 if (IC_output_switch_) {
978 if (!modus_.is_collider()) {
979 throw std::runtime_error(
980 "Initial conditions can only be extracted in collider modus.");
983 if (config.has_value({
"Output",
"Initial_Conditions",
"Proper_Time"})) {
986 config.take({
"Output",
"Initial_Conditions",
"Proper_Time"});
989 double default_proper_time = modus_.nuclei_passing_time();
991 config.take({
"Output",
"Initial_Conditions",
"Lower_Bound"}, 0.5);
992 if (default_proper_time >= lower_bound) {
993 proper_time = default_proper_time;
996 <<
"Nuclei passing time is too short, hypersurface proper time set "
998 << lower_bound <<
" fm.";
999 proper_time = lower_bound;
1002 action_finders_.emplace_back(
1003 make_unique<HyperSurfaceCrossActionsFinder>(proper_time));
1006 if (config.has_value({
"Collision_Term",
"Pauli_Blocking"})) {
1008 pauli_blocker_ = make_unique<PauliBlocker>(
1009 config[
"Collision_Term"][
"Pauli_Blocking"], parameters_);
1013 config.take({
"Collision_Term",
"Power_Particle_Formation"},
1014 modus_.sqrt_s_NN() >= 200. ? -1. : 1.);
1050 " create OutputInterface objects");
1052 auto output_conf = config[
"Output"];
1280 <<
"Density type printed to headers: " << dens_type_;
1282 const OutputParameters output_parameters(std::move(output_conf));
1284 std::vector<std::string> output_contents = output_conf.list_upmost_nodes();
1285 for (
const auto &content : output_contents) {
1286 auto this_output_conf = output_conf[content.c_str()];
1287 const std::vector<std::string> formats = this_output_conf.take({
"Format"});
1288 if (output_path ==
"") {
1291 for (
const auto &
format : formats) {
1292 create_output(
format, content, output_path, output_parameters);
1303 if (config.has_value({
"Potentials"})) {
1306 throw std::invalid_argument(
"Can't use potentials without time steps!");
1310 <<
"Potentials don't work with frozen Fermi momenta! "
1311 "Use normal Fermi motion instead.";
1312 throw std::invalid_argument(
1313 "Can't use potentials "
1314 "with frozen Fermi momenta!");
1317 << parameters_.labclock->timestep_duration();
1319 potentials_ = make_unique<Potentials>(config[
"Potentials"], parameters_);
1378 if (config.has_value({
"Lattice"})) {
1380 const std::array<double, 3> l = config.take({
"Lattice",
"Sizes"});
1381 const std::array<int, 3>
n = config.take({
"Lattice",
"Cell_Number"});
1382 const std::array<double, 3> origin = config.take({
"Lattice",
"Origin"});
1383 const bool periodic = config.take({
"Lattice",
"Periodic"});
1385 if (printout_lattice_td_) {
1386 dens_type_lattice_printout_ = output_parameters.td_dens_type;
1387 printout_tmn_ = output_parameters.td_tmn;
1388 printout_tmn_landau_ = output_parameters.td_tmn_landau;
1389 printout_v_landau_ = output_parameters.td_v_landau;
1391 if (printout_tmn_ || printout_tmn_landau_ || printout_v_landau_) {
1392 Tmn_ = make_unique<RectangularLattice<EnergyMomentumTensor>>(
1399 if (potentials_->use_skyrme()) {
1400 jmu_B_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1402 UB_lat_ = make_unique<RectangularLattice<FourVector>>(
1405 RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
1408 if (potentials_->use_symmetry()) {
1409 jmu_I3_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1411 UI3_lat_ = make_unique<RectangularLattice<FourVector>>(
1414 RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
1419 jmu_B_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1423 jmu_I3_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1430 jmu_custom_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1433 }
else if (printout_lattice_td_) {
1435 "If you want Thermodynamic VTK output, configure a lattice for it.");
1438 if ((potentials_ !=
nullptr) && (jmu_B_lat_ ==
nullptr)) {
1440 <<
"not going to be calculated.";
1444 if (parameters_.potential_affect_threshold) {
1451 if (config.has_value({
"Forced_Thermalization"})) {
1452 Configuration &&th_conf = config[
"Forced_Thermalization"];
1453 thermalizer_ = modus_.create_grandcan_thermalizer(th_conf);
1458 seed_ = config.take({
"General",
"Randomseed"});
1462 const std::string
hline(113,
'-');
1490 uint64_t scatterings_this_interval,
1491 const QuantumNumbers &conserved_initial,
1493 double E_mean_field,
1494 double E_mean_field_initial);
1508 const Potentials &potentials,
1509 RectangularLattice<smash::DensityOnLattice> &jmu_B_lat,
1510 const ExperimentParameters ¶meters);
1527 EventInfo
fill_event_info(
const Particles &particles,
double E_mean_field,
1528 double modus_impact_parameter,
1529 const ExperimentParameters ¶meters,
1530 bool projectile_target_interact);
1532 template <
typename Modus>
1542 while (r == INT64_MIN) {
1545 seed_ = std::abs(r);
1550 if (process_string_ptr_ != NULL) {
1551 process_string_ptr_->init_pythia_hadron_rndm();
1556 if (modus_.is_collider()) {
1557 nucleon_has_interacted_.assign(modus_.total_N_number(),
false);
1561 double start_time = modus_.initial_conditions(&particles_, parameters_);
1565 modus_.impose_boundary_conditions(&particles_, outputs_);
1567 double timestep = delta_time_startup_;
1569 switch (time_step_mode_) {
1573 timestep = end_time_ - start_time;
1575 const double max_dt = modus_.max_timestep(max_transverse_distance_sqr_);
1576 if (max_dt > 0. && max_dt < timestep) {
1581 std::unique_ptr<UniformClock> clock_for_this_event;
1582 if (modus_.is_list() && (timestep < 0.0)) {
1583 throw std::runtime_error(
1584 "Timestep for the given event is negative. \n"
1585 "This might happen if the formation times of the input particles are "
1586 "larger than the specified end time of the simulation.");
1588 clock_for_this_event = make_unique<UniformClock>(start_time, timestep);
1589 parameters_.labclock = std::move(clock_for_this_event);
1592 parameters_.outputclock->reset(start_time,
true);
1594 parameters_.outputclock->remove_times_in_past(start_time);
1597 "Lab clock: t_start = ", parameters_.labclock->current_time(),
1598 ", dt = ", parameters_.labclock->timestep_duration());
1603 wall_actions_total_ = 0;
1604 previous_wall_actions_total_ = 0;
1605 interactions_total_ = 0;
1606 previous_interactions_total_ = 0;
1607 discarded_interactions_total_ = 0;
1608 total_pauli_blocked_ = 0;
1609 projectile_target_interact_ =
false;
1610 total_hypersurface_crossing_actions_ = 0;
1611 total_energy_removed_ = 0.0;
1614 logg[
LExperiment].info() <<
"Time[fm] Ekin[GeV] E_MF[GeV] ETotal[GeV] "
1615 <<
"ETot/N[GeV] D(ETot/N)[GeV] Scatt&Decays "
1616 <<
"Particles Comp.Time";
1618 double E_mean_field = 0.0;
1620 update_potentials();
1622 if ((jmu_B_lat_ !=
nullptr)) {
1627 initial_mean_field_energy_ = E_mean_field;
1629 particles_, 0u, conserved_initial_, time_start_,
1630 parameters_.labclock->current_time(), E_mean_field,
1631 initial_mean_field_energy_);
1635 parameters_, projectile_target_interact_);
1638 for (
const auto &output : outputs_) {
1639 output->at_eventstart(particles_, event_number, event_info);
1643 template <
typename Modus>
1644 template <
typename Container>
1646 Action &action,
const Container &particles_before_actions) {
1648 if (!action.
is_valid(particles_)) {
1649 discarded_interactions_total_++;
1651 " (discarded: invalid)");
1656 if (pauli_blocker_ && action.
is_pauli_blocked(particles_, *pauli_blocker_)) {
1657 total_pauli_blocked_++;
1660 if (modus_.is_collider()) {
1663 bool incoming_projectile =
false;
1664 bool incoming_target =
false;
1666 assert(incoming.id() >= 0);
1667 if (incoming.id() < modus_.total_N_number()) {
1668 nucleon_has_interacted_[incoming.id()] =
true;
1670 if (incoming.id() < modus_.proj_N_number()) {
1671 incoming_projectile =
true;
1673 if (incoming.id() >= modus_.proj_N_number() &&
1674 incoming.id() < modus_.total_N_number()) {
1675 incoming_target =
true;
1679 if (incoming_projectile & incoming_target) {
1680 projectile_target_interact_ =
true;
1685 const auto id_process =
static_cast<uint32_t
>(interactions_total_ + 1);
1686 action.
perform(&particles_, id_process);
1687 interactions_total_++;
1689 wall_actions_total_++;
1692 total_hypersurface_crossing_actions_++;
1699 constexpr
bool compute_grad =
false;
1700 const bool smearing =
true;
1702 particles_before_actions, density_param_,
1703 dens_type_, compute_grad, smearing));
1720 for (
const auto &output : outputs_) {
1721 if (!output->is_dilepton_output() && !output->is_photon_output()) {
1722 if (output->is_IC_output() &&
1724 output->at_interaction(action, rho);
1725 }
else if (!output->is_IC_output()) {
1726 output->at_interaction(action, rho);
1736 if (photons_switch_ &&
1742 constexpr
double action_time = 0.;
1744 n_fractional_photons_,
1760 photon_act.add_single_process();
1762 photon_act.perform_photons(outputs_);
1765 if (bremsstrahlung_switch_ &&
1770 constexpr
double action_time = 0.;
1773 n_fractional_photons_,
1790 brems_act.add_single_process();
1792 brems_act.perform_bremsstrahlung(outputs_);
1799 template <
typename Modus>
1803 while (parameters_.labclock->current_time() < end_time_) {
1804 const double t = parameters_.labclock->current_time();
1806 std::min(parameters_.labclock->timestep_duration(), end_time_ - t);
1807 logg[
LExperiment].debug(
"Timestepless propagation for next ", dt,
" fm/c.");
1811 thermalizer_->is_time_to_thermalize(parameters_.labclock)) {
1812 const bool ignore_cells_under_treshold =
true;
1813 thermalizer_->update_thermalizer_lattice(particles_, density_param_,
1814 ignore_cells_under_treshold);
1815 const double current_t = parameters_.labclock->current_time();
1816 thermalizer_->thermalize(particles_, current_t,
1817 parameters_.testparticles);
1820 perform_action(th_act, particles_);
1824 if (particles_.size() > 0 && action_finders_.size() > 0) {
1826 double min_cell_length = compute_min_cell_length(dt);
1830 use_grid_ ? modus_.create_grid(particles_, min_cell_length, dt)
1831 : modus_.create_grid(particles_, min_cell_length, dt,
1834 const double gcell_vol = grid.cell_volume();
1838 [&](
const ParticleList &search_list) {
1839 for (
const auto &finder : action_finders_) {
1840 actions.
insert(finder->find_actions_in_cell(
1841 search_list, dt, gcell_vol, beam_momentum_));
1844 [&](
const ParticleList &search_list,
1845 const ParticleList &neighbors_list) {
1846 for (
const auto &finder : action_finders_) {
1847 actions.
insert(finder->find_actions_with_neighbors(
1848 search_list, neighbors_list, dt, beam_momentum_));
1856 run_time_evolution_timestepless(actions);
1861 update_potentials();
1862 update_momenta(&particles_, parameters_.labclock->timestep_duration(),
1863 *potentials_, FB_lat_.get(), FI3_lat_.get());
1872 ++(*parameters_.labclock);
1880 if (!potentials_ && !parameters_.strings_switch &&
1882 std::string err_msg = conserved_initial_.report_deviations(particles_);
1883 if (!err_msg.empty()) {
1885 throw std::runtime_error(
"Violation of conserved quantities!");
1890 if (pauli_blocker_) {
1892 "Interactions: Pauli-blocked/performed = ", total_pauli_blocked_,
"/",
1893 interactions_total_ - wall_actions_total_);
1897 template <
typename Modus>
1901 if (dilepton_finder_ !=
nullptr) {
1902 for (
const auto &output : outputs_) {
1903 dilepton_finder_->shine(particles_, output.get(), dt);
1916 constexpr uint64_t max_uint32 = std::numeric_limits<uint32_t>::max();
1917 if (interactions_total >= max_uint32) {
1918 throw std::runtime_error(
"Integer overflow in total interaction number!");
1922 template <
typename Modus>
1924 const double start_time = parameters_.labclock->current_time();
1925 const double end_time =
1926 std::min(parameters_.labclock->next_time(), end_time_);
1927 double time_left = end_time - start_time;
1929 "Timestepless propagation: ",
"Actions size = ", actions.
size(),
1930 ", start time = ", start_time,
", end time = ", end_time);
1935 ActionPtr act = actions.
pop();
1936 if (!act->is_valid(particles_)) {
1937 discarded_interactions_total_++;
1939 " (discarded: invalid)");
1942 if (act->time_of_execution() > end_time) {
1944 act,
" scheduled later than end time: t_action[fm/c] = ",
1945 act->time_of_execution(),
", t_end[fm/c] = ", end_time);
1949 while (next_output_time() <= act->time_of_execution()) {
1951 next_output_time());
1952 propagate_and_shine(next_output_time());
1953 ++(*parameters_.outputclock);
1954 intermediate_output();
1959 ", action time = ", act->time_of_execution());
1960 propagate_and_shine(act->time_of_execution());
1967 act->update_incoming(particles_);
1968 const bool performed = perform_action(*act, particles_);
1978 time_left = end_time - act->time_of_execution();
1979 const ParticleList &outgoing_particles = act->outgoing_particles();
1981 const double gcell_vol = 0.0;
1982 for (
const auto &finder : action_finders_) {
1984 actions.
insert(finder->find_actions_in_cell(outgoing_particles, time_left,
1985 gcell_vol, beam_momentum_));
1987 actions.
insert(finder->find_actions_with_surrounding_particles(
1988 outgoing_particles, particles_, time_left, beam_momentum_));
1994 while (next_output_time() <= end_time) {
1996 next_output_time());
1997 propagate_and_shine(next_output_time());
1998 ++(*parameters_.outputclock);
2000 if (parameters_.outputclock->current_time() < end_time_) {
2001 intermediate_output();
2005 propagate_and_shine(end_time);
2008 template <
typename Modus>
2010 const uint64_t wall_actions_this_interval =
2011 wall_actions_total_ - previous_wall_actions_total_;
2012 previous_wall_actions_total_ = wall_actions_total_;
2013 const uint64_t interactions_this_interval = interactions_total_ -
2014 previous_interactions_total_ -
2015 wall_actions_this_interval;
2016 previous_interactions_total_ = interactions_total_;
2017 double E_mean_field = 0.0;
2020 if ((jmu_B_lat_ !=
nullptr)) {
2029 if (modus_.is_box()) {
2030 double tmp = (E_mean_field - initial_mean_field_energy_) /
2031 (E_mean_field + initial_mean_field_energy_);
2037 if (std::abs(tmp) > 0.01) {
2039 <<
"\n\n\n\t The mean field at t = "
2040 << parameters_.outputclock->current_time()
2041 <<
" [fm/c] differs from the mean field at t = 0:"
2042 <<
"\n\t\t initial_mean_field_energy_ = "
2043 << initial_mean_field_energy_ <<
" [GeV]"
2044 <<
"\n\t\t abs[(E_MF - E_MF(t=0))/(E_MF + E_MF(t=0))] = "
2046 <<
"\n\t\t E_MF/E_MF(t=0) = "
2047 << E_mean_field / initial_mean_field_energy_ <<
"\n\n";
2054 particles_, interactions_this_interval, conserved_initial_, time_start_,
2055 parameters_.outputclock->current_time(), E_mean_field,
2056 initial_mean_field_energy_);
2061 parameters_, projectile_target_interact_);
2063 if (!(modus_.is_box() && parameters_.outputclock->current_time() <
2064 modus_.equilibration_time())) {
2065 for (
const auto &output : outputs_) {
2066 if (output->is_dilepton_output() || output->is_photon_output() ||
2067 output->is_IC_output()) {
2071 output->at_intermediate_time(particles_, parameters_.outputclock,
2072 density_param_, event_info);
2075 switch (dens_type_lattice_printout_) {
2078 density_param_, particles_,
false);
2094 dens_type_lattice_printout_, density_param_,
2097 dens_type_lattice_printout_,
2100 if (printout_tmn_ || printout_tmn_landau_ || printout_v_landau_) {
2102 density_param_, particles_);
2103 if (printout_tmn_) {
2105 dens_type_lattice_printout_, *Tmn_);
2107 if (printout_tmn_landau_) {
2109 dens_type_lattice_printout_, *Tmn_);
2111 if (printout_v_landau_) {
2113 dens_type_lattice_printout_, *Tmn_);
2118 output->thermodynamics_output(*thermalizer_);
2124 template <
typename Modus>
2127 if (potentials_->use_symmetry() && jmu_I3_lat_ !=
nullptr) {
2132 if ((potentials_->use_skyrme() || potentials_->use_symmetry()) &&
2133 jmu_B_lat_ !=
nullptr) {
2136 const size_t UBlattice_size = UB_lat_->size();
2137 for (
size_t i = 0; i < UBlattice_size; i++) {
2138 auto jB = (*jmu_B_lat_)[i];
2140 std::abs(jB.density()) >
really_small ? jB.jmu_net() / jB.density()
2142 double baryon_density = jB.density();
2146 if (potentials_->use_skyrme()) {
2148 flow_four_velocity_B * potentials_->skyrme_pot(baryon_density);
2149 (*FB_lat_)[i] = potentials_->skyrme_force(
2150 baryon_density, baryon_grad_rho, baryon_dj_dt, baryon_rot_j);
2152 if (potentials_->use_symmetry() && jmu_I3_lat_ !=
nullptr) {
2153 auto jI3 = (*jmu_I3_lat_)[i];
2156 ? jI3.jmu_net() / jI3.density()
2159 flow_four_velocity_I3 *
2160 potentials_->symmetry_pot(jI3.density(), baryon_density);
2161 (*FI3_lat_)[i] = potentials_->symmetry_force(
2162 jI3.density(), jI3.grad_rho(), jI3.dj_dt(), jI3.rot_j(),
2163 baryon_density, baryon_grad_rho, baryon_dj_dt, baryon_rot_j);
2170 template <
typename Modus>
2174 uint64_t interactions_old;
2175 const auto particles_before_actions = particles_.copy_to_vector();
2179 interactions_old = interactions_total_;
2182 if (dilepton_finder_ !=
nullptr) {
2183 for (
const auto &output : outputs_) {
2184 dilepton_finder_->shine_final(particles_, output.get(),
true);
2188 for (
const auto &finder : action_finders_) {
2189 actions.
insert(finder->find_final_actions(particles_));
2193 perform_action(*actions.
pop(), particles_before_actions);
2196 }
while (interactions_total_ > interactions_old);
2199 if (dilepton_finder_ !=
nullptr) {
2200 for (
const auto &output : outputs_) {
2201 dilepton_finder_->shine_final(particles_, output.get(),
false);
2206 template <
typename Modus>
2211 double E_mean_field = 0.0;
2212 if (
likely(parameters_.labclock > 0)) {
2213 const uint64_t wall_actions_this_interval =
2214 wall_actions_total_ - previous_wall_actions_total_;
2215 const uint64_t interactions_this_interval = interactions_total_ -
2216 previous_interactions_total_ -
2217 wall_actions_this_interval;
2220 if ((jmu_B_lat_ !=
nullptr)) {
2226 particles_, interactions_this_interval, conserved_initial_, time_start_,
2227 end_time_, E_mean_field, initial_mean_field_energy_);
2228 if (IC_output_switch_ && (particles_.size() == 0)) {
2231 const double remaining_energy =
2232 conserved_initial_.momentum().x0() - total_energy_removed_;
2234 throw std::runtime_error(
2235 "There is remaining energy in the system although all particles "
2238 std::to_string(remaining_energy) +
" [GeV]");
2242 <<
"Time real: " << SystemClock::now() - time_start_;
2244 <<
"Interactions before reaching hypersurface: "
2245 << interactions_total_ - wall_actions_total_ -
2246 total_hypersurface_crossing_actions_;
2248 <<
"Total number of particles removed on hypersurface: "
2249 << total_hypersurface_crossing_actions_;
2252 const double precent_discarded =
2253 interactions_total_ > 0
2254 ?
static_cast<double>(discarded_interactions_total_) * 100.0 /
2257 std::stringstream msg_discarded;
2259 <<
"Discarded interaction number: " << discarded_interactions_total_
2260 <<
" (" << precent_discarded
2261 <<
"% of the total interaction number including wall crossings)";
2265 <<
"Time real: " << SystemClock::now() - time_start_;
2269 precent_discarded > 1.0) {
2272 << msg_discarded.str()
2273 <<
"\nThe number of discarded interactions is large, which means "
2274 "the assumption for the stochastic criterion of\n1 interaction"
2275 "per particle per timestep is probably violated. Consider "
2276 "reducing the timestep size.";
2280 << interactions_total_ - wall_actions_total_;
2284 int unformed_particles_count = 0;
2285 for (
const auto &particle : particles_) {
2286 if (particle.formation_time() > end_time_) {
2287 unformed_particles_count++;
2290 if (unformed_particles_count > 0) {
2292 "End time might be too small. ", unformed_particles_count,
2293 " unformed particles were found at the end of the evolution.");
2299 parameters_, projectile_target_interact_);
2301 for (
const auto &output : outputs_) {
2302 output->at_eventend(particles_, evt_num, event_info);
2306 template <
typename Modus>
2309 for (
int j = 0; j < nevents_; j++) {
2310 mainlog.info() <<
"Event " << j;
2313 initialize_new_event(j);
2321 if (modus_.is_collider()) {
2322 if (!modus_.cll_in_nucleus()) {
2323 nucleon_has_interacted_.assign(modus_.total_N_number(),
false);
2325 nucleon_has_interacted_.assign(modus_.total_N_number(),
true);
2331 for (
int i = 0; i < modus_.total_N_number(); i++) {
2332 const auto mass_beam = particles_.copy_to_vector()[i].effective_mass();
2333 const auto v_beam = i < modus_.proj_N_number()
2334 ? modus_.velocity_projectile()
2335 : modus_.velocity_target();
2336 const auto gamma = 1.0 / std::sqrt(1.0 - v_beam * v_beam);
2337 beam_momentum_.emplace_back(
FourVector(gamma * mass_beam, 0.0, 0.0,
2338 gamma * v_beam * mass_beam));
2342 run_time_evolution();
2344 if (force_decays_) {
2355 #endif // SRC_INCLUDE_SMASH_EXPERIMENT_H_