7 #ifndef SRC_INCLUDE_EXPERIMENT_H_
8 #define SRC_INCLUDE_EXPERIMENT_H_
58 template <
typename T,
typename Ratio>
60 const chrono::duration<T, Ratio> &seconds) {
61 using Seconds = chrono::duration<double>;
62 using Minutes = chrono::duration<double, std::ratio<60>>;
63 using Hours = chrono::duration<double, std::ratio<60 * 60>>;
64 constexpr Minutes threshold_for_minutes{10};
65 constexpr Hours threshold_for_hours{3};
66 if (seconds < threshold_for_minutes) {
67 return out << Seconds(seconds).count() <<
" [s]";
69 if (seconds < threshold_for_hours) {
70 return out << Minutes(seconds).count() <<
" [min]";
72 return out << Hours(seconds).count() <<
" [h]";
77 static constexpr
int LMain = LogArea::Main::id;
117 const bf::path &output_path);
125 virtual void run() = 0;
133 using std::invalid_argument::invalid_argument;
137 template <
typename Modus>
139 template <
typename Modus>
166 template <
typename Modus>
243 template <
typename Container>
245 const Container &particles_before_actions);
397 std::unique_ptr<RectangularLattice<FourVector>>
UB_lat_ =
nullptr;
403 std::unique_ptr<RectangularLattice<FourVector>>
UI3_lat_ =
nullptr;
406 std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
410 std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
414 std::unique_ptr<RectangularLattice<EnergyMomentumTensor>>
Tmn_;
564 friend std::ostream &operator<<<>(std::ostream &out,
const Experiment &e);
568 template <
typename Modus>
570 out <<
"End time: " << e.
end_time_ <<
" fm/c\n";
575 template <
typename Modus>
577 const std::string &content,
578 const bf::path &output_path,
580 logg[
LExperiment].info() <<
"Adding output " << content <<
" of format "
583 if (
format ==
"VTK" && content ==
"Particles") {
584 outputs_.emplace_back(
585 make_unique<VtkOutput>(output_path, content, out_par));
586 }
else if (
format ==
"Root") {
587 #ifdef SMASH_USE_ROOT
588 if (content ==
"Initial_Conditions") {
589 outputs_.emplace_back(
590 make_unique<RootOutput>(output_path,
"SMASH_IC", out_par));
592 outputs_.emplace_back(
593 make_unique<RootOutput>(output_path, content, out_par));
597 "Root output requested, but Root support not compiled in");
599 }
else if (
format ==
"Binary") {
600 if (content ==
"Collisions" || content ==
"Dileptons" ||
601 content ==
"Photons") {
602 outputs_.emplace_back(
603 make_unique<BinaryOutputCollisions>(output_path, content, out_par));
604 }
else if (content ==
"Particles") {
605 outputs_.emplace_back(
606 make_unique<BinaryOutputParticles>(output_path, content, out_par));
607 }
else if (content ==
"Initial_Conditions") {
608 outputs_.emplace_back(make_unique<BinaryOutputInitialConditions>(
609 output_path, content, out_par));
611 }
else if (
format ==
"Oscar1999" ||
format ==
"Oscar2013") {
612 outputs_.emplace_back(
614 }
else if (content ==
"Thermodynamics" &&
format ==
"ASCII") {
615 outputs_.emplace_back(
616 make_unique<ThermodynamicOutput>(output_path, content, out_par));
617 }
else if (content ==
"Thermodynamics" &&
format ==
"VTK") {
618 printout_lattice_td_ =
true;
619 outputs_.emplace_back(
620 make_unique<VtkOutput>(output_path, content, out_par));
621 }
else if (content ==
"Initial_Conditions" &&
format ==
"ASCII") {
622 outputs_.emplace_back(
623 make_unique<ICOutput>(output_path,
"SMASH_IC", out_par));
626 <<
"Unknown combination of format (" <<
format <<
") and content ("
627 << content <<
"). Fix the config.";
780 template <
typename Modus>
784 modus_(config[
"Modi"], parameters_),
786 nevents_(config.take({
"General",
"Nevents"})),
787 end_time_(config.take({
"General",
"End_Time"})),
788 delta_time_startup_(parameters_.labclock->timestep_duration()),
790 config.take({
"Collision_Term",
"Force_Decays_At_End"},
true)),
791 use_grid_(config.take({
"General",
"Use_Grid"},
true)),
794 config.take({
"General",
"Expansion_Rate"}, 0.1)),
796 config.take({
"Collision_Term",
"Dileptons",
"Decays"},
false)),
797 photons_switch_(config.take(
798 {
"Collision_Term",
"Photons",
"2to2_Scatterings"},
false)),
799 bremsstrahlung_switch_(
800 config.take({
"Collision_Term",
"Photons",
"Bremsstrahlung"},
false)),
801 IC_output_switch_(config.has_value({
"Output",
"Initial_Conditions"})),
807 if (dileptons_switch_) {
808 dilepton_finder_ = make_unique<DecayActionsFinderDilepton>();
810 if (photons_switch_ || bremsstrahlung_switch_) {
811 n_fractional_photons_ =
812 config.take({
"Collision_Term",
"Photons",
"Fractional_Photons"}, 100);
814 if (parameters_.two_to_one) {
815 if (parameters_.res_lifetime_factor < 0.) {
816 throw std::invalid_argument(
817 "Resonance lifetime modifier cannot be negative!");
821 "Resonance lifetime set to zero. Make sure resonances cannot "
823 "inelastically (e.g. resonance chains), else SMASH is known to "
826 action_finders_.emplace_back(
827 make_unique<DecayActionsFinder>(parameters_.res_lifetime_factor));
829 bool no_coll = config.take({
"Collision_Term",
"No_Collisions"},
false);
830 if ((parameters_.two_to_one || parameters_.included_2to2.any() ||
831 parameters_.strings_switch) &&
833 auto scat_finder = make_unique<ScatterActionsFinder>(
834 config, parameters_, nucleon_has_interacted_, modus_.total_N_number(),
835 modus_.proj_N_number());
836 max_transverse_distance_sqr_ =
837 scat_finder->max_transverse_distance_sqr(parameters_.testparticles);
838 process_string_ptr_ = scat_finder->get_process_string_ptr();
839 action_finders_.emplace_back(std::move(scat_finder));
842 process_string_ptr_ = NULL;
844 const double modus_l = modus_.length();
846 action_finders_.emplace_back(make_unique<WallCrossActionsFinder>(modus_l));
848 if (IC_output_switch_) {
849 if (!modus_.is_collider()) {
850 throw std::runtime_error(
851 "Initial conditions can only be extracted in collider modus.");
854 if (config.has_value({
"Output",
"Initial_Conditions",
"Proper_Time"})) {
857 config.take({
"Output",
"Initial_Conditions",
"Proper_Time"});
860 double default_proper_time = modus_.nuclei_passing_time();
862 config.take({
"Output",
"Initial_Conditions",
"Lower_Bound"}, 0.5);
863 if (default_proper_time >= lower_bound) {
864 proper_time = default_proper_time;
867 <<
"Nuclei passing time is too short, hypersurface proper time set "
869 << lower_bound <<
" fm.";
870 proper_time = lower_bound;
873 action_finders_.emplace_back(
874 make_unique<HyperSurfaceCrossActionsFinder>(proper_time));
877 if (config.has_value({
"Collision_Term",
"Pauli_Blocking"})) {
879 pauli_blocker_ = make_unique<PauliBlocker>(
880 config[
"Collision_Term"][
"Pauli_Blocking"], parameters_);
883 config.take({
"Collision_Term",
"Power_Particle_Formation"}, 1.);
920 auto output_conf = config[
"Output"];
1143 <<
"Density type printed to headers: " << dens_type_;
1145 const OutputParameters output_parameters(std::move(output_conf));
1147 std::vector<std::string> output_contents = output_conf.list_upmost_nodes();
1148 for (
const auto &content : output_contents) {
1149 auto this_output_conf = output_conf[content.c_str()];
1150 const std::vector<std::string> formats = this_output_conf.take({
"Format"});
1151 if (output_path ==
"") {
1154 for (
const auto &
format : formats) {
1155 create_output(
format, content, output_path, output_parameters);
1166 if (config.has_value({
"Potentials"})) {
1169 throw std::invalid_argument(
"Can't use potentials without time steps!");
1173 <<
"Potentials don't work with frozen Fermi momenta! "
1174 "Use normal Fermi motion instead.";
1175 throw std::invalid_argument(
1176 "Can't use potentials "
1177 "with frozen Fermi momenta!");
1180 << parameters_.labclock->timestep_duration();
1182 potentials_ = make_unique<Potentials>(config[
"Potentials"], parameters_);
1240 if (config.has_value({
"Lattice"})) {
1242 const std::array<double, 3> l = config.take({
"Lattice",
"Sizes"});
1243 const std::array<int, 3>
n = config.take({
"Lattice",
"Cell_Number"});
1244 const std::array<double, 3> origin = config.take({
"Lattice",
"Origin"});
1245 const bool periodic = config.take({
"Lattice",
"Periodic"});
1247 if (printout_lattice_td_) {
1248 dens_type_lattice_printout_ = output_parameters.td_dens_type;
1249 printout_tmn_ = output_parameters.td_tmn;
1250 printout_tmn_landau_ = output_parameters.td_tmn_landau;
1251 printout_v_landau_ = output_parameters.td_v_landau;
1253 if (printout_tmn_ || printout_tmn_landau_ || printout_v_landau_) {
1254 Tmn_ = make_unique<RectangularLattice<EnergyMomentumTensor>>(
1261 if (potentials_->use_skyrme()) {
1262 jmu_B_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1264 UB_lat_ = make_unique<RectangularLattice<FourVector>>(
1267 RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
1270 if (potentials_->use_symmetry()) {
1271 jmu_I3_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1273 UI3_lat_ = make_unique<RectangularLattice<FourVector>>(
1276 RectangularLattice<std::pair<ThreeVector, ThreeVector>>>(
1281 jmu_B_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1285 jmu_I3_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1292 jmu_custom_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1295 }
else if (printout_lattice_td_) {
1297 "If you want Thermodynamic VTK output, configure a lattice for it.");
1300 if ((potentials_ !=
nullptr) && (jmu_B_lat_ ==
nullptr)) {
1302 <<
"not going to be calculated.";
1306 if (parameters_.potential_affect_threshold) {
1313 if (config.has_value({
"Forced_Thermalization"})) {
1314 Configuration &&th_conf = config[
"Forced_Thermalization"];
1315 thermalizer_ = modus_.create_grandcan_thermalizer(th_conf);
1320 seed_ = config.take({
"General",
"Randomseed"});
1324 const std::string
hline(113,
'-');
1352 uint64_t scatterings_this_interval,
1353 const QuantumNumbers &conserved_initial,
1355 double E_mean_field,
1356 double E_mean_field_initial);
1371 const Potentials &potentials,
1372 RectangularLattice<smash::DensityOnLattice> &jmu_B_lat,
1373 const ExperimentParameters ¶meters);
1375 template <
typename Modus>
1385 while (r == INT64_MIN) {
1388 seed_ = std::abs(r);
1393 if (process_string_ptr_ != NULL) {
1394 process_string_ptr_->init_pythia_hadron_rndm();
1400 double start_time = modus_.initial_conditions(&particles_, parameters_);
1404 modus_.impose_boundary_conditions(&particles_, outputs_);
1406 double timestep = delta_time_startup_;
1408 switch (time_step_mode_) {
1412 timestep = end_time_ - start_time;
1414 const double max_dt = modus_.max_timestep(max_transverse_distance_sqr_);
1415 if (max_dt > 0. && max_dt < timestep) {
1420 std::unique_ptr<UniformClock> clock_for_this_event;
1421 if (modus_.is_list() && (timestep < 0.0)) {
1422 throw std::runtime_error(
1423 "Timestep for the given event is negative. \n"
1424 "This might happen if the formation times of the input particles are "
1425 "larger than the specified end time of the simulation.");
1427 clock_for_this_event = make_unique<UniformClock>(start_time, timestep);
1428 parameters_.labclock = std::move(clock_for_this_event);
1431 parameters_.outputclock->reset(start_time,
true);
1433 parameters_.outputclock->remove_times_in_past(start_time);
1436 "Lab clock: t_start = ", parameters_.labclock->current_time(),
1437 ", dt = ", parameters_.labclock->timestep_duration());
1442 wall_actions_total_ = 0;
1443 previous_wall_actions_total_ = 0;
1444 interactions_total_ = 0;
1445 previous_interactions_total_ = 0;
1446 total_pauli_blocked_ = 0;
1447 projectile_target_interact_ =
false;
1448 total_hypersurface_crossing_actions_ = 0;
1449 total_energy_removed_ = 0.0;
1452 logg[
LExperiment].info() <<
"Time[fm] Ekin[GeV] E_MF[GeV] ETotal[GeV] "
1453 <<
"ETot/N[GeV] D(ETot/N)[GeV] Scatt&Decays "
1454 <<
"Particles Comp.Time";
1456 double E_mean_field = 0.0;
1458 update_potentials();
1460 if ((jmu_B_lat_ !=
nullptr)) {
1465 initial_mean_field_energy_ = E_mean_field;
1467 particles_, 0u, conserved_initial_, time_start_,
1468 parameters_.labclock->current_time(), E_mean_field,
1469 initial_mean_field_energy_);
1472 template <
typename Modus>
1473 template <
typename Container>
1475 Action &action,
const Container &particles_before_actions) {
1477 if (!action.
is_valid(particles_)) {
1479 " (discarded: invalid)");
1484 if (pauli_blocker_ && action.
is_pauli_blocked(particles_, *pauli_blocker_)) {
1485 total_pauli_blocked_++;
1488 if (modus_.is_collider()) {
1491 bool incoming_projectile =
false;
1492 bool incoming_target =
false;
1494 assert(incoming.id() >= 0);
1495 if (incoming.id() < modus_.total_N_number()) {
1496 nucleon_has_interacted_[incoming.id()] =
true;
1498 if (incoming.id() < modus_.proj_N_number()) {
1499 incoming_projectile =
true;
1501 if (incoming.id() >= modus_.proj_N_number() &&
1502 incoming.id() < modus_.total_N_number()) {
1503 incoming_target =
true;
1507 if (incoming_projectile & incoming_target) {
1508 projectile_target_interact_ =
true;
1513 const auto id_process = static_cast<uint32_t>(interactions_total_ + 1);
1514 action.
perform(&particles_, id_process);
1515 interactions_total_++;
1517 wall_actions_total_++;
1520 total_hypersurface_crossing_actions_++;
1527 constexpr
bool compute_grad =
false;
1528 const bool smearing =
true;
1530 particles_before_actions, density_param_,
1531 dens_type_, compute_grad, smearing));
1548 for (
const auto &output : outputs_) {
1549 if (!output->is_dilepton_output() && !output->is_photon_output()) {
1550 if (output->is_IC_output() &&
1552 output->at_interaction(action, rho);
1553 }
else if (!output->is_IC_output()) {
1554 output->at_interaction(action, rho);
1564 if (photons_switch_ &&
1570 constexpr
double action_time = 0.;
1572 n_fractional_photons_,
1588 photon_act.add_single_process();
1590 photon_act.perform_photons(outputs_);
1593 if (bremsstrahlung_switch_ &&
1598 constexpr
double action_time = 0.;
1601 n_fractional_photons_,
1618 brems_act.add_single_process();
1620 brems_act.perform_bremsstrahlung(outputs_);
1627 template <
typename Modus>
1631 while (parameters_.labclock->current_time() < end_time_) {
1632 const double t = parameters_.labclock->current_time();
1634 std::min(parameters_.labclock->timestep_duration(), end_time_ - t);
1635 logg[
LExperiment].debug(
"Timestepless propagation for next ", dt,
" fm/c.");
1639 thermalizer_->is_time_to_thermalize(parameters_.labclock)) {
1640 const bool ignore_cells_under_treshold =
true;
1641 thermalizer_->update_thermalizer_lattice(particles_, density_param_,
1642 ignore_cells_under_treshold);
1643 const double current_t = parameters_.labclock->current_time();
1644 thermalizer_->thermalize(particles_, current_t,
1645 parameters_.testparticles);
1648 perform_action(th_act, particles_);
1652 if (particles_.size() > 0 && action_finders_.size() > 0) {
1654 double min_cell_length = compute_min_cell_length(dt);
1658 use_grid_ ? modus_.create_grid(particles_, min_cell_length, dt)
1659 : modus_.create_grid(particles_, min_cell_length, dt,
1662 const double cell_vol = grid.cell_volume();
1666 [&](
const ParticleList &search_list) {
1667 for (
const auto &finder : action_finders_) {
1668 actions.
insert(finder->find_actions_in_cell(
1669 search_list, dt, cell_vol, beam_momentum_));
1672 [&](
const ParticleList &search_list,
1673 const ParticleList &neighbors_list) {
1674 for (
const auto &finder : action_finders_) {
1675 actions.
insert(finder->find_actions_with_neighbors(
1676 search_list, neighbors_list, dt, beam_momentum_));
1684 run_time_evolution_timestepless(actions);
1689 update_potentials();
1690 update_momenta(&particles_, parameters_.labclock->timestep_duration(),
1691 *potentials_, FB_lat_.get(), FI3_lat_.get());
1700 ++(*parameters_.labclock);
1708 if (!potentials_ && !parameters_.strings_switch &&
1710 std::string err_msg = conserved_initial_.report_deviations(particles_);
1711 if (!err_msg.empty()) {
1713 throw std::runtime_error(
"Violation of conserved quantities!");
1718 if (pauli_blocker_) {
1720 "Interactions: Pauli-blocked/performed = ", total_pauli_blocked_,
"/",
1721 interactions_total_ - wall_actions_total_);
1725 template <
typename Modus>
1729 if (dilepton_finder_ !=
nullptr) {
1730 for (
const auto &output : outputs_) {
1731 dilepton_finder_->shine(particles_, output.get(), dt);
1744 constexpr uint64_t max_uint32 = std::numeric_limits<uint32_t>::max();
1745 if (interactions_total >= max_uint32) {
1746 throw std::runtime_error(
"Integer overflow in total interaction number!");
1750 template <
typename Modus>
1752 const double start_time = parameters_.labclock->current_time();
1753 const double end_time =
1754 std::min(parameters_.labclock->next_time(), end_time_);
1755 double time_left = end_time - start_time;
1757 "Timestepless propagation: ",
"Actions size = ", actions.
size(),
1758 ", start time = ", start_time,
", end time = ", end_time);
1763 ActionPtr act = actions.
pop();
1764 if (!act->is_valid(particles_)) {
1766 " (discarded: invalid)");
1769 if (act->time_of_execution() > end_time) {
1771 act,
" scheduled later than end time: t_action[fm/c] = ",
1772 act->time_of_execution(),
", t_end[fm/c] = ", end_time);
1776 while (next_output_time() <= act->time_of_execution()) {
1778 next_output_time());
1779 propagate_and_shine(next_output_time());
1780 ++(*parameters_.outputclock);
1781 intermediate_output();
1786 ", action time = ", act->time_of_execution());
1787 propagate_and_shine(act->time_of_execution());
1794 act->update_incoming(particles_);
1795 const bool performed = perform_action(*act, particles_);
1805 time_left = end_time - act->time_of_execution();
1806 const ParticleList &outgoing_particles = act->outgoing_particles();
1808 const double cell_vol = 0.0;
1809 for (
const auto &finder : action_finders_) {
1811 actions.
insert(finder->find_actions_in_cell(outgoing_particles, time_left,
1812 cell_vol, beam_momentum_));
1814 actions.
insert(finder->find_actions_with_surrounding_particles(
1815 outgoing_particles, particles_, time_left, beam_momentum_));
1821 while (next_output_time() <= end_time) {
1823 next_output_time());
1824 propagate_and_shine(next_output_time());
1825 ++(*parameters_.outputclock);
1827 if (parameters_.outputclock->current_time() < end_time_) {
1828 intermediate_output();
1832 propagate_and_shine(end_time);
1835 template <
typename Modus>
1837 const uint64_t wall_actions_this_interval =
1838 wall_actions_total_ - previous_wall_actions_total_;
1839 previous_wall_actions_total_ = wall_actions_total_;
1840 const uint64_t interactions_this_interval = interactions_total_ -
1841 previous_interactions_total_ -
1842 wall_actions_this_interval;
1843 previous_interactions_total_ = interactions_total_;
1844 double E_mean_field = 0.0;
1847 if ((jmu_B_lat_ !=
nullptr)) {
1856 if (modus_.length() > 0.0) {
1857 double tmp = (E_mean_field - initial_mean_field_energy_) /
1858 (E_mean_field + initial_mean_field_energy_);
1864 if (std::abs(tmp) > 0.01) {
1866 <<
"\n\n\n\t The mean field at t = "
1867 << parameters_.outputclock->current_time()
1868 <<
" [fm/c] differs from the mean field at t = 0:"
1869 <<
"\n\t\t initial_mean_field_energy_ = "
1870 << initial_mean_field_energy_ <<
" [GeV]"
1871 <<
"\n\t\t abs[(E_MF - E_MF(t=0))/(E_MF + E_MF(t=0))] = "
1873 <<
"\n\t\t E_MF/E_MF(t=0) = "
1874 << E_mean_field / initial_mean_field_energy_ <<
"\n\n";
1881 particles_, interactions_this_interval, conserved_initial_, time_start_,
1882 parameters_.outputclock->current_time(), E_mean_field,
1883 initial_mean_field_energy_);
1886 if (!(modus_.is_box() && parameters_.outputclock->current_time() <
1887 modus_.equilibration_time())) {
1888 for (
const auto &output : outputs_) {
1889 if (output->is_dilepton_output() || output->is_photon_output() ||
1890 output->is_IC_output()) {
1894 output->at_intermediate_time(particles_, parameters_.outputclock,
1898 switch (dens_type_lattice_printout_) {
1901 density_param_, particles_,
false);
1917 dens_type_lattice_printout_, density_param_,
1920 dens_type_lattice_printout_,
1923 if (printout_tmn_ || printout_tmn_landau_ || printout_v_landau_) {
1925 density_param_, particles_);
1926 if (printout_tmn_) {
1928 dens_type_lattice_printout_, *Tmn_);
1930 if (printout_tmn_landau_) {
1932 dens_type_lattice_printout_, *Tmn_);
1934 if (printout_v_landau_) {
1936 dens_type_lattice_printout_, *Tmn_);
1941 output->thermodynamics_output(*thermalizer_);
1947 template <
typename Modus>
1950 if (potentials_->use_symmetry() && jmu_I3_lat_ !=
nullptr) {
1955 if ((potentials_->use_skyrme() || potentials_->use_symmetry()) &&
1956 jmu_B_lat_ !=
nullptr) {
1959 const size_t UBlattice_size = UB_lat_->size();
1960 assert(UBlattice_size == UI3_lat_->size());
1961 for (
size_t i = 0; i < UBlattice_size; i++) {
1962 auto jB = (*jmu_B_lat_)[i];
1964 std::abs(jB.density()) >
really_small ? jB.jmu_net() / jB.density()
1966 double baryon_density = jB.density();
1970 if (potentials_->use_skyrme()) {
1972 flow_four_velocity_B * potentials_->skyrme_pot(baryon_density);
1973 (*FB_lat_)[i] = potentials_->skyrme_force(
1974 baryon_density, baryon_grad_rho, baryon_dj_dt, baryon_rot_j);
1976 if (potentials_->use_symmetry() && jmu_I3_lat_ !=
nullptr) {
1977 auto jI3 = (*jmu_I3_lat_)[i];
1980 ? jI3.jmu_net() / jI3.density()
1983 flow_four_velocity_I3 *
1984 potentials_->symmetry_pot(jI3.density(), baryon_density);
1985 (*FI3_lat_)[i] = potentials_->symmetry_force(
1986 jI3.density(), jI3.grad_rho(), jI3.dj_dt(), jI3.rot_j(),
1987 baryon_density, baryon_grad_rho, baryon_dj_dt, baryon_rot_j);
1994 template <
typename Modus>
1998 uint64_t interactions_old;
1999 const auto particles_before_actions = particles_.copy_to_vector();
2003 interactions_old = interactions_total_;
2006 if (dilepton_finder_ !=
nullptr) {
2007 for (
const auto &output : outputs_) {
2008 dilepton_finder_->shine_final(particles_, output.get(),
true);
2012 for (
const auto &finder : action_finders_) {
2013 actions.
insert(finder->find_final_actions(particles_));
2017 perform_action(*actions.
pop(), particles_before_actions);
2020 }
while (interactions_total_ > interactions_old);
2023 if (dilepton_finder_ !=
nullptr) {
2024 for (
const auto &output : outputs_) {
2025 dilepton_finder_->shine_final(particles_, output.get(),
false);
2030 template <
typename Modus>
2035 if (
likely(parameters_.labclock > 0)) {
2036 const uint64_t wall_actions_this_interval =
2037 wall_actions_total_ - previous_wall_actions_total_;
2038 const uint64_t interactions_this_interval = interactions_total_ -
2039 previous_interactions_total_ -
2040 wall_actions_this_interval;
2041 double E_mean_field = 0.0;
2044 if ((jmu_B_lat_ !=
nullptr)) {
2050 particles_, interactions_this_interval, conserved_initial_, time_start_,
2051 end_time_, E_mean_field, initial_mean_field_energy_);
2052 if (IC_output_switch_ && (particles_.size() == 0)) {
2055 const double remaining_energy =
2056 conserved_initial_.momentum().x0() - total_energy_removed_;
2058 throw std::runtime_error(
2059 "There is remaining energy in the system although all particles "
2062 std::to_string(remaining_energy) +
" [GeV]");
2066 <<
"Time real: " << SystemClock::now() - time_start_;
2068 <<
"Interactions before reaching hypersurface: "
2069 << interactions_total_ - wall_actions_total_ -
2070 total_hypersurface_crossing_actions_;
2072 <<
"Total number of particles removed on hypersurface: "
2073 << total_hypersurface_crossing_actions_;
2078 <<
"Time real: " << SystemClock::now() - time_start_;
2080 << interactions_total_ - wall_actions_total_;
2084 int unformed_particles_count = 0;
2085 for (
const auto &particle : particles_) {
2086 if (particle.formation_time() > end_time_) {
2087 unformed_particles_count++;
2090 if (unformed_particles_count > 0) {
2092 "End time might be too small. ", unformed_particles_count,
2093 " unformed particles were found at the end of the evolution.");
2097 for (
const auto &output : outputs_) {
2098 output->at_eventend(particles_, evt_num, modus_.impact_parameter(),
2099 !projectile_target_interact_);
2103 template <
typename Modus>
2106 for (
int j = 0; j < nevents_; j++) {
2107 mainlog.info() <<
"Event " << j;
2110 initialize_new_event();
2118 if (modus_.is_collider()) {
2119 if (!modus_.cll_in_nucleus()) {
2120 nucleon_has_interacted_.assign(modus_.total_N_number(),
false);
2122 nucleon_has_interacted_.assign(modus_.total_N_number(),
true);
2128 for (
int i = 0; i < modus_.total_N_number(); i++) {
2129 const auto mass_beam = particles_.copy_to_vector()[i].effective_mass();
2130 const auto v_beam = i < modus_.proj_N_number()
2131 ? modus_.velocity_projectile()
2132 : modus_.velocity_target();
2133 const auto gamma = 1.0 / std::sqrt(1.0 - v_beam * v_beam);
2134 beam_momentum_.emplace_back(
FourVector(gamma * mass_beam, 0.0, 0.0,
2135 gamma * v_beam * mass_beam));
2140 for (
const auto &output : outputs_) {
2141 output->at_eventstart(particles_, j);
2144 run_time_evolution();
2146 if (force_decays_) {
2157 #endif // SRC_INCLUDE_EXPERIMENT_H_