7 #ifndef SRC_INCLUDE_EXPERIMENT_H_ 8 #define SRC_INCLUDE_EXPERIMENT_H_ 55 template <
typename T,
typename Ratio>
57 const chrono::duration<T, Ratio> &seconds) {
58 using Seconds = chrono::duration<double>;
59 using Minutes = chrono::duration<double, std::ratio<60>>;
60 using Hours = chrono::duration<double, std::ratio<60 * 60>>;
61 constexpr Minutes threshold_for_minutes{10};
62 constexpr Hours threshold_for_hours{3};
63 if (seconds < threshold_for_minutes) {
64 return out << Seconds(seconds).count() <<
" [s]";
66 if (seconds < threshold_for_hours) {
67 return out << Minutes(seconds).count() <<
" [min]";
69 return out << Hours(seconds).count() <<
" [h]";
111 static std::unique_ptr<ExperimentBase> create(
Configuration config,
112 const bf::path &output_path);
120 virtual void run() = 0;
128 using std::invalid_argument::invalid_argument;
132 template <
typename Modus>
134 template <
typename Modus>
135 std::ostream &operator<<(std::ostream &out, const Experiment<Modus> &e);
161 template <
typename Modus>
194 void initialize_new_event();
202 void run_time_evolution();
205 void do_final_decays();
212 void final_output(
const int evt_num);
238 template <
typename Container>
239 bool perform_action(
Action &action,
240 const Container &particles_before_actions);
249 void create_output(
const std::string &
format,
const std::string &content,
258 void propagate_and_shine(
double to_time);
272 void run_time_evolution_timestepless(
Actions &actions);
275 void intermediate_output();
278 void update_potentials();
289 return std::sqrt(4 * dt * dt + max_transverse_distance_sqr_);
294 return parameters_.outputclock.next_time();
345 std::vector<bool> nucleon_has_interacted_ = {};
352 std::vector<FourVector> beam_momentum_ = {};
364 int n_fractional_photons_ = 100;
388 std::unique_ptr<RectangularLattice<FourVector>> UB_lat_ =
nullptr;
394 std::unique_ptr<RectangularLattice<FourVector>> UI3_lat_ =
nullptr;
397 std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
401 std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector>>>
405 std::unique_ptr<RectangularLattice<EnergyMomentumTensor>>
Tmn_;
408 bool printout_tmn_ =
false;
411 bool printout_tmn_landau_ =
false;
414 bool printout_v_landau_ =
false;
417 bool printout_lattice_td_ =
false;
476 double max_transverse_distance_sqr_ = std::numeric_limits<double>::max();
497 uint64_t interactions_total_ = 0;
503 uint64_t previous_interactions_total_ = 0;
509 uint64_t wall_actions_total_ = 0;
515 uint64_t previous_wall_actions_total_ = 0;
521 uint64_t total_pauli_blocked_ = 0;
531 friend std::ostream &operator<<<>(std::ostream &out,
const Experiment &e);
535 template <
typename Modus>
536 std::ostream &operator<<(std::ostream &out, const Experiment<Modus> &e) {
537 out <<
"End time: " << e.end_time_ <<
" fm/c\n";
542 template <
typename Modus>
544 const std::string &content,
545 const bf::path &output_path,
547 const auto &log = logger<LogArea::Experiment>();
548 log.info() <<
"Adding output " << content <<
" of format " << format
551 if (format ==
"VTK" && content ==
"Particles") {
552 outputs_.emplace_back(
553 make_unique<VtkOutput>(output_path, content, out_par));
554 }
else if (format ==
"Root") {
555 #ifdef SMASH_USE_ROOT 556 outputs_.emplace_back(
557 make_unique<RootOutput>(output_path, content, out_par));
559 log.error(
"Root output requested, but Root support not compiled in");
561 }
else if (format ==
"Binary") {
562 if (content ==
"Collisions" || content ==
"Dileptons" ||
563 content ==
"Photons") {
564 outputs_.emplace_back(
565 make_unique<BinaryOutputCollisions>(output_path, content, out_par));
566 }
else if (content ==
"Particles") {
567 outputs_.emplace_back(
568 make_unique<BinaryOutputParticles>(output_path, content, out_par));
570 }
else if (format ==
"Oscar1999" || format ==
"Oscar2013") {
571 outputs_.emplace_back(
573 }
else if (content ==
"Thermodynamics" && format ==
"ASCII") {
574 outputs_.emplace_back(
575 make_unique<ThermodynamicOutput>(output_path, content, out_par));
576 }
else if (content ==
"Thermodynamics" && format ==
"VTK") {
577 printout_lattice_td_ =
true;
578 outputs_.emplace_back(
579 make_unique<VtkOutput>(output_path, content, out_par));
581 log.error() <<
"Unknown combination of format (" << format
582 <<
") and content (" << content <<
"). Fix the config.";
708 template <
typename Modus>
712 modus_(config[
"Modi"], parameters_),
714 nevents_(config.
take({
"General",
"Nevents"})),
715 end_time_(config.
take({
"General",
"End_Time"})),
716 delta_time_startup_(parameters_.labclock.timestep_duration()),
718 config.
take({
"Collision_Term",
"Force_Decays_At_End"},
true)),
719 use_grid_(config.
take({
"General",
"Use_Grid"},
true)),
722 config.
take({
"General",
"Expansion_Rate"}, 0.1)),
723 dileptons_switch_(config.
has_value({
"Output",
"Dileptons"})),
724 photons_switch_(config.
has_value({
"Output",
"Photons"})),
727 const auto &log = logger<LogArea::Experiment>();
731 if (dileptons_switch_) {
732 dilepton_finder_ = make_unique<DecayActionsFinderDilepton>();
734 if (parameters_.photons_switch) {
735 n_fractional_photons_ = config.
take({
"Output",
"Photons",
"Fractions"});
737 if (parameters_.two_to_one) {
738 action_finders_.emplace_back(make_unique<DecayActionsFinder>());
740 bool no_coll = config.
take({
"Collision_Term",
"No_Collisions"},
false);
741 if ((parameters_.two_to_one || parameters_.included_2to2.any() ||
742 parameters_.strings_switch) &&
744 auto scat_finder = make_unique<ScatterActionsFinder>(
745 config, parameters_, nucleon_has_interacted_, modus_.total_N_number(),
746 modus_.proj_N_number());
747 max_transverse_distance_sqr_ =
748 scat_finder->max_transverse_distance_sqr(parameters_.testparticles);
749 process_string_ptr_ = scat_finder->get_process_string_ptr();
750 action_finders_.emplace_back(std::move(scat_finder));
753 process_string_ptr_ = NULL;
755 const double modus_l = modus_.length();
757 action_finders_.emplace_back(make_unique<WallCrossActionsFinder>(modus_l));
760 if (config.
has_value({
"Collision_Term",
"Pauli_Blocking"})) {
761 log.info() <<
"Pauli blocking is ON.";
762 pauli_blocker_ = make_unique<PauliBlocker>(
763 config[
"Collision_Term"][
"Pauli_Blocking"], parameters_);
765 ParticleData::formation_power_ =
766 config.
take({
"Collision_Term",
"Power_Particle_Formation"}, 1.);
804 auto output_conf = config[
"Output"];
1024 dens_type_ = config.
take({
"Output",
"Density_Type"}, DensityType::None);
1025 log.debug() <<
"Density type printed to headers: " << dens_type_;
1029 std::vector<std::string> output_contents = output_conf.list_upmost_nodes();
1030 for (
const auto &content : output_contents) {
1031 auto this_output_conf = output_conf[content.c_str()];
1032 std::vector<std::string> formats = this_output_conf.take({
"Format"});
1033 for (
const auto &
format : formats) {
1034 create_output(
format, content, output_path, output_parameters);
1047 log.error() <<
"Potentials only work with time steps!";
1048 throw std::invalid_argument(
"Can't use potentials without time steps!");
1051 log.error() <<
"Potentials don't work with frozen Fermi momenta! " 1052 "Use normal Fermi motion instead.";
1053 throw std::invalid_argument(
1054 "Can't use potentials " 1055 "with frozen Fermi momenta!");
1057 log.info() <<
"Potentials are ON. Timestep is " 1058 << parameters_.labclock.timestep_duration();
1060 potentials_ = make_unique<Potentials>(config[
"Potentials"], parameters_);
1120 const std::array<double, 3> l = config.
take({
"Lattice",
"Sizes"});
1121 const std::array<int, 3>
n = config.
take({
"Lattice",
"Cell_Number"});
1122 const std::array<double, 3> origin = config.
take({
"Lattice",
"Origin"});
1123 const bool periodic = config.
take({
"Lattice",
"Periodic"});
1125 if (printout_lattice_td_) {
1126 dens_type_lattice_printout_ = output_parameters.
td_dens_type;
1127 printout_tmn_ = output_parameters.
td_tmn;
1129 printout_v_landau_ = output_parameters.
td_v_landau;
1131 if (printout_tmn_ || printout_tmn_landau_ || printout_v_landau_) {
1132 Tmn_ = make_unique<RectangularLattice<EnergyMomentumTensor>>(
1133 l,
n, origin, periodic, LatticeUpdate::AtOutput);
1139 if (potentials_->use_skyrme()) {
1140 jmu_B_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1141 LatticeUpdate::EveryTimestep);
1142 UB_lat_ = make_unique<RectangularLattice<FourVector>>(
1143 l,
n, origin, periodic, LatticeUpdate::EveryTimestep);
1146 l,
n, origin, periodic, LatticeUpdate::EveryTimestep);
1148 if (potentials_->use_symmetry()) {
1149 jmu_I3_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1150 LatticeUpdate::EveryTimestep);
1151 UI3_lat_ = make_unique<RectangularLattice<FourVector>>(
1152 l,
n, origin, periodic, LatticeUpdate::EveryTimestep);
1155 l,
n, origin, periodic, LatticeUpdate::EveryTimestep);
1158 if (dens_type_lattice_printout_ == DensityType::Baryon) {
1159 jmu_B_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1160 LatticeUpdate::AtOutput);
1162 if (dens_type_lattice_printout_ == DensityType::BaryonicIsospin) {
1163 jmu_I3_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1164 LatticeUpdate::AtOutput);
1167 if (dens_type_lattice_printout_ != DensityType::None &&
1168 dens_type_lattice_printout_ != DensityType::BaryonicIsospin &&
1169 dens_type_lattice_printout_ != DensityType::Baryon) {
1170 jmu_custom_lat_ = make_unique<DensityLattice>(l,
n, origin, periodic,
1171 LatticeUpdate::AtOutput);
1173 }
else if (printout_lattice_td_) {
1175 "If you want Thermodynamic VTK output, configure a lattice for it.");
1179 if (parameters_.potential_affect_threshold) {
1186 if (config.
has_value({
"Forced_Thermalization"})) {
1188 thermalizer_ = modus_.create_grandcan_thermalizer(th_conf);
1193 seed_ = config.
take({
"General",
"Randomseed"});
1197 const std::string
hline(67,
'-');
1199 template <
typename Modus>
1201 const auto &log = logger<LogArea::Experiment>();
1204 log.info() <<
"random number seed: " << seed_;
1211 while (r == INT64_MIN) {
1214 seed_ = std::abs(r);
1219 if (process_string_ptr_ != NULL) {
1220 process_string_ptr_->init_pythia_hadron_rndm();
1226 double start_time = modus_.initial_conditions(&particles_, parameters_);
1230 modus_.impose_boundary_conditions(&particles_, outputs_);
1232 double timestep = delta_time_startup_;
1234 switch (time_step_mode_) {
1238 timestep = end_time_ - start_time;
1240 const double max_dt = modus_.max_timestep(max_transverse_distance_sqr_);
1241 if (max_dt > 0. && max_dt < timestep) {
1246 Clock clock_for_this_event(start_time, timestep);
1247 parameters_.labclock = std::move(clock_for_this_event);
1250 const double dt_output = parameters_.outputclock.timestep_duration();
1251 const double zeroth_output_time =
1252 std::floor(start_time / dt_output) * dt_output;
1253 Clock output_clock(zeroth_output_time, dt_output);
1254 parameters_.outputclock = std::move(output_clock);
1256 log.debug(
"Lab clock: t_start = ", parameters_.labclock.current_time(),
1257 ", dt = ", parameters_.labclock.timestep_duration());
1258 log.debug(
"Output clock: t_start = ", parameters_.outputclock.current_time(),
1259 ", dt = ", parameters_.outputclock.timestep_duration());
1264 wall_actions_total_ = 0;
1265 previous_wall_actions_total_ = 0;
1266 interactions_total_ = 0;
1267 previous_interactions_total_ = 0;
1268 total_pauli_blocked_ = 0;
1270 log.info() <<
hline;
1271 log.info() <<
"Time [fm] Ediff [GeV] Scatt.|Decays " 1273 log.info() <<
hline;
1276 template <
typename Modus>
1277 template <
typename Container>
1279 Action &action,
const Container &particles_before_actions) {
1280 const auto &log = logger<LogArea::Experiment>();
1282 if (!action.
is_valid(particles_)) {
1283 log.debug(~
einhard::DRed(),
"✘ ", action,
" (discarded: invalid)");
1287 log.debug(
"Process Type is: ", action.
get_type());
1288 if (pauli_blocker_ && action.
is_pauli_blocked(particles_, *pauli_blocker_)) {
1289 total_pauli_blocked_++;
1292 if (modus_.is_collider()) {
1296 assert(incoming.id() >= 0);
1297 if (incoming.id() < modus_.total_N_number()) {
1298 nucleon_has_interacted_[incoming.id()] =
true;
1304 const auto id_process =
static_cast<uint32_t
>(interactions_total_ + 1);
1305 action.
perform(&particles_, id_process);
1306 interactions_total_++;
1307 if (action.
get_type() == ProcessType::Wall) {
1308 wall_actions_total_++;
1312 if (dens_type_ != DensityType::None) {
1314 constexpr
bool compute_grad =
false;
1315 const bool smearing =
true;
1317 particles_before_actions, density_param_,
1318 dens_type_, compute_grad, smearing));
1335 for (
const auto &output : outputs_) {
1336 if (!output->is_dilepton_output() && !output->is_photon_output()) {
1337 output->at_interaction(action, rho);
1346 if (photons_switch_ &&
1348 ScatterActionPhoton::is_kinematically_possible(
1352 constexpr
double action_time = 0.;
1354 n_fractional_photons_,
1370 photon_act.add_single_process();
1372 photon_act.perform_photons(outputs_);
1399 uint64_t scatterings_this_interval,
1403 template <
typename Modus>
1407 const auto &log = logger<LogArea::Experiment>();
1411 parameters_.labclock.current_time());
1413 while (parameters_.labclock.current_time() < end_time_) {
1414 const double t = parameters_.labclock.current_time();
1416 std::min(parameters_.labclock.timestep_duration(), end_time_ - t);
1417 log.debug(
"Timestepless propagation for next ", dt,
" fm/c.");
1421 thermalizer_->is_time_to_thermalize(parameters_.labclock)) {
1422 const bool ignore_cells_under_treshold =
true;
1423 thermalizer_->update_thermalizer_lattice(particles_, density_param_,
1424 ignore_cells_under_treshold);
1425 const double current_t = parameters_.labclock.current_time();
1426 thermalizer_->thermalize(particles_, current_t,
1427 parameters_.testparticles);
1430 perform_action(th_act, particles_);
1435 double min_cell_length = compute_min_cell_length(dt);
1436 log.debug(
"Creating grid with minimal cell length ", min_cell_length);
1437 const auto &grid = use_grid_
1438 ? modus_.create_grid(particles_, min_cell_length, dt)
1439 : modus_.create_grid(particles_, min_cell_length, dt,
1440 CellSizeStrategy::Largest);
1444 [&](
const ParticleList &search_list) {
1445 for (
const auto &finder : action_finders_) {
1446 actions.
insert(finder->find_actions_in_cell(search_list, dt));
1449 [&](
const ParticleList &search_list,
1450 const ParticleList &neighbors_list) {
1451 for (
const auto &finder : action_finders_) {
1452 actions.
insert(finder->find_actions_with_neighbors(
1453 search_list, neighbors_list, dt));
1460 run_time_evolution_timestepless(actions);
1465 update_potentials();
1466 update_momenta(&particles_, parameters_.labclock.timestep_duration(),
1467 *potentials_, FB_lat_.get(), FI3_lat_.get());
1476 ++parameters_.labclock;
1484 if (!potentials_ && !parameters_.strings_switch &&
1486 std::string err_msg = conserved_initial_.report_deviations(particles_);
1487 if (!err_msg.empty()) {
1488 log.error() << err_msg;
1489 throw std::runtime_error(
"Violation of conserved quantities!");
1494 if (pauli_blocker_) {
1495 log.info(
"Interactions: Pauli-blocked/performed = ", total_pauli_blocked_,
1496 "/", interactions_total_ - wall_actions_total_);
1500 template <
typename Modus>
1504 if (dilepton_finder_ !=
nullptr) {
1505 for (
const auto &output : outputs_) {
1506 dilepton_finder_->shine(particles_, output.get(), dt);
1519 constexpr uint64_t max_uint32 = std::numeric_limits<uint32_t>::max();
1520 if (interactions_total >= max_uint32) {
1521 throw std::runtime_error(
"Integer overflow in total interaction number!");
1525 template <
typename Modus>
1527 const auto &log = logger<LogArea::Experiment>();
1529 const double start_time = parameters_.labclock.current_time();
1530 const double end_time = std::min(parameters_.labclock.next_time(), end_time_);
1531 double time_left = end_time - start_time;
1532 log.debug(
"Timestepless propagation: ",
"Actions size = ", actions.
size(),
1533 ", start time = ", start_time,
", end time = ", end_time);
1538 ActionPtr act = actions.
pop();
1539 if (!act->is_valid(particles_)) {
1540 log.debug(~
einhard::DRed(),
"✘ ", act,
" (discarded: invalid)");
1543 if (act->time_of_execution() > end_time) {
1544 log.error(act,
" scheduled later than end time: t_action[fm/c] = ",
1545 act->time_of_execution(),
", t_end[fm/c] = ", end_time);
1549 while (next_output_time() <= act->time_of_execution()) {
1550 log.debug(
"Propagating until output time: ", next_output_time());
1551 propagate_and_shine(next_output_time());
1552 ++parameters_.outputclock;
1553 intermediate_output();
1557 log.debug(
"Propagating until next action ", act,
1558 ", action time = ", act->time_of_execution());
1559 propagate_and_shine(act->time_of_execution());
1566 act->update_incoming(particles_);
1568 const bool performed = perform_action(*act, particles_);
1578 time_left = end_time - act->time_of_execution();
1579 const ParticleList &outgoing_particles = act->outgoing_particles();
1580 for (
const auto &finder : action_finders_) {
1583 finder->find_actions_in_cell(outgoing_particles, time_left));
1585 actions.
insert(finder->find_actions_with_surrounding_particles(
1586 outgoing_particles, particles_, time_left));
1592 while (next_output_time() <= end_time) {
1593 log.debug(
"Propagating until output time: ", next_output_time());
1594 propagate_and_shine(next_output_time());
1595 ++parameters_.outputclock;
1597 if (parameters_.outputclock.current_time() < end_time_) {
1598 intermediate_output();
1602 log.debug(
"Propagating to time ", end_time);
1603 propagate_and_shine(end_time);
1606 template <
typename Modus>
1608 const auto &log = logger<LogArea::Experiment>();
1609 const uint64_t wall_actions_this_interval =
1610 wall_actions_total_ - previous_wall_actions_total_;
1611 previous_wall_actions_total_ = wall_actions_total_;
1612 const uint64_t interactions_this_interval = interactions_total_ -
1613 previous_interactions_total_ -
1614 wall_actions_this_interval;
1615 previous_interactions_total_ = interactions_total_;
1617 conserved_initial_, time_start_,
1618 parameters_.outputclock.current_time());
1621 for (
const auto &output : outputs_) {
1622 if (output->is_dilepton_output() || output->is_photon_output()) {
1625 output->at_intermediate_time(particles_, parameters_.outputclock,
1629 switch (dens_type_lattice_printout_) {
1630 case DensityType::Baryon:
1632 density_param_, particles_,
false);
1634 DensityType::Baryon, *jmu_B_lat_);
1636 case DensityType::BaryonicIsospin:
1637 update_lattice(jmu_I3_lat_.get(), lat_upd, DensityType::BaryonicIsospin,
1638 density_param_, particles_,
false);
1640 DensityType::BaryonicIsospin,
1643 case DensityType::None:
1647 dens_type_lattice_printout_, density_param_, particles_,
1650 dens_type_lattice_printout_,
1653 if (printout_tmn_ || printout_tmn_landau_ || printout_v_landau_) {
1655 density_param_, particles_);
1656 if (printout_tmn_) {
1658 dens_type_lattice_printout_, *Tmn_);
1660 if (printout_tmn_landau_) {
1662 dens_type_lattice_printout_, *Tmn_);
1664 if (printout_v_landau_) {
1666 dens_type_lattice_printout_, *Tmn_);
1671 output->thermodynamics_output(*thermalizer_);
1676 template <
typename Modus>
1679 if (potentials_->use_skyrme() && jmu_B_lat_ !=
nullptr) {
1681 DensityType::Baryon, density_param_, particles_,
true);
1682 const size_t UBlattice_size = UB_lat_->size();
1683 for (
size_t i = 0; i < UBlattice_size; i++) {
1684 auto jB = (*jmu_B_lat_)[i];
1686 std::abs(jB.density()) >
really_small ? jB.jmu_net() / jB.density()
1689 flow_four_velocity * potentials_->skyrme_pot(jB.density());
1690 (*FB_lat_)[i] = potentials_->skyrme_force(jB.density(), jB.grad_rho(),
1691 jB.dj_dt(), jB.rot_j());
1694 if (potentials_->use_symmetry() && jmu_I3_lat_ !=
nullptr) {
1696 DensityType::BaryonicIsospin, density_param_, particles_,
1698 const size_t UI3lattice_size = UI3_lat_->size();
1699 for (
size_t i = 0; i < UI3lattice_size; i++) {
1700 auto jI3 = (*jmu_I3_lat_)[i];
1703 ? jI3.jmu_net() / jI3.density()
1706 flow_four_velocity * potentials_->symmetry_pot(jI3.density());
1707 (*FI3_lat_)[i] = potentials_->symmetry_force(jI3.grad_rho(),
1708 jI3.dj_dt(), jI3.rot_j());
1714 template <
typename Modus>
1718 uint64_t interactions_old;
1719 const auto particles_before_actions = particles_.copy_to_vector();
1723 interactions_old = interactions_total_;
1726 if (dilepton_finder_ !=
nullptr) {
1727 for (
const auto &output : outputs_) {
1728 dilepton_finder_->shine_final(particles_, output.get(),
true);
1732 for (
const auto &finder : action_finders_) {
1733 actions.
insert(finder->find_final_actions(particles_));
1737 perform_action(*actions.
pop(), particles_before_actions);
1740 }
while (interactions_total_ > interactions_old);
1743 if (dilepton_finder_ !=
nullptr) {
1744 for (
const auto &output : outputs_) {
1745 dilepton_finder_->shine_final(particles_, output.get(),
false);
1750 template <
typename Modus>
1752 const auto &log = logger<LogArea::Experiment>();
1756 if (
likely(parameters_.labclock > 0)) {
1757 const uint64_t wall_actions_this_interval =
1758 wall_actions_total_ - previous_wall_actions_total_;
1759 const uint64_t interactions_this_interval = interactions_total_ -
1760 previous_interactions_total_ -
1761 wall_actions_this_interval;
1763 conserved_initial_, time_start_,
1764 parameters_.outputclock.current_time());
1765 log.info() <<
hline;
1766 log.info() <<
"Time real: " << SystemClock::now() - time_start_;
1767 log.info() <<
"Final interaction number: " 1768 << interactions_total_ - wall_actions_total_;
1770 int unformed_particles_count = 0;
1771 for (
const auto &particle : particles_) {
1772 if (particle.formation_time() > end_time_) {
1773 unformed_particles_count++;
1776 if (unformed_particles_count > 0) {
1777 log.warn(
"End time might be too small. ", unformed_particles_count,
1778 " unformed particles were found at the end of the evolution.");
1782 for (
const auto &output : outputs_) {
1783 output->at_eventend(particles_, evt_num, modus_.impact_parameter());
1787 template <
typename Modus>
1789 const auto &mainlog = logger<LogArea::Main>();
1790 for (
int j = 0; j < nevents_; j++) {
1791 mainlog.info() <<
"Event " << j;
1794 initialize_new_event();
1802 if (modus_.is_collider()) {
1803 if (!modus_.cll_in_nucleus()) {
1804 nucleon_has_interacted_.assign(modus_.total_N_number(),
false);
1806 nucleon_has_interacted_.assign(modus_.total_N_number(),
true);
1812 for (
int i = 0; i < modus_.total_N_number(); i++) {
1813 const auto mass_beam = particles_.copy_to_vector()[i].effective_mass();
1814 const auto v_beam = i < modus_.proj_N_number()
1815 ? modus_.velocity_projectile()
1816 : modus_.velocity_target();
1817 const auto gamma = 1.0 / std::sqrt(1.0 - v_beam * v_beam);
1818 beam_momentum_.emplace_back(
FourVector(gamma * mass_beam, 0.0, 0.0,
1819 gamma * v_beam * mass_beam));
1824 for (
const auto &output : outputs_) {
1825 output->at_eventstart(particles_, j);
1828 run_time_evolution();
1830 if (force_decays_) {
1841 #endif // SRC_INCLUDE_EXPERIMENT_H_ 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...
The main class, where the simulation of an experiment is executed.
A class to pre-calculate and store parameters relevant for density calculation.
OutputPtr photon_output_
The Photon output.
Potentials * pot_pointer
Pointer to a Potential class.
FermiMotion
Option to use Fermi Motion.
void check_interactions_total(uint64_t interactions_total)
Make sure interactions_total can be represented as a 32-bit integer.
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].
std::unique_ptr< RectangularLattice< EnergyMomentumTensor > > Tmn_
Lattices of energy-momentum tensors for printout.
constexpr double really_small
Numerical error tolerance.
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.
The Actions class abstracts the storage and manipulation of actions.
std::unique_ptr< DensityLattice > jmu_custom_lat_
Custom density on the lattices.
String excitation processes used in SMASH.
std::unique_ptr< T > make_unique(Args &&...args)
Definition for make_unique Is in C++14's standard library; necessary for older compilers.
DensityType td_dens_type
Type (e.g., baryon/pion/hadron) of thermodynamic quantity.
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > FB_lat_
Lattices for the electric and magnetic components of the Skyrme force.
RectangularLattice< FourVector > * UI3_lat_pointer
Pointer to the symmmetry potential on the lattice.
#define likely(x)
Tell the branch predictor that this expression is likely true.
void update_momenta(Particles *particles, double dt, const Potentials &pot, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *FB_lat, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *FI3_lat)
Updates the momenta of all particles at the current time step according to the equations of motion: ...
void insert(ActionList &&new_acts)
Insert a list of actions into this object.
std::unique_ptr< DecayActionsFinderDilepton > dilepton_finder_
The Dilepton Action Finder.
void update_lattice(RectangularLattice< T > *lat, const LatticeUpdate update, const DensityType dens_type, const DensityParameters &par, const Particles &particles, const bool compute_gradient=false)
Updates the contents on the lattice.
ThreeVector threevec() const
const TimeStepMode time_step_mode_
This indicates whether to use time steps.
constexpr double fm2_mb
mb <-> fm^2 conversion factor.
void set_seed(T &&seed)
Sets the seed of the random number engine.
LatticeUpdate
Enumerator option for lattice updates.
Interface to the SMASH configuration files.
double next_output_time() const
Shortcut for next output time.
bool is_pauli_blocked(const Particles &particles, const PauliBlocker &p_bl) const
Check if the action is Pauli-blocked.
constexpr double maximum_cross_section
The maximal cross section (in mb) for which it is guaranteed that all collisions with this cross sect...
Non-template interface to Experiment<Modus>.
ExperimentParameters create_experiment_parameters(Configuration config)
Gathers all general Experiment parameters.
virtual ProcessType get_type() const
Get the process type.
bool has_value(std::initializer_list< const char * > keys) const
Returns whether there is a non-empty value behind the requested keys.
std::unique_ptr< GrandCanThermalizer > thermalizer_
Instance of class used for forced thermalization.
const bool force_decays_
This indicates whether we force all resonances to decay in the last timestep.
bool td_tmn_landau
Print out energy-momentum tensor in Landau rest frame (of type td_dens_type) or not?
StringProcess * process_string_ptr_
Pointer to the string process class object, which is used to set the random seed for PYTHIA objects i...
QuantumNumbers conserved_initial_
The conserved quantities of the system.
ThermalizationAction implements forced thermalization as an Action class.
ExperimentParameters parameters_
Struct of several member variables.
bool any_particles_thermalized() const
This method checks, if there are particles in the region to be thermalized.
const bool use_grid_
This indicates whether to use the grid.
A container class to hold all the arrays on the lattice and access them.
Particles particles_
Complete particle list.
const std::string hline(67, '-')
String representing a horizontal line.
RectangularLattice< FourVector > * UB_lat_pointer
Pointer to the skyrme potential on the lattice.
std::unique_ptr< DensityLattice > jmu_I3_lat_
Isospin projection density on the lattices.
OutputPtr dilepton_output_
The Dilepton output.
Collection of useful type aliases to measure and output the (real) runtime.
std::unique_ptr< OutputInterface > create_oscar_output(const std::string &format, const std::string &content, const bf::path &path, const OutputParameters &out_par)
const double end_time_
simulation time at which the evolution is stopped.
TimeStepMode
The time step mode.
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > FI3_lat_
Lattices for the electric and magnetic component of the symmetry force.
Engine::result_type advance()
Advance the engine's state and return the generated value.
std::string format_measurements(const Particles &particles, uint64_t scatterings_this_interval, const QuantumNumbers &conserved_initial, SystemTimePoint time_start, double time)
Generate the tabulated string which will be printed to the screen when SMASH is running.
#define source_location
Hackery that is required to output the location in the source code where the log statement occurs...
Value take(std::initializer_list< const char * > keys)
The default interface for SMASH to read configuration values.
Don't use time steps; propagate from action to action.
const ExpansionProperties metric_
This struct contains information on the metric to be used.
Exception class that is thrown if an invalid modus is requested from the Experiment factory...
double compute_min_cell_length(double dt) const
Calculate the minimal size for the grid cells such that the ScatterActionsFinder will find all collis...
const double delta_time_startup_
The clock's timestep size at start up.
A container for storing conserved values.
Don't use fermi motion.
ActionPtr pop()
Return the first action in the list and removes it from the list.
Helper structure for Experiment to hold output options and parameters.
const bool dileptons_switch_
This indicates whether dileptons are switched on.
std::unique_ptr< ActionFinderInterface > photon_finder_
The (Scatter) Actions Finder for Direct Photons.
std::unique_ptr< Potentials > potentials_
An instance of potentials class, that stores parameters of potentials, calculates them and their grad...
void add_dummy_hadronic_process(double reaction_cross_section)
Adds one hadronic process with a given cross-section.
Clock tracks the time in the simulation.
Action is the base class for a generic process that takes a number of incoming particles and transfor...
virtual double get_total_weight() const =0
Return the total weight value, which is mainly used for the weight output entry.
ScatterActionPhoton is a special action which takes two incoming particles and performs a perturbativ...
const bool photons_switch_
This indicates whether photons are switched on.
std::ostream & operator<<(std::ostream &out, const Experiment< Modus > &e)
Creates a verbose textual description of the setup of the Experiment.
Use fermi motion without potentials.
bool is_valid(const Particles &particles) const
Check whether the action still applies.
FourVector get_interaction_point() const
Get the interaction point.
std::tuple< double, FourVector, ThreeVector, ThreeVector, ThreeVector > current_eckart(const ThreeVector &r, const ParticleList &plist, const DensityParameters &par, DensityType dens_type, bool compute_gradient, bool smearing)
Calculates Eckart rest frame density and 4-current of a given density type and optionally the gradien...
std::chrono::time_point< std::chrono::system_clock > SystemTimePoint
Type (alias) that is used to store the current time.
OutputsList outputs_
A list of output formaters.
Modus modus_
Instance of the Modus template parameter.
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.
bool td_tmn
Print out energy-momentum tensor of type td_dens_type or not?
Particles * particles()
Provides external access to SMASH particles.
std::vector< std::unique_ptr< ActionFinderInterface > > action_finders_
The Action finder objects.
DensityParameters density_param_
Structure to precalculate and hold parameters for density computations.
A stream modifier that allows to colorize the log output.
const ParticleList & incoming_particles() const
Get the list of particles that go into the action.
Modus * modus()
Provides external access to SMASH calculation modus.
The Particles class abstracts the storage and manipulation of particles.
bool td_v_landau
Print out Landau velocity of type td_dens_type or not?
DensityType
Allows to choose which kind of density to calculate.
const int nevents_
Number of events.
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
std::unique_ptr< PauliBlocker > pauli_blocker_
An instance of PauliBlocker class that stores parameters needed for Pauli blocking calculations and c...
Struct containing the type of the metric and the expansion parameter of the metric.
std::unique_ptr< DensityLattice > jmu_B_lat_
Baryon density on the lattices.
ActionList::size_type size() const
Helper structure for Experiment.
virtual void perform(Particles *particles, uint32_t id_process)
Actually perform the action, e.g.