Version: SMASH-3.3
smash::Experiment< Modus > Class Template Reference

#include <experiment.h>

template<typename Modus>
class smash::Experiment< Modus >

The main class, where the simulation of an experiment is executed.

The Experiment class owns all data (maybe indirectly) relevant for the execution of the experiment simulation. The experiment can be conducted in different running modi. Since the abstraction of these differences should not incur any overhead, the design is built around the Policy pattern.

The Policy pattern was defined by Andrei Alexandrescu in his book "Modern C++ Design: Generic Programming and Design Patterns Applied". Addison-Wesley:

A policy defines a class interface or a class template interface. The interface consists of one or all of the following: inner type definitions, member functions, and member variables.

The policy pattern can also be understood as a compile-time variant of the strategy pattern.

The Modus template parameter defines the "policy" of the Experiment class. It determines several aspects of the experiment execution at compile time. The original strategy pattern would select these differences at run time, thus incurring an overhead. This overhead becomes severe in cases where calls to strategy/policy functions are done very frequently. Using the policy pattern, the compiler can fully optimize: It creates a new instance of all functions in Experiment for all different Modus types.

Definition at line 192 of file experiment.h.

Inheritance diagram for smash::Experiment< Modus >:
smash::ExperimentBase

Public Member Functions

void run () override
 Runs the experiment. More...
 
 Experiment (Configuration &config, const std::filesystem::path &output_path)
 Create a new Experiment. More...
 
void initialize_new_event ()
 This is called in the beginning of each event. More...
 
void run_time_evolution (const double t_end, ParticleList &&add_plist={}, ParticleList &&remove_plist={})
 Runs the time evolution of an event with fixed-size time steps or without timesteps, from action to actions. More...
 
void do_final_interactions ()
 Performs the final decays of an event. More...
 
void final_output ()
 Output at the end of an event. More...
 
Particlesfirst_ensemble ()
 Provides external access to SMASH particles. More...
 
std::vector< Particles > * all_ensembles ()
 Getter for all ensembles. More...
 
Modus * modus ()
 Provides external access to SMASH calculation modus. More...
 
void increase_event_number ()
 Increases the event number by one. More...
 
- Public Member Functions inherited from smash::ExperimentBase
 ExperimentBase ()=default
 
virtual ~ExperimentBase ()=default
 The virtual destructor avoids undefined behavior when destroying derived objects. More...
 

Private Member Functions

bool perform_action (Action &action, int i_ensemble, bool include_pauli_blocking=true)
 Perform the given action. More...
 
void create_output (const std::string &format, const std::string &content, const std::filesystem::path &output_path, const OutputParameters &par)
 Create a list of output files. More...
 
void propagate_and_shine (double to_time, Particles &particles)
 Propagate all particles until time to_time without any interactions and shine dileptons. More...
 
void run_time_evolution_timestepless (Actions &actions, int i_ensemble, const double end_time_propagation)
 Performs all the propagations and actions during a certain time interval neglecting the influence of the potentials. More...
 
void intermediate_output ()
 Intermediate output during an event. More...
 
void update_potentials ()
 Recompute potentials on lattices if necessary. More...
 
double compute_min_cell_length (double dt) const
 Calculate the minimal size for the grid cells such that the ScatterActionsFinder will find all collisions within the maximal transverse distance (which is determined by the maximal cross section). More...
 
double next_output_time () const
 Shortcut for next output time. More...
 
void count_nonempty_ensembles ()
 Counts the number of ensembles in wich interactions took place at the end of an event. More...
 
bool is_finished ()
 Checks wether the desired number events have been calculated. More...
 

Private Attributes

ExperimentParameters parameters_
 Struct of several member variables. More...
 
DensityParameters density_param_
 Structure to precalculate and hold parameters for density computations. More...
 
Modus modus_
 Instance of the Modus template parameter. More...
 
std::vector< Particlesensembles_
 Complete particle list, all ensembles in one vector. More...
 
std::unique_ptr< Potentialspotentials_
 An instance of potentials class, that stores parameters of potentials, calculates them and their gradients. More...
 
std::unique_ptr< PauliBlockerpauli_blocker_
 An instance of PauliBlocker class that stores parameters needed for Pauli blocking calculations and computes phase-space density. More...
 
OutputsList outputs_
 A list of output formaters. More...
 
OutputPtr dilepton_output_
 The Dilepton output. More...
 
OutputPtr photon_output_
 The Photon output. More...
 
std::vector< bool > projectile_target_interact_
 Whether the projectile and the target collided. More...
 
std::vector< FourVectorbeam_momentum_ = {}
 The initial nucleons in the ColliderModus propagate with beam_momentum_, if Fermi motion is frozen. More...
 
std::vector< std::unique_ptr< ActionFinderInterface > > action_finders_
 The Action finder objects. More...
 
std::unique_ptr< DecayActionsFinderDileptondilepton_finder_
 The Dilepton Action Finder. More...
 
std::unique_ptr< ActionFinderInterfacephoton_finder_
 The (Scatter) Actions Finder for Direct Photons. More...
 
int n_fractional_photons_
 Number of fractional photons produced per single reaction. More...
 
std::unique_ptr< DensityLatticej_QBS_lat_
 4-current for j_QBS lattice output More...
 
std::unique_ptr< DensityLatticejmu_B_lat_
 Baryon density on the lattice. More...
 
std::unique_ptr< DensityLatticejmu_I3_lat_
 Isospin projection density on the lattice. More...
 
std::unique_ptr< DensityLatticejmu_el_lat_
 Electric charge density on the lattice. More...
 
std::unique_ptr< FieldsLatticefields_lat_
 Mean-field A^mu on the lattice. More...
 
std::unique_ptr< DensityLatticejmu_custom_lat_
 Custom density on the lattices. More...
 
DensityType dens_type_lattice_printout_ = DensityType::None
 Type of density for lattice printout. More...
 
std::unique_ptr< RectangularLattice< FourVector > > UB_lat_ = nullptr
 Lattices for Skyrme or VDF potentials (evaluated in the local rest frame) times the baryon flow 4-velocity. More...
 
std::unique_ptr< RectangularLattice< FourVector > > UI3_lat_ = nullptr
 Lattices for symmetry potentials (evaluated in the local rest frame) times the isospin flow 4-velocity. More...
 
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > FB_lat_
 Lattices for the electric and magnetic components of the Skyrme or VDF force. More...
 
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > FI3_lat_
 Lattices for the electric and magnetic component of the symmetry force. More...
 
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > EM_lat_
 Lattices for electric and magnetic field in fm^-2. More...
 
std::unique_ptr< RectangularLattice< EnergyMomentumTensor > > Tmn_
 Lattices of energy-momentum tensors for printout. More...
 
std::unique_ptr< RectangularLattice< FourVector > > old_jmu_auxiliary_
 Auxiliary lattice for values of jmu at a time step t0. More...
 
std::unique_ptr< RectangularLattice< FourVector > > new_jmu_auxiliary_
 Auxiliary lattice for values of jmu at a time step t0 + dt. More...
 
std::unique_ptr< RectangularLattice< std::array< FourVector, 4 > > > four_gradient_auxiliary_
 Auxiliary lattice for calculating the four-gradient of jmu. More...
 
std::unique_ptr< RectangularLattice< FourVector > > old_fields_auxiliary_
 Auxiliary lattice for values of Amu at a time step t0. More...
 
std::unique_ptr< RectangularLattice< FourVector > > new_fields_auxiliary_
 Auxiliary lattice for values of Amu at a time step t0 + dt. More...
 
std::unique_ptr< RectangularLattice< std::array< FourVector, 4 > > > fields_four_gradient_auxiliary_
 Auxiliary lattice for calculating the four-gradient of Amu. More...
 
bool printout_rho_eckart_ = false
 Whether to print the Eckart rest frame density. More...
 
bool printout_tmn_ = false
 Whether to print the energy-momentum tensor. More...
 
bool printout_tmn_landau_ = false
 Whether to print the energy-momentum tensor in Landau frame. More...
 
bool printout_v_landau_ = false
 Whether to print the 4-velocity in Landau frame. More...
 
bool printout_j_QBS_ = false
 Whether to print the Q, B, S 4-currents. More...
 
bool printout_lattice_td_ = false
 Whether to print the thermodynamics quantities evaluated on the lattices. More...
 
bool printout_full_lattice_any_td_ = false
 Whether to print the thermodynamics quantities evaluated on the lattices, point by point, in any format. More...
 
std::unique_ptr< GrandCanThermalizerthermalizer_
 Instance of class used for forced thermalization. More...
 
StringProcessprocess_string_ptr_
 Pointer to the string process class object, which is used to set the random seed for PYTHIA objects in each event. More...
 
int nevents_ = 0
 Number of events. More...
 
int minimum_nonempty_ensembles_ = 0
 The number of ensembles, in which interactions take place, to be calculated. More...
 
EventCounting event_counting_ = EventCounting::Invalid
 The way in which the number of calculated events is specified. More...
 
int event_ = 0
 Current event. More...
 
int nonempty_ensembles_ = 0
 Number of ensembles containing an interaction. More...
 
int max_events_ = 0
 Maximum number of events to be calculated in order obtain the desired number of non-empty events using the MinimumNonemptyEnsembles option. More...
 
const double end_time_
 simulation time at which the evolution is stopped. More...
 
const double delta_time_startup_
 The clock's timestep size at start up. More...
 
const bool force_decays_
 This indicates whether we force all resonances to decay in the last timestep. More...
 
const bool use_grid_
 This indicates whether to use the grid. More...
 
const ExpansionProperties metric_
 This struct contains information on the metric to be used. More...
 
const bool dileptons_switch_
 This indicates whether dileptons are switched on. More...
 
const bool photons_switch_
 This indicates whether photons are switched on. More...
 
const bool bremsstrahlung_switch_
 This indicates whether bremsstrahlung is switched on. More...
 
const bool IC_switch_
 This indicates whether the experiment will be used as initial condition for hydrodynamics. More...
 
const bool IC_dynamic_
 This indicates if the IC is dynamic. More...
 
const TimeStepMode time_step_mode_
 This indicates whether to use time steps. More...
 
double max_transverse_distance_sqr_ = std::numeric_limits<double>::max()
 Maximal distance at which particles can interact in case of the geometric criterion, squared. More...
 
QuantumNumbers conserved_initial_
 The conserved quantities of the system. More...
 
double initial_mean_field_energy_
 The initial total mean field energy in the system. More...
 
SystemTimePoint time_start_ = SystemClock::now()
 system starting time of the simulation More...
 
DensityType dens_type_ = DensityType::None
 Type of density to be written to collision headers. More...
 
uint64_t interactions_total_ = 0
 Total number of interactions for current timestep. More...
 
uint64_t previous_interactions_total_ = 0
 Total number of interactions for previous timestep. More...
 
uint64_t wall_actions_total_ = 0
 Total number of wall-crossings for current timestep. More...
 
uint64_t previous_wall_actions_total_ = 0
 Total number of wall-crossings for previous timestep. More...
 
uint64_t total_pauli_blocked_ = 0
 Total number of Pauli-blockings for current timestep. More...
 
uint64_t total_hypersurface_crossing_actions_ = 0
 Total number of particles removed from the evolution in hypersurface crossing actions. More...
 
uint64_t discarded_interactions_total_ = 0
 Total number of discarded interactions, because they were invalidated before they could be performed. More...
 
double total_energy_removed_ = 0.0
 Total energy removed from the system in hypersurface crossing actions. More...
 
double total_energy_violated_by_Pythia_ = 0.0
 Total energy violation introduced by Pythia. More...
 
bool kinematic_cuts_for_IC_output_ = false
 This indicates whether kinematic cuts are enabled for the IC output. More...
 
int64_t seed_ = -1
 random seed for the next event. More...
 

Friends

class ExperimentBase
 
std::ostream & operator<< (std::ostream &out, const Experiment &e)
 Writes the initial state for the Experiment to the output stream. More...
 

Additional Inherited Members

- Static Public Member Functions inherited from smash::ExperimentBase
static std::unique_ptr< ExperimentBasecreate (Configuration &config, const std::filesystem::path &output_path)
 Factory method that creates and initializes a new Experiment<Modus>. More...
 

Constructor & Destructor Documentation

◆ Experiment()

template<typename Modus >
smash::Experiment< Modus >::Experiment ( Configuration config,
const std::filesystem::path &  output_path 
)
explicit

Create a new Experiment.

This constructor is only called from the ExperimentBase::create factory method.

Parameters
[in,out]configThe Configuration object contains all initial setup of the experiment. It is forwarded to the constructors of member variables as needed. Note that the object is passed by non-const reference. This is only necessary for bookkeeping: Values are not only read, but actually taken out of the object. Thus, all values that remain were not used.
[in]output_pathThe directory where the output files are written.

Member Function Documentation

◆ run()

template<typename Modus >
void smash::Experiment< Modus >::run
overridevirtual

Runs the experiment.

The constructor does the setup of the experiment. The run function executes the complete experiment.

Implements smash::ExperimentBase.

Definition at line 3252 of file experiment.h.

3252  {
3253  const auto &mainlog = logg[LMain];
3254  for (event_ = 0; !is_finished(); event_++) {
3255  mainlog.info() << "Event " << event_;
3256 
3257  // Sample initial particles, start clock, some printout and book-keeping
3259 
3261 
3263 
3264  // Output at event end
3265  final_output();
3266  }
3267 }
void run_time_evolution(const double t_end, ParticleList &&add_plist={}, ParticleList &&remove_plist={})
Runs the time evolution of an event with fixed-size time steps or without timesteps,...
Definition: experiment.h:2453
void initialize_new_event()
This is called in the beginning of each event.
Definition: experiment.h:2062
bool is_finished()
Checks wether the desired number events have been calculated.
Definition: experiment.h:3221
int event_
Current event.
Definition: experiment.h:574
void do_final_interactions()
Performs the final decays of an event.
Definition: experiment.h:3020
void final_output()
Output at the end of an event.
Definition: experiment.h:3068
const double end_time_
simulation time at which the evolution is stopped.
Definition: experiment.h:586
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:40
static constexpr int LMain
Definition: experiment.h:93

◆ initialize_new_event()

template<typename Modus >
void smash::Experiment< Modus >::initialize_new_event

This is called in the beginning of each event.

It initializes particles according to selected modus, resets the clock and saves the initial conserved quantities for subsequent sanity checks.

Definition at line 2062 of file experiment.h.

2062  {
2064  logg[LExperiment].info() << "random number seed: " << seed_;
2065  /* Set seed for the next event. It has to be positive, so it can be entered
2066  * in the config.
2067  *
2068  * We have to be careful about the minimal integer, whose absolute value
2069  * cannot be represented. */
2070  int64_t r = random::advance();
2071  while (r == INT64_MIN) {
2072  r = random::advance();
2073  }
2074  seed_ = std::abs(r);
2075  /* Set the random seed used in PYTHIA hadronization
2076  * to be same with the SMASH one.
2077  * In this way we ensure that the results are reproducible
2078  * for every event if one knows SMASH random seed. */
2079  if (process_string_ptr_ != NULL) {
2081  }
2082 
2083  for (Particles &particles : ensembles_) {
2084  particles.reset();
2085  }
2086 
2087  // Sample particles according to the initial conditions
2088  double start_time = -1.0;
2089 
2090  // Sample impact parameter only once per all ensembles
2091  // It should be the same for all ensembles
2092  if (modus_.is_collider()) {
2093  modus_.sample_impact();
2094  logg[LExperiment].info("Impact parameter = ", modus_.impact_parameter(),
2095  " fm");
2096  }
2097  for (Particles &particles : ensembles_) {
2098  start_time = modus_.initial_conditions(&particles, parameters_);
2099  }
2100  /* For box modus make sure that particles are in the box. In principle, after
2101  * a correct initialization they should be, so this is just playing it safe.
2102  */
2103  for (Particles &particles : ensembles_) {
2104  modus_.impose_boundary_conditions(&particles, outputs_);
2105  }
2106  // Reset the simulation clock
2107  double timestep = delta_time_startup_;
2108 
2109  switch (time_step_mode_) {
2110  case TimeStepMode::Fixed:
2111  break;
2112  case TimeStepMode::None:
2113  timestep = end_time_ - start_time;
2114  // Take care of the box modus + timestepless propagation
2115  const double max_dt = modus_.max_timestep(max_transverse_distance_sqr_);
2116  if (max_dt > 0. && max_dt < timestep) {
2117  timestep = max_dt;
2118  }
2119  break;
2120  }
2121  std::unique_ptr<UniformClock> clock_for_this_event;
2122  if (modus_.is_list() && (timestep < 0.0)) {
2123  throw std::runtime_error(
2124  "Timestep for the given event is negative. \n"
2125  "This might happen if the formation times of the input particles are "
2126  "larger than the specified end time of the simulation.");
2127  }
2128  clock_for_this_event =
2129  std::make_unique<UniformClock>(start_time, timestep, end_time_);
2130  parameters_.labclock = std::move(clock_for_this_event);
2131 
2132  // Reset the output clock
2133  parameters_.outputclock->reset(start_time, true);
2134  // remove time before starting time in case of custom output times.
2135  parameters_.outputclock->remove_times_in_past(start_time);
2136 
2137  logg[LExperiment].debug(
2138  "Lab clock: t_start = ", parameters_.labclock->current_time(),
2139  ", dt = ", parameters_.labclock->timestep_duration());
2140 
2141  /* Save the initial conserved quantum numbers and total momentum in
2142  * the system for conservation checks */
2143  conserved_initial_ = QuantumNumbers(ensembles_);
2144  wall_actions_total_ = 0;
2146  interactions_total_ = 0;
2152  total_energy_removed_ = 0.0;
2154  // Print output headers
2155  logg[LExperiment].info() << hline;
2156  logg[LExperiment].info() << "Time[fm] Ekin[GeV] E_MF[GeV] ETotal[GeV] "
2157  << "ETot/N[GeV] D(ETot/N)[GeV] Scatt&Decays "
2158  << "Particles Comp.Time";
2159  logg[LExperiment].info() << hline;
2160  double E_mean_field = 0.0;
2161  if (potentials_) {
2162  // update_potentials();
2163  // if (parameters.outputclock->current_time() == 0.0 )
2164  // using the lattice is necessary
2165  if ((jmu_B_lat_ != nullptr)) {
2170  parameters_.labclock->timestep_duration(), true);
2171  // Because there was no lattice at t=-Delta_t, the time derivatives
2172  // drho_dt and dj^mu/dt at t=0 are huge, while they shouldn't be; we
2173  // overwrite the time derivative to zero by hand.
2174  for (auto &node : *jmu_B_lat_) {
2175  node.overwrite_drho_dt_to_zero();
2176  node.overwrite_djmu_dt_to_zero();
2177  }
2179  EM_lat_.get(), parameters_);
2180  }
2181  }
2182  initial_mean_field_energy_ = E_mean_field;
2185  parameters_.labclock->current_time(), E_mean_field,
2187 
2188  // Output at event start
2189  for (const auto &output : outputs_) {
2190  for (int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2191  auto event_info = fill_event_info(
2192  ensembles_, E_mean_field, modus_.impact_parameter(), parameters_,
2194  output->at_eventstart(ensembles_[i_ens], {event_, i_ens}, event_info);
2195  }
2196  // For thermodynamic output
2197  output->at_eventstart(ensembles_, event_);
2198  // For thermodynamic lattice output
2200  if (printout_rho_eckart_) {
2201  switch (dens_type_lattice_printout_) {
2202  case DensityType::Baryon:
2203  output->at_eventstart(event_, ThermodynamicQuantity::EckartDensity,
2205  break;
2207  output->at_eventstart(event_, ThermodynamicQuantity::EckartDensity,
2209  break;
2210  case DensityType::None:
2211  break;
2212  default:
2213  output->at_eventstart(event_, ThermodynamicQuantity::EckartDensity,
2215  *jmu_custom_lat_);
2216  }
2217  }
2218  if (printout_tmn_) {
2219  output->at_eventstart(event_, ThermodynamicQuantity::Tmn,
2221  }
2222  if (printout_tmn_landau_) {
2223  output->at_eventstart(event_, ThermodynamicQuantity::TmnLandau,
2225  }
2226  if (printout_v_landau_) {
2227  output->at_eventstart(event_, ThermodynamicQuantity::LandauVelocity,
2229  }
2230  if (printout_j_QBS_) {
2231  output->at_eventstart(event_, ThermodynamicQuantity::j_QBS,
2233  }
2234  }
2235  }
2236 
2237  /* In the ColliderModus, if Fermi motion is frozen, assign the beam momenta
2238  * to the nucleons in both the projectile and the target. Every ensemble
2239  * gets the same beam momenta, so no need to create beam_momenta_ vector
2240  * for every ensemble.
2241  */
2242  if (modus_.is_collider() && modus_.fermi_motion() == FermiMotion::Frozen) {
2243  for (ParticleData &particle : ensembles_[0]) {
2244  const double m = particle.effective_mass();
2245  double v_beam = 0.0;
2246  if (particle.belongs_to() == BelongsTo::Projectile) {
2247  v_beam = modus_.velocity_projectile();
2248  } else if (particle.belongs_to() == BelongsTo::Target) {
2249  v_beam = modus_.velocity_target();
2250  }
2251  const double gamma = 1.0 / std::sqrt(1.0 - v_beam * v_beam);
2252  beam_momentum_.emplace_back(
2253  FourVector(gamma * m, 0.0, 0.0, gamma * v_beam * m));
2254  } // loop over particles
2255  }
2256 }
double initial_mean_field_energy_
The initial total mean field energy in the system.
Definition: experiment.h:647
bool printout_tmn_
Whether to print the energy-momentum tensor.
Definition: experiment.h:512
QuantumNumbers conserved_initial_
The conserved quantities of the system.
Definition: experiment.h:641
DensityParameters density_param_
Structure to precalculate and hold parameters for density computations.
Definition: experiment.h:375
double total_energy_removed_
Total energy removed from the system in hypersurface crossing actions.
Definition: experiment.h:700
DensityType dens_type_lattice_printout_
Type of density for lattice printout.
Definition: experiment.h:460
double max_transverse_distance_sqr_
Maximal distance at which particles can interact in case of the geometric criterion,...
Definition: experiment.h:632
bool printout_j_QBS_
Whether to print the Q, B, S 4-currents.
Definition: experiment.h:521
const TimeStepMode time_step_mode_
This indicates whether to use time steps.
Definition: experiment.h:626
std::unique_ptr< DensityLattice > jmu_custom_lat_
Custom density on the lattices.
Definition: experiment.h:457
bool printout_full_lattice_any_td_
Whether to print the thermodynamics quantities evaluated on the lattices, point by point,...
Definition: experiment.h:528
std::unique_ptr< DensityLattice > jmu_B_lat_
Baryon density on the lattice.
Definition: experiment.h:439
std::vector< FourVector > beam_momentum_
The initial nucleons in the ColliderModus propagate with beam_momentum_, if Fermi motion is frozen.
Definition: experiment.h:421
std::unique_ptr< RectangularLattice< FourVector > > new_jmu_auxiliary_
Auxiliary lattice for values of jmu at a time step t0 + dt.
Definition: experiment.h:495
const double delta_time_startup_
The clock's timestep size at start up.
Definition: experiment.h:593
std::unique_ptr< RectangularLattice< EnergyMomentumTensor > > Tmn_
Lattices of energy-momentum tensors for printout.
Definition: experiment.h:490
std::vector< Particles > ensembles_
Complete particle list, all ensembles in one vector.
Definition: experiment.h:384
SystemTimePoint time_start_
system starting time of the simulation
Definition: experiment.h:650
uint64_t previous_wall_actions_total_
Total number of wall-crossings for previous timestep.
Definition: experiment.h:677
OutputsList outputs_
A list of output formaters.
Definition: experiment.h:402
bool printout_rho_eckart_
Whether to print the Eckart rest frame density.
Definition: experiment.h:509
bool printout_v_landau_
Whether to print the 4-velocity in Landau frame.
Definition: experiment.h:518
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > EM_lat_
Lattices for electric and magnetic field in fm^-2.
Definition: experiment.h:487
Modus modus_
Instance of the Modus template parameter.
Definition: experiment.h:381
std::unique_ptr< RectangularLattice< FourVector > > old_jmu_auxiliary_
Auxiliary lattice for values of jmu at a time step t0.
Definition: experiment.h:493
std::unique_ptr< DensityLattice > j_QBS_lat_
4-current for j_QBS lattice output
Definition: experiment.h:436
bool printout_tmn_landau_
Whether to print the energy-momentum tensor in Landau frame.
Definition: experiment.h:515
std::unique_ptr< RectangularLattice< std::array< FourVector, 4 > > > four_gradient_auxiliary_
Auxiliary lattice for calculating the four-gradient of jmu.
Definition: experiment.h:498
StringProcess * process_string_ptr_
Pointer to the string process class object, which is used to set the random seed for PYTHIA objects i...
Definition: experiment.h:537
ExperimentParameters parameters_
Struct of several member variables.
Definition: experiment.h:372
std::unique_ptr< Potentials > potentials_
An instance of potentials class, that stores parameters of potentials, calculates them and their grad...
Definition: experiment.h:390
uint64_t wall_actions_total_
Total number of wall-crossings for current timestep.
Definition: experiment.h:671
uint64_t total_hypersurface_crossing_actions_
Total number of particles removed from the evolution in hypersurface crossing actions.
Definition: experiment.h:689
uint64_t interactions_total_
Total number of interactions for current timestep.
Definition: experiment.h:659
std::unique_ptr< DensityLattice > jmu_I3_lat_
Isospin projection density on the lattice.
Definition: experiment.h:442
uint64_t total_pauli_blocked_
Total number of Pauli-blockings for current timestep.
Definition: experiment.h:683
std::vector< bool > projectile_target_interact_
Whether the projectile and the target collided.
Definition: experiment.h:414
int64_t seed_
random seed for the next event.
Definition: experiment.h:711
uint64_t previous_interactions_total_
Total number of interactions for previous timestep.
Definition: experiment.h:665
uint64_t discarded_interactions_total_
Total number of discarded interactions, because they were invalidated before they could be performed.
Definition: experiment.h:695
bool kinematic_cuts_for_IC_output_
This indicates whether kinematic cuts are enabled for the IC output.
Definition: experiment.h:708
double total_energy_violated_by_Pythia_
Total energy violation introduced by Pythia.
Definition: experiment.h:705
void init_pythia_hadron_rndm()
Set PYTHIA random seeds to be desired values.
@ Frozen
Use fermi motion without potentials.
@ Fixed
Use fixed time step.
@ None
Don't use time steps; propagate from action to action.
@ EckartDensity
Density in the Eckart frame.
@ Tmn
Energy-momentum tensor in lab frame.
@ LandauVelocity
Velocity of the Landau rest frame.
@ j_QBS
Electric (Q), baryonic (B) and strange (S) currents.
@ TmnLandau
Energy-momentum tensor in Landau rest frame.
Engine::result_type advance()
Advance the engine's state and return the generated value.
Definition: random.h:78
void set_seed(T &&seed)
Sets the seed of the random number engine.
Definition: random.h:71
EventInfo fill_event_info(const std::vector< Particles > &ensembles, double E_mean_field, double modus_impact_parameter, const ExperimentParameters &parameters, bool projectile_target_interact, bool kinematic_cut_for_SMASH_IC)
Generate the EventInfo object which is passed to outputs_.
Definition: experiment.cc:601
std::string format_measurements(const std::vector< Particles > &ensembles, uint64_t scatterings_this_interval, const QuantumNumbers &conserved_initial, SystemTimePoint time_start, double time, double E_mean_field, double E_mean_field_initial)
Generate a string which will be printed to the screen when SMASH is running.
Definition: experiment.cc:333
double calculate_mean_field_energy(const Potentials &potentials, RectangularLattice< smash::DensityOnLattice > &jmu_B_lat, RectangularLattice< std::pair< ThreeVector, ThreeVector >> *em_lattice, const ExperimentParameters &parameters)
Calculate the total mean field energy of the system; this will be printed to the screen when SMASH is...
Definition: experiment.cc:381
static constexpr int LExperiment
void update_lattice(RectangularLattice< DensityOnLattice > *lat, RectangularLattice< FourVector > *old_jmu, RectangularLattice< FourVector > *new_jmu, RectangularLattice< std::array< FourVector, 4 >> *four_grad_lattice, const LatticeUpdate update, const DensityType dens_type, const DensityParameters &par, const std::vector< Particles > &ensembles, const double time_step, const bool compute_gradient)
Updates the contents on the lattice of DensityOnLattice type.
Definition: density.cc:186
const std::string hline(113, '-')
String representing a horizontal line.
int n_ensembles
Number of parallel ensembles.
std::unique_ptr< Clock > outputclock
Output clock to keep track of the next output time.
std::unique_ptr< Clock > labclock
System clock (for simulation time keeping in the computational frame)

◆ run_time_evolution()

template<typename Modus >
void smash::Experiment< Modus >::run_time_evolution ( const double  t_end,
ParticleList &&  add_plist = {},
ParticleList &&  remove_plist = {} 
)

Runs the time evolution of an event with fixed-size time steps or without timesteps, from action to actions.

Within one timestep (fixed) evolution from action to action is invoked.

Parameters
[in]t_endTime until run_time_evolution is run, in SMASH this is the configured end_time, but it might differ if SMASH is used as an external library
[in]add_plistA by-default empty particle list which is added to the current particle content of the system
[in]remove_plistA by-default empty particle list which is removed from the current particle content of the system
Note
This function is meant to take over ownership of the to-be-added/removed particle lists and that's why these are passed by rvalue reference.

Definition at line 2453 of file experiment.h.

2455  {
2456  if (!add_plist.empty() || !remove_plist.empty()) {
2457  if (ensembles_.size() > 1) {
2458  throw std::runtime_error(
2459  "Adding or removing particles from SMASH is only possible when one "
2460  "ensemble is used.");
2461  }
2462  const double action_time = parameters_.labclock->current_time();
2463  /* Use two if statements. The first one is to check if the particles are
2464  * valid. Since this might remove all particles, a second if statement is
2465  * needed to avoid executing the action in that case.*/
2466  if (!add_plist.empty()) {
2468  }
2469  if (!add_plist.empty()) {
2470  // Create and perform action to add particle(s)
2471  auto action_add_particles = std::make_unique<FreeforallAction>(
2472  ParticleList{}, add_plist, action_time);
2473  perform_action(*action_add_particles, 0);
2474  }
2475  // Also here 2 if statements are needed as above.
2476  if (!remove_plist.empty()) {
2477  validate_and_adjust_particle_list(remove_plist);
2478  }
2479  if (!remove_plist.empty()) {
2480  ParticleList found_particles_to_remove;
2481  for (const auto &particle_to_remove : remove_plist) {
2482  const auto iterator_to_particle_to_be_removed_in_ensemble =
2483  std::find_if(
2484  ensembles_[0].begin(), ensembles_[0].end(),
2485  [&particle_to_remove, &action_time](const ParticleData &p) {
2487  particle_to_remove, p, action_time);
2488  });
2489  if (iterator_to_particle_to_be_removed_in_ensemble !=
2490  ensembles_[0].end())
2491  found_particles_to_remove.push_back(
2492  *iterator_to_particle_to_be_removed_in_ensemble);
2493  }
2494  // Sort the particles found to be removed according to their id and look
2495  // for duplicates (sorting is needed to call std::adjacent_find).
2496  std::sort(found_particles_to_remove.begin(),
2497  found_particles_to_remove.end(),
2498  [](const ParticleData &p1, const ParticleData &p2) {
2499  return p1.id() < p2.id();
2500  });
2501  const auto iterator_to_first_duplicate = std::adjacent_find(
2502  found_particles_to_remove.begin(), found_particles_to_remove.end(),
2503  [](const ParticleData &p1, const ParticleData &p2) {
2504  return p1.id() == p2.id();
2505  });
2506  if (iterator_to_first_duplicate != found_particles_to_remove.end()) {
2507  logg[LExperiment].error() << "The same particle has been asked to be "
2508  "removed multiple times:\n"
2509  << *iterator_to_first_duplicate;
2510  throw std::logic_error("Particle cannot be removed twice!");
2511  }
2512  if (auto delta = remove_plist.size() - found_particles_to_remove.size();
2513  delta > 0) {
2514  logg[LExperiment].warn(
2515  "When trying to remove particle(s) at the beginning ",
2516  "of the system evolution,\n", delta,
2517  " particle(s) could not be found and will be ignored.");
2518  }
2519  if (!found_particles_to_remove.empty()) {
2520  [[maybe_unused]] const auto number_particles_before_removal =
2521  ensembles_[0].size();
2522  // Create and perform action to remove particles
2523  auto action_remove_particles = std::make_unique<FreeforallAction>(
2524  found_particles_to_remove, ParticleList{}, action_time);
2525  perform_action(*action_remove_particles, 0);
2526 
2527  assert(number_particles_before_removal -
2528  found_particles_to_remove.size() ==
2529  ensembles_[0].size());
2530  }
2531  }
2532  }
2533 
2534  if (t_end > end_time_) {
2535  logg[LExperiment].fatal()
2536  << "Evolution asked to be run until " << t_end << " > " << end_time_
2537  << " and this cannot be done (because of how the clock works).";
2538  throw std::logic_error(
2539  "Experiment cannot evolve the system beyond End_Time.");
2540  }
2541  while (*(parameters_.labclock) < t_end) {
2542  const double dt = parameters_.labclock->timestep_duration();
2543  logg[LExperiment].debug("Timestepless propagation for next ", dt, " fm.");
2544 
2545  // Perform forced thermalization if required
2546  if (thermalizer_ &&
2547  thermalizer_->is_time_to_thermalize(parameters_.labclock)) {
2548  const bool ignore_cells_under_treshold = true;
2549  // Thermodynamics in thermalizer is computed from all ensembles,
2550  // but thermalization actions act on each ensemble independently
2551  thermalizer_->update_thermalizer_lattice(ensembles_, density_param_,
2552  ignore_cells_under_treshold);
2553  const double current_t = parameters_.labclock->current_time();
2554  for (int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2555  thermalizer_->thermalize(ensembles_[i_ens], current_t,
2557  ThermalizationAction th_act(*thermalizer_, current_t);
2558  if (th_act.any_particles_thermalized()) {
2559  perform_action(th_act, i_ens);
2560  }
2561  }
2562  }
2563 
2564  if (IC_dynamic_) {
2565  modus_.build_fluidization_lattice(parameters_.labclock->current_time(),
2567  }
2568 
2569  std::vector<Actions> actions(parameters_.n_ensembles);
2570  for (int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2571  actions[i_ens].clear();
2572  if (ensembles_[i_ens].size() > 0 && action_finders_.size() > 0) {
2573  /* (1.a) Create grid. */
2574  const double min_cell_length = compute_min_cell_length(dt);
2575  logg[LExperiment].debug("Creating grid with minimal cell length ",
2576  min_cell_length);
2577  /* For the hyper-surface-crossing actions also unformed particles are
2578  * searched and therefore needed on the grid. */
2579  const bool include_unformed_particles = IC_switch_;
2580  const auto &grid =
2581  use_grid_ ? modus_.create_grid(ensembles_[i_ens], min_cell_length,
2582  dt, parameters_.coll_crit,
2583  include_unformed_particles)
2584  : modus_.create_grid(ensembles_[i_ens], min_cell_length,
2585  dt, parameters_.coll_crit,
2586  include_unformed_particles,
2588 
2589  const double gcell_vol = grid.cell_volume();
2590  /* (1.b) Iterate over cells and find actions. */
2591  grid.iterate_cells(
2592  [&](const ParticleList &search_list) {
2593  for (const auto &finder : action_finders_) {
2594  actions[i_ens].insert(finder->find_actions_in_cell(
2595  search_list, dt, gcell_vol, beam_momentum_));
2596  }
2597  },
2598  [&](const ParticleList &search_list,
2599  const ParticleList &neighbors_list) {
2600  for (const auto &finder : action_finders_) {
2601  actions[i_ens].insert(finder->find_actions_with_neighbors(
2602  search_list, neighbors_list, dt, beam_momentum_));
2603  }
2604  });
2605  }
2606  }
2607 
2608  /* \todo (optimizations) Adapt timestep size here */
2609 
2610  /* (2) Propagate from action to action until next output or timestep end */
2611  const double end_timestep_time = parameters_.labclock->next_time();
2612  while (next_output_time() < end_timestep_time) {
2613  for (int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2614  run_time_evolution_timestepless(actions[i_ens], i_ens,
2615  next_output_time());
2616  }
2617  ++(*parameters_.outputclock);
2618 
2620  }
2621  for (int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2622  run_time_evolution_timestepless(actions[i_ens], i_ens, end_timestep_time);
2623  }
2624 
2625  /* (3) Update potentials (if computed on the lattice) and
2626  * compute new momenta according to equations of motion */
2627  if (potentials_) {
2629  update_momenta(ensembles_, parameters_.labclock->timestep_duration(),
2630  *potentials_, FB_lat_.get(), FI3_lat_.get(), EM_lat_.get(),
2631  jmu_B_lat_.get());
2632  }
2633 
2634  /* (4) Expand universe if non-minkowskian metric; updates
2635  * positions and momenta according to the selected expansion */
2637  for (Particles &particles : ensembles_) {
2638  expand_space_time(&particles, parameters_, metric_);
2639  }
2640  }
2641 
2642  ++(*parameters_.labclock);
2643 
2644  /* (5) Check conservation laws.
2645  *
2646  * Check conservation of conserved quantities if potentials and string
2647  * fragmentation are off. If potentials are on then momentum is conserved
2648  * only in average. If string fragmentation is on, then energy and
2649  * momentum are only very roughly conserved in high-energy collisions. */
2652  std::string err_msg = conserved_initial_.report_deviations(ensembles_);
2653  if (!err_msg.empty()) {
2654  logg[LExperiment].error() << err_msg;
2655  throw std::runtime_error("Violation of conserved quantities!");
2656  }
2657  }
2658  }
2659 
2660  /* Increment once more the output clock in order to have it prepared for the
2661  * final_output() call. Once close to the end time, the while-loop above to
2662  * produce intermediate output is not entered as the next_output_time() is
2663  * never strictly smaller than end_timestep_time (they are usually equal).
2664  * Since in the final_output() function the current time of the output clock
2665  * is used to produce the output, this has to be incremented before producing
2666  * the final output and it makes sense to do it here.
2667  */
2668  ++(*parameters_.outputclock);
2669 
2670  if (pauli_blocker_) {
2671  logg[LExperiment].info(
2672  "Interactions: Pauli-blocked/performed = ", total_pauli_blocked_, "/",
2674  }
2675 }
const ExpansionProperties metric_
This struct contains information on the metric to be used.
Definition: experiment.h:605
std::vector< std::unique_ptr< ActionFinderInterface > > action_finders_
The Action finder objects.
Definition: experiment.h:424
double next_output_time() const
Shortcut for next output time.
Definition: experiment.h:350
const bool IC_dynamic_
This indicates if the IC is dynamic.
Definition: experiment.h:623
std::unique_ptr< GrandCanThermalizer > thermalizer_
Instance of class used for forced thermalization.
Definition: experiment.h:531
void run_time_evolution_timestepless(Actions &actions, int i_ensemble, const double end_time_propagation)
Performs all the propagations and actions during a certain time interval neglecting the influence of ...
Definition: experiment.h:2704
void intermediate_output()
Intermediate output during an event.
Definition: experiment.h:2768
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > FI3_lat_
Lattices for the electric and magnetic component of the symmetry force.
Definition: experiment.h:483
double compute_min_cell_length(double dt) const
Calculate the minimal size for the grid cells such that the ScatterActionsFinder will find all collis...
Definition: experiment.h:342
const bool IC_switch_
This indicates whether the experiment will be used as initial condition for hydrodynamics.
Definition: experiment.h:620
std::unique_ptr< RectangularLattice< std::pair< ThreeVector, ThreeVector > > > FB_lat_
Lattices for the electric and magnetic components of the Skyrme or VDF force.
Definition: experiment.h:479
std::unique_ptr< PauliBlocker > pauli_blocker_
An instance of PauliBlocker class that stores parameters needed for Pauli blocking calculations and c...
Definition: experiment.h:396
bool perform_action(Action &action, int i_ensemble, bool include_pauli_blocking=true)
Perform the given action.
const bool use_grid_
This indicates whether to use the grid.
Definition: experiment.h:602
void update_potentials()
Recompute potentials on lattices if necessary.
Definition: experiment.h:2919
std::string report_deviations(const std::vector< Particles > &ensembles) const
Checks if the current particle list has still the same values and reports about differences.
constexpr int p
Proton.
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, DensityLattice *jB_lat)
Updates the momenta of all particles at the current time step according to the equations of motion:
Definition: propagation.cc:131
void expand_space_time(Particles *particles, const ExperimentParameters &parameters, const ExpansionProperties &metric)
Modifies positions and momentum of all particles to account for space-time deformation.
Definition: propagation.cc:106
bool are_particles_identical_at_given_time(const ParticleData &p1, const ParticleData &p2, double time)
Utility function to compare two ParticleData instances with respect to their PDG code,...
void validate_and_adjust_particle_list(ParticleList &particle_list)
Validate a particle list adjusting each particle to be a valid SMASH particle.
Definition: experiment.cc:623
@ Largest
Make cells as large as possible.
ExpansionMode mode_
Type of metric used.
Definition: propagation.h:28
const CollisionCriterion coll_crit
Employed collision criterion.
bool strings_switch
This indicates whether string fragmentation is switched on.
int testparticles
Number of test-particles.

◆ do_final_interactions()

template<typename Modus >
void smash::Experiment< Modus >::do_final_interactions

Performs the final decays of an event.

Exceptions
runtime_errorif found actions cannot be performed

Definition at line 3020 of file experiment.h.

3020  {
3021  /* At end of time evolution: Force all resonances to decay. In order to handle
3022  * decay chains, we need to loop until no further actions occur. */
3023  bool actions_performed, actions_found;
3024  uint64_t interactions_old;
3025  do {
3026  actions_found = false;
3027  interactions_old = interactions_total_;
3028  for (int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
3029  Actions actions;
3030  // Dileptons: shining of remaining resonances
3031  if (dilepton_finder_ != nullptr) {
3032  for (const auto &output : outputs_) {
3033  dilepton_finder_->shine_final(ensembles_[i_ens], output.get(), true);
3034  }
3035  }
3036  // Find actions.
3037  for (const auto &finder : action_finders_) {
3038  auto found_actions = finder->find_final_actions(ensembles_[i_ens]);
3039  if (!found_actions.empty()) {
3040  actions.insert(std::move(found_actions));
3041  actions_found = true;
3042  }
3043  }
3044  // Perform actions.
3045  while (!actions.is_empty()) {
3046  perform_action(*actions.pop(), i_ens, false);
3047  }
3048  }
3049  actions_performed = interactions_total_ > interactions_old;
3050  // Throw an error if actions were found but not performed
3051  if (actions_found && !actions_performed) {
3052  throw std::runtime_error("Final actions were found but not performed.");
3053  }
3054  // loop until no more decays occur
3055  } while (actions_performed);
3056 
3057  // Dileptons: shining of stable particles at the end
3058  if (dilepton_finder_ != nullptr) {
3059  for (const auto &output : outputs_) {
3060  for (Particles &particles : ensembles_) {
3061  dilepton_finder_->shine_final(particles, output.get(), false);
3062  }
3063  }
3064  }
3065 }
std::unique_ptr< DecayActionsFinderDilepton > dilepton_finder_
The Dilepton Action Finder.
Definition: experiment.h:427

◆ final_output()

template<typename Modus >
void smash::Experiment< Modus >::final_output

Output at the end of an event.

Definition at line 3068 of file experiment.h.

3068  {
3069  /* make sure the experiment actually ran (note: we should compare this
3070  * to the start time, but we don't know that. Therefore, we check that
3071  * the time is positive, which should heuristically be the same). */
3072  double E_mean_field = 0.0;
3073  if (likely(parameters_.labclock > 0)) {
3074  const uint64_t wall_actions_this_interval =
3076  const uint64_t interactions_this_interval = interactions_total_ -
3078  wall_actions_this_interval;
3079  if (potentials_) {
3080  // using the lattice is necessary
3081  if ((jmu_B_lat_ != nullptr)) {
3083  EM_lat_.get(), parameters_);
3084  }
3085  }
3086  if (std::abs(parameters_.labclock->current_time() - end_time_) >
3087  really_small) {
3088  logg[LExperiment].warn()
3089  << "SMASH not propagated until configured end time. Current time = "
3090  << parameters_.labclock->current_time()
3091  << "fm. End time = " << end_time_ << "fm.";
3092  } else {
3094  ensembles_, interactions_this_interval, conserved_initial_,
3096  }
3097  int total_particles = 0;
3098  for (const Particles &particles : ensembles_) {
3099  total_particles += particles.size();
3100  }
3101  if (IC_switch_ && (total_particles == 0)) {
3102  const double initial_system_energy_plus_Pythia_violations =
3104  const double fraction_of_total_system_energy_removed =
3105  initial_system_energy_plus_Pythia_violations / total_energy_removed_;
3106  // Verify there is no more energy in the system if all particles were
3107  // removed when crossing the hypersurface
3108  if (std::fabs(fraction_of_total_system_energy_removed - 1.) >
3109  really_small) {
3110  throw std::runtime_error(
3111  "There is remaining energy in the system although all particles "
3112  "were removed.\n"
3113  "E_remain = " +
3114  std::to_string((initial_system_energy_plus_Pythia_violations -
3116  " [GeV]");
3117  } else {
3118  logg[LExperiment].info() << hline;
3119  logg[LExperiment].info()
3120  << "Time real: " << SystemClock::now() - time_start_;
3121  logg[LExperiment].info()
3122  << "Interactions before reaching hypersurface: "
3125  logg[LExperiment].info()
3126  << "Total number of particles removed on hypersurface: "
3128  }
3129  } else {
3130  const double precent_discarded =
3132  ? static_cast<double>(discarded_interactions_total_) * 100.0 /
3134  : 0.0;
3135  std::stringstream msg_discarded;
3136  msg_discarded
3137  << "Discarded interaction number: " << discarded_interactions_total_
3138  << " (" << precent_discarded
3139  << "% of the total interaction number including wall crossings)";
3140 
3141  logg[LExperiment].info() << hline;
3142  logg[LExperiment].info()
3143  << "Time real: " << SystemClock::now() - time_start_;
3144  logg[LExperiment].debug() << msg_discarded.str();
3145 
3147  precent_discarded > 1.0) {
3148  // The chosen threshold of 1% is a heuristical value
3149  logg[LExperiment].warn()
3150  << msg_discarded.str()
3151  << "\nThe number of discarded interactions is large, which means "
3152  "the assumption for the stochastic criterion of\n1 interaction "
3153  "per particle per timestep is probably violated. Consider "
3154  "reducing the timestep size.";
3155  }
3156 
3157  logg[LExperiment].info() << "Final interaction number: "
3159  }
3160 
3161  // Check if there are unformed particles
3162  int unformed_particles_count = 0;
3163  for (const Particles &particles : ensembles_) {
3164  for (const ParticleData &particle : particles) {
3165  if (particle.formation_time() > end_time_) {
3166  unformed_particles_count++;
3167  }
3168  }
3169  }
3170  if (unformed_particles_count > 0) {
3171  logg[LExperiment].warn(
3172  "End time might be too small. ", unformed_particles_count,
3173  " unformed particles were found at the end of the evolution.");
3174  }
3175  }
3176 
3177  // Keep track of how many ensembles had interactions
3179 
3180  for (const auto &output : outputs_) {
3181  for (int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
3182  auto event_info = fill_event_info(
3183  ensembles_, E_mean_field, modus_.impact_parameter(), parameters_,
3185  output->at_eventend(ensembles_[i_ens], {event_, i_ens}, event_info);
3186  }
3187  // For thermodynamic output
3188  output->at_eventend(ensembles_, event_);
3189 
3190  // For thermodynamic lattice output
3191  if (printout_rho_eckart_) {
3193  output->at_eventend(ThermodynamicQuantity::EckartDensity);
3194  }
3195  }
3196  if (printout_tmn_) {
3197  output->at_eventend(ThermodynamicQuantity::Tmn);
3198  }
3199  if (printout_tmn_landau_) {
3200  output->at_eventend(ThermodynamicQuantity::TmnLandau);
3201  }
3202  if (printout_v_landau_) {
3203  output->at_eventend(ThermodynamicQuantity::LandauVelocity);
3204  }
3205  if (printout_j_QBS_) {
3206  output->at_eventend(ThermodynamicQuantity::j_QBS);
3207  }
3208  }
3209 }
void count_nonempty_ensembles()
Counts the number of ensembles in wich interactions took place at the end of an event.
Definition: experiment.h:3212
double x0() const
Definition: fourvector.h:313
FourVector momentum() const
@ Stochastic
Stochastic Criteiron.
#define likely(x)
Tell the branch predictor that this expression is likely true.
Definition: macros.h:14
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
Definition: stringify.cc:26
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:41

◆ first_ensemble()

template<typename Modus >
Particles* smash::Experiment< Modus >::first_ensemble ( )
inline

Provides external access to SMASH particles.

This is helpful if SMASH is used as a 3rd-party library.

Definition at line 261 of file experiment.h.

261 { return &ensembles_[0]; }

◆ all_ensembles()

template<typename Modus >
std::vector<Particles>* smash::Experiment< Modus >::all_ensembles ( )
inline

Getter for all ensembles.

Definition at line 263 of file experiment.h.

263 { return &ensembles_; }

◆ modus()

template<typename Modus >
Modus* smash::Experiment< Modus >::modus ( )
inline

Provides external access to SMASH calculation modus.

This is helpful if SMASH is used as a 3rd-party library.

Definition at line 269 of file experiment.h.

269 { return &modus_; }

◆ increase_event_number()

template<typename Modus >
void smash::Experiment< Modus >::increase_event_number

Increases the event number by one.

This function is helpful if SMASH is used as a 3rd-party library.

Definition at line 3247 of file experiment.h.

3247  {
3248  event_++;
3249 }

◆ perform_action()

template<typename Modus >
bool smash::Experiment< Modus >::perform_action ( Action action,
int  i_ensemble,
bool  include_pauli_blocking = true 
)
private

Perform the given action.

Parameters
[in]actionThe action to perform
[in]i_ensembleindex of ensemble in which action is performed
[in]include_pauli_blockingwheter to take Pauli blocking into account. Skipping Pauli blocking is useful for example for final decays.
Returns
False if the action is rejected either due to invalidity or Pauli-blocking, or true if it's accepted and performed.

◆ create_output()

template<typename Modus >
void smash::Experiment< Modus >::create_output ( const std::string &  format,
const std::string &  content,
const std::filesystem::path &  output_path,
const OutputParameters par 
)
private

Create a list of output files.

Parameters
[in]formatFormat of the output file (e.g. Root, Oscar, Vtk)
[in]contentContent of the output (e.g. particles, collisions)
[in]output_pathPath of the output file
[in]parOutput options.(e.g. Extended)

Definition at line 730 of file experiment.h.

733  {
734  // Disable output which do not properly work with multiple ensembles
735  if (ensembles_.size() > 1) {
736  auto abort_because_of = [](const std::string &s) {
737  throw std::invalid_argument(
738  s + " output is not available with multiple parallel ensembles.");
739  };
740  if (content == "Initial_Conditions") {
741  abort_because_of("Initial_Conditions");
742  }
743  if ((format == "HepMC") || (format == "HepMC_asciiv3") ||
744  (format == "HepMC_treeroot")) {
745  abort_because_of("HepMC");
746  }
747  if (content == "Rivet") {
748  abort_because_of("Rivet");
749  }
750  if (content == "Collisions") {
751  logg[LExperiment].warn(
752  "Information coming from different ensembles in 'Collisions' output "
753  "is not distinguishable.\nSuch an output with multiple parallel "
754  "ensembles should only be used if later in the data analysis\nit is "
755  "not necessary to trace back which data belongs to which ensemble.");
756  }
757  }
758 
759  if (format == "VTK" && content == "Particles") {
760  outputs_.emplace_back(
761  std::make_unique<VtkOutput>(output_path, content, out_par));
762  } else if (format == "Root") {
763 #ifdef SMASH_USE_ROOT
764  if (content == "Initial_Conditions") {
765  outputs_.emplace_back(
766  std::make_unique<RootOutput>(output_path, "SMASH_IC", out_par));
767  } else {
768  outputs_.emplace_back(
769  std::make_unique<RootOutput>(output_path, content, out_par));
770  }
771 #else
772  logg[LExperiment].error(
773  "Root output requested, but Root support not compiled in");
774 #endif
775  } else if ((format == "Binary" || format == "Oscar2013_bin") &&
776  (content == "Collisions" || content == "Particles" ||
777  content == "Dileptons" || content == "Photons" ||
778  content == "Initial_Conditions")) {
779  outputs_.emplace_back(
780  create_binary_output(format, content, output_path, out_par));
781  } else if (format == "Oscar1999" || format == "Oscar2013") {
782  outputs_.emplace_back(
783  create_oscar_output(format, content, output_path, out_par));
784  } else if (format == "ASCII" &&
785  (content == "Particles" || content == "Collisions" ||
786  content == "Dileptons" || content == "Photons" ||
787  content == "Initial_Conditions")) {
788  outputs_.emplace_back(
789  create_oscar_output(format, content, output_path, out_par));
790  } else if (content == "Thermodynamics" && format == "ASCII") {
791  outputs_.emplace_back(
792  std::make_unique<ThermodynamicOutput>(output_path, content, out_par));
793  } else if (content == "Thermodynamics" &&
794  (format == "Lattice_ASCII" || format == "Lattice_Binary")) {
796  outputs_.emplace_back(std::make_unique<ThermodynamicLatticeOutput>(
797  output_path, content, out_par, format == "Lattice_ASCII",
798  format == "Lattice_Binary"));
799  } else if (content == "Thermodynamics" && format == "VTK") {
800  printout_lattice_td_ = true;
801  outputs_.emplace_back(
802  std::make_unique<VtkOutput>(output_path, content, out_par));
803  } else if (content == "Initial_Conditions" && format == "For_vHLLE") {
804  if (IC_dynamic_) {
805  throw std::invalid_argument(
806  "Dynamic initial conditions are only available in Oscar2013 and "
807  "Binary formats.");
808  }
809  outputs_.emplace_back(
810  std::make_unique<ICOutput>(output_path, "SMASH_IC_For_vHLLE", out_par));
811  } else if ((format == "HepMC") || (format == "HepMC_asciiv3") ||
812  (format == "HepMC_treeroot")) {
813 #ifdef SMASH_USE_HEPMC
814  if (content == "Particles") {
815  if ((format == "HepMC") || (format == "HepMC_asciiv3")) {
816  outputs_.emplace_back(std::make_unique<HepMcOutput>(
817  output_path, "SMASH_HepMC_particles", false, "asciiv3"));
818  } else if (format == "HepMC_treeroot") {
819 #ifdef SMASH_USE_HEPMC_ROOTIO
820  outputs_.emplace_back(std::make_unique<HepMcOutput>(
821  output_path, "SMASH_HepMC_particles", false, "root"));
822 #else
823  logg[LExperiment].error(
824  "Requested HepMC_treeroot output not available, "
825  "ROOT or HepMC3_ROOTIO missing or not found by cmake.");
826 #endif
827  }
828  } else if (content == "Collisions") {
829  if ((format == "HepMC") || (format == "HepMC_asciiv3")) {
830  outputs_.emplace_back(std::make_unique<HepMcOutput>(
831  output_path, "SMASH_HepMC_collisions", true, "asciiv3"));
832  } else if (format == "HepMC_treeroot") {
833 #ifdef SMASH_USE_HEPMC_ROOTIO
834  outputs_.emplace_back(std::make_unique<HepMcOutput>(
835  output_path, "SMASH_HepMC_collisions", true, "root"));
836 #else
837  logg[LExperiment].error(
838  "Requested HepMC_treeroot output not available, "
839  "ROOT or HepMC3_ROOTIO missing or not found by cmake.");
840 #endif
841  }
842  } else {
843  logg[LExperiment].error(
844  "HepMC only available for Particles and "
845  "Collisions content. Requested for " +
846  content + ".");
847  }
848 #else
849  logg[LExperiment].error(
850  "HepMC output requested, but HepMC support not compiled in");
851 #endif
852  } else if (content == "Coulomb" && format == "VTK") {
853  outputs_.emplace_back(
854  std::make_unique<VtkOutput>(output_path, "Fields", out_par));
855  } else if (content == "Rivet") {
856 #ifdef SMASH_USE_RIVET
857  // flag to ensure that the Rivet format has not been already assigned
858  static bool rivet_format_already_selected = false;
859  // if the next check is true, then we are trying to assign the format twice
860  if (rivet_format_already_selected) {
861  logg[LExperiment].warn(
862  "Rivet output format can only be one, either YODA or YODA-full. "
863  "Only your first valid choice will be used.");
864  return;
865  }
866  if (format == "YODA") {
867  outputs_.emplace_back(std::make_unique<RivetOutput>(
868  output_path, "SMASH_Rivet", false, out_par.rivet_parameters));
869  rivet_format_already_selected = true;
870  } else if (format == "YODA-full") {
871  outputs_.emplace_back(std::make_unique<RivetOutput>(
872  output_path, "SMASH_Rivet_full", true, out_par.rivet_parameters));
873  rivet_format_already_selected = true;
874  } else {
875  logg[LExperiment].error("Rivet format " + format +
876  "not one of YODA or YODA-full");
877  }
878 #else
879  logg[LExperiment].error(
880  "Rivet output requested, but Rivet support not compiled in");
881 #endif
882  } else {
883  logg[LExperiment].error()
884  << "Unknown combination of format (" << format << ") and content ("
885  << content << "). Fix the config.";
886  }
887 
888  logg[LExperiment].info() << "Added output " << content << " of format "
889  << format << "\n";
890 }
bool printout_lattice_td_
Whether to print the thermodynamics quantities evaluated on the lattices.
Definition: experiment.h:524
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...
Definition: logging.h:217
std::unique_ptr< OutputInterface > create_oscar_output(const std::string &format, const std::string &content, const std::filesystem::path &path, const OutputParameters &out_par)
Definition: oscaroutput.cc:918
std::unique_ptr< OutputInterface > create_binary_output(const std::string &format, const std::string &content, const std::filesystem::path &path, const OutputParameters &out_par)
Create a binary output object.

◆ propagate_and_shine()

template<typename Modus >
void smash::Experiment< Modus >::propagate_and_shine ( double  to_time,
Particles particles 
)
private

Propagate all particles until time to_time without any interactions and shine dileptons.

Parameters
[in]to_timeTime at the end of propagation [fm]
[in,out]particlesParticles to be propagated

Definition at line 2678 of file experiment.h.

2679  {
2680  const double dt =
2681  propagate_straight_line(&particles, to_time, beam_momentum_);
2682  if (dilepton_finder_ != nullptr) {
2683  for (const auto &output : outputs_) {
2684  dilepton_finder_->shine(particles, output.get(), dt);
2685  }
2686  }
2687 }
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.
Definition: propagation.cc:44

◆ run_time_evolution_timestepless()

template<typename Modus >
void smash::Experiment< Modus >::run_time_evolution_timestepless ( Actions actions,
int  i_ensemble,
const double  end_time_propagation 
)
private

Performs all the propagations and actions during a certain time interval neglecting the influence of the potentials.

This function is called in either the time stepless cases or the cases with time steps.

Parameters
[in,out]actionsActions occur during a certain time interval. They provide the ending times of the propagations and are updated during the time interval.
[in]i_ensembleindex of ensemble to be evolved
[in]end_time_propagationtime until propagation should be performed

Definition at line 2704 of file experiment.h.

2705  {
2706  Particles &particles = ensembles_[i_ensemble];
2707  logg[LExperiment].debug(
2708  "Timestepless propagation: ", "Actions size = ", actions.size(),
2709  ", end time = ", end_time_propagation);
2710 
2711  // iterate over all actions
2712  while (!actions.is_empty()) {
2713  if (actions.earliest_time() > end_time_propagation) {
2714  break;
2715  }
2716  // get next action
2717  ActionPtr act = actions.pop();
2718  if (!act->is_valid(particles)) {
2720  logg[LExperiment].debug(~einhard::DRed(), "✘ ", act,
2721  " (discarded: invalid)");
2722  continue;
2723  }
2724  logg[LExperiment].debug(~einhard::Green(), "✔ ", act,
2725  ", action time = ", act->time_of_execution());
2726 
2727  /* (1) Propagate to the next action. */
2728  propagate_and_shine(act->time_of_execution(), particles);
2729 
2730  /* (2) Perform action.
2731  *
2732  * Update the positions of the incoming particles, because the information
2733  * in the action object will be outdated as the particles have been
2734  * propagated since the construction of the action. */
2735  act->update_incoming(particles);
2736  const bool performed = perform_action(*act, i_ensemble);
2737 
2738  /* No need to update actions for outgoing particles
2739  * if the action is not performed. */
2740  if (!performed) {
2741  continue;
2742  }
2743 
2744  /* (3) Update actions for newly-produced particles. */
2745 
2746  const double end_time_timestep = parameters_.labclock->next_time();
2747  // New actions are always search until the end of the current timestep
2748  const double time_left = end_time_timestep - act->time_of_execution();
2749  const ParticleList &outgoing_particles = act->outgoing_particles();
2750  // Grid cell volume set to zero, since there is no grid
2751  const double gcell_vol = 0.0;
2752  for (const auto &finder : action_finders_) {
2753  // Outgoing particles can still decay, cross walls...
2754  actions.insert(finder->find_actions_in_cell(outgoing_particles, time_left,
2755  gcell_vol, beam_momentum_));
2756  // ... and collide with other particles.
2757  actions.insert(finder->find_actions_with_surrounding_particles(
2758  outgoing_particles, particles, time_left, beam_momentum_));
2759  }
2760 
2762  }
2763 
2764  propagate_and_shine(end_time_propagation, particles);
2765 }
A stream modifier that allows to colorize the log output.
Definition: einhard.hpp:147
void propagate_and_shine(double to_time, Particles &particles)
Propagate all particles until time to_time without any interactions and shine dileptons.
Definition: experiment.h:2678
void check_interactions_total(uint64_t interactions_total)
Make sure interactions_total can be represented as a 32-bit integer.
Definition: experiment.h:2696

◆ intermediate_output()

template<typename Modus >
void smash::Experiment< Modus >::intermediate_output
private

Intermediate output during an event.

Auxiliary variable to communicate the time in the computational frame at the functions printing the thermodynamics lattice output

Definition at line 2768 of file experiment.h.

2768  {
2769  const uint64_t wall_actions_this_interval =
2772  const uint64_t interactions_this_interval = interactions_total_ -
2774  wall_actions_this_interval;
2776  double E_mean_field = 0.0;
2779  double computational_frame_time = 0.0;
2780  if (potentials_) {
2781  // using the lattice is necessary
2782  if ((jmu_B_lat_ != nullptr)) {
2784  EM_lat_.get(), parameters_);
2785  /*
2786  * Mean field calculated in a box should remain approximately constant if
2787  * the system is in equilibrium, and so deviations from its original value
2788  * may signal a phase transition or other dynamical process. This
2789  * comparison only makes sense in the Box Modus, hence the condition.
2790  */
2791  if (modus_.is_box()) {
2792  double tmp = (E_mean_field - initial_mean_field_energy_) /
2793  (E_mean_field + initial_mean_field_energy_);
2794  /*
2795  * This is displayed when the system evolves away from its initial
2796  * configuration (which is when the total mean field energy in the box
2797  * deviates from its initial value).
2798  */
2799  if (std::abs(tmp) > 0.01) {
2800  logg[LExperiment].info()
2801  << "\n\n\n\t The mean field at t = "
2802  << parameters_.outputclock->current_time()
2803  << " [fm] differs from the mean field at t = 0:"
2804  << "\n\t\t initial_mean_field_energy_ = "
2805  << initial_mean_field_energy_ << " [GeV]"
2806  << "\n\t\t abs[(E_MF - E_MF(t=0))/(E_MF + E_MF(t=0))] = "
2807  << std::abs(tmp)
2808  << "\n\t\t E_MF/E_MF(t=0) = "
2809  << E_mean_field / initial_mean_field_energy_ << "\n\n";
2810  }
2811  }
2812  }
2813  }
2814 
2816  ensembles_, interactions_this_interval, conserved_initial_, time_start_,
2817  parameters_.outputclock->current_time(), E_mean_field,
2819  const LatticeUpdate lat_upd = LatticeUpdate::AtOutput;
2820 
2821  // save evolution data
2822  if (!(modus_.is_box() && parameters_.outputclock->current_time() <
2823  modus_.equilibration_time())) {
2824  for (const auto &output : outputs_) {
2825  if (output->is_dilepton_output() || output->is_photon_output() ||
2826  output->is_IC_output()) {
2827  continue;
2828  }
2829  for (int i_ens = 0; i_ens < parameters_.n_ensembles; i_ens++) {
2830  auto event_info = fill_event_info(
2831  ensembles_, E_mean_field, modus_.impact_parameter(), parameters_,
2833 
2834  output->at_intermediate_time(ensembles_[i_ens], parameters_.outputclock,
2835  density_param_, {event_, i_ens},
2836  event_info);
2837  computational_frame_time = event_info.current_time;
2838  }
2839  // For thermodynamic output
2840  output->at_intermediate_time(ensembles_, parameters_.outputclock,
2841  density_param_);
2842 
2843  // Thermodynamic output on the lattice versus time
2844  if (printout_rho_eckart_) {
2845  switch (dens_type_lattice_printout_) {
2846  case DensityType::Baryon:
2849  ensembles_, false);
2850  output->thermodynamics_output(ThermodynamicQuantity::EckartDensity,
2852  output->thermodynamics_lattice_output(*jmu_B_lat_,
2853  computational_frame_time);
2854  break;
2857  jmu_I3_lat_.get(), lat_upd, DensityType::BaryonicIsospin,
2858  density_param_, ensembles_, false);
2859  output->thermodynamics_output(ThermodynamicQuantity::EckartDensity,
2861  *jmu_I3_lat_);
2862  output->thermodynamics_lattice_output(*jmu_I3_lat_,
2863  computational_frame_time);
2864  break;
2865  case DensityType::None:
2866  break;
2867  default:
2870  density_param_, ensembles_, false);
2871  output->thermodynamics_output(ThermodynamicQuantity::EckartDensity,
2873  *jmu_custom_lat_);
2874  output->thermodynamics_lattice_output(*jmu_custom_lat_,
2875  computational_frame_time);
2876  }
2877  }
2881  ensembles_, false);
2882  if (printout_tmn_) {
2883  output->thermodynamics_output(ThermodynamicQuantity::Tmn,
2885  output->thermodynamics_lattice_output(
2886  ThermodynamicQuantity::Tmn, *Tmn_, computational_frame_time);
2887  }
2888  if (printout_tmn_landau_) {
2889  output->thermodynamics_output(ThermodynamicQuantity::TmnLandau,
2891  output->thermodynamics_lattice_output(
2893  computational_frame_time);
2894  }
2895  if (printout_v_landau_) {
2896  output->thermodynamics_output(ThermodynamicQuantity::LandauVelocity,
2898  output->thermodynamics_lattice_output(
2900  computational_frame_time);
2901  }
2902  }
2903  if (EM_lat_) {
2904  output->fields_output("Efield", "Bfield", *EM_lat_);
2905  }
2906  if (printout_j_QBS_) {
2907  output->thermodynamics_lattice_output(
2908  *j_QBS_lat_, computational_frame_time, ensembles_, density_param_);
2909  }
2910 
2911  if (thermalizer_) {
2912  output->thermodynamics_output(*thermalizer_);
2913  }
2914  }
2915  }
2916 }
void update_lattice_accumulating_ensembles(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 when ensembles are used.
Definition: density.h:644
LatticeUpdate
Enumerator option for lattice updates.
Definition: lattice.h:38

◆ update_potentials()

template<typename Modus >
void smash::Experiment< Modus >::update_potentials
private

Recompute potentials on lattices if necessary.

Definition at line 2919 of file experiment.h.

2919  {
2920  if (potentials_) {
2921  if (potentials_->use_symmetry() && jmu_I3_lat_ != nullptr) {
2926  parameters_.labclock->timestep_duration(), true);
2927  }
2928  if ((potentials_->use_skyrme() || potentials_->use_symmetry()) &&
2929  jmu_B_lat_ != nullptr) {
2934  parameters_.labclock->timestep_duration(), true);
2935  const size_t UBlattice_size = UB_lat_->size();
2936  for (size_t i = 0; i < UBlattice_size; i++) {
2937  auto jB = (*jmu_B_lat_)[i];
2938  const FourVector flow_four_velocity_B =
2939  std::abs(jB.rho()) > very_small_double ? jB.jmu_net() / jB.rho()
2940  : FourVector();
2941  double baryon_density = jB.rho();
2942  ThreeVector baryon_grad_j0 = jB.grad_j0();
2943  ThreeVector baryon_dvecj_dt = jB.dvecj_dt();
2944  ThreeVector baryon_curl_vecj = jB.curl_vecj();
2945  if (potentials_->use_skyrme()) {
2946  (*UB_lat_)[i] =
2947  flow_four_velocity_B * potentials_->skyrme_pot(baryon_density);
2948  (*FB_lat_)[i] =
2949  potentials_->skyrme_force(baryon_density, baryon_grad_j0,
2950  baryon_dvecj_dt, baryon_curl_vecj);
2951  }
2952  if (potentials_->use_symmetry() && jmu_I3_lat_ != nullptr) {
2953  auto jI3 = (*jmu_I3_lat_)[i];
2954  const FourVector flow_four_velocity_I3 =
2955  std::abs(jI3.rho()) > very_small_double
2956  ? jI3.jmu_net() / jI3.rho()
2957  : FourVector();
2958  (*UI3_lat_)[i] = flow_four_velocity_I3 *
2959  potentials_->symmetry_pot(jI3.rho(), baryon_density);
2960  (*FI3_lat_)[i] = potentials_->symmetry_force(
2961  jI3.rho(), jI3.grad_j0(), jI3.dvecj_dt(), jI3.curl_vecj(),
2962  baryon_density, baryon_grad_j0, baryon_dvecj_dt,
2963  baryon_curl_vecj);
2964  }
2965  }
2966  }
2967  if (potentials_->use_coulomb()) {
2970  density_param_, ensembles_, true);
2971  for (size_t i = 0; i < EM_lat_->size(); i++) {
2972  ThreeVector electric_field = {0., 0., 0.};
2973  ThreeVector position = jmu_el_lat_->cell_center(i);
2974  jmu_el_lat_->integrate_volume(electric_field,
2976  potentials_->coulomb_r_cut(), position);
2977  ThreeVector magnetic_field = {0., 0., 0.};
2978  jmu_el_lat_->integrate_volume(magnetic_field,
2980  potentials_->coulomb_r_cut(), position);
2981  (*EM_lat_)[i] = std::make_pair(electric_field, magnetic_field);
2982  }
2983  } // if ((potentials_->use_skyrme() || ...
2984  if (potentials_->use_vdf() && jmu_B_lat_ != nullptr) {
2989  parameters_.labclock->timestep_duration(), true);
2992  fields_lat_.get(), old_fields_auxiliary_.get(),
2995  parameters_.labclock->timestep_duration());
2996  }
2997  const size_t UBlattice_size = UB_lat_->size();
2998  for (size_t i = 0; i < UBlattice_size; i++) {
2999  auto jB = (*jmu_B_lat_)[i];
3000  (*UB_lat_)[i] = potentials_->vdf_pot(jB.rho(), jB.jmu_net());
3003  (*FB_lat_)[i] = potentials_->vdf_force(
3004  jB.rho(), jB.drho_dxnu().x0(), jB.drho_dxnu().threevec(),
3005  jB.grad_rho_cross_vecj(), jB.jmu_net().x0(), jB.grad_j0(),
3006  jB.jmu_net().threevec(), jB.dvecj_dt(), jB.curl_vecj());
3007  break;
3009  auto Amu = (*fields_lat_)[i];
3010  (*FB_lat_)[i] = potentials_->vdf_force(
3011  Amu.grad_A0(), Amu.dvecA_dt(), Amu.curl_vecA());
3012  break;
3013  }
3014  } // for (size_t i = 0; i < UBlattice_size; i++)
3015  } // if potentials_->use_vdf()
3016  }
3017 }
std::unique_ptr< RectangularLattice< FourVector > > new_fields_auxiliary_
Auxiliary lattice for values of Amu at a time step t0 + dt.
Definition: experiment.h:503
std::unique_ptr< RectangularLattice< std::array< FourVector, 4 > > > fields_four_gradient_auxiliary_
Auxiliary lattice for calculating the four-gradient of Amu.
Definition: experiment.h:506
std::unique_ptr< FieldsLattice > fields_lat_
Mean-field A^mu on the lattice.
Definition: experiment.h:448
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...
Definition: experiment.h:466
std::unique_ptr< RectangularLattice< FourVector > > old_fields_auxiliary_
Auxiliary lattice for values of Amu at a time step t0.
Definition: experiment.h:501
std::unique_ptr< DensityLattice > jmu_el_lat_
Electric charge density on the lattice.
Definition: experiment.h:445
static ThreeVector B_field_integrand(ThreeVector pos, DensityOnLattice &charge_density, ThreeVector point)
Integrand for calculating the magnetic field using the Biot-Savart formula.
Definition: potentials.h:383
static ThreeVector E_field_integrand(ThreeVector pos, DensityOnLattice &charge_density, ThreeVector point)
Integrand for calculating the electric field.
Definition: potentials.h:365
constexpr double very_small_double
A very small double, used to avoid division by zero.
Definition: constants.h:44
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.
Definition: fields.cc:14
FieldDerivativesMode field_derivatives_mode
mode of calculating field derivatives

◆ compute_min_cell_length()

template<typename Modus >
double smash::Experiment< Modus >::compute_min_cell_length ( double  dt) const
inlineprivate

Calculate the minimal size for the grid cells such that the ScatterActionsFinder will find all collisions within the maximal transverse distance (which is determined by the maximal cross section).

Parameters
[in]dtThe current time step size [fm]
Returns
The minimal required size of cells

Definition at line 342 of file experiment.h.

342  {
345  }
346  return std::sqrt(4 * dt * dt + max_transverse_distance_sqr_);
347  }
double fixed_min_cell_length
Fixed minimal grid cell length (in fm).

◆ next_output_time()

template<typename Modus >
double smash::Experiment< Modus >::next_output_time ( ) const
inlineprivate

Shortcut for next output time.

Definition at line 350 of file experiment.h.

350  {
351  return parameters_.outputclock->next_time();
352  }

◆ count_nonempty_ensembles()

template<typename Modus >
void smash::Experiment< Modus >::count_nonempty_ensembles
private

Counts the number of ensembles in wich interactions took place at the end of an event.

Definition at line 3212 of file experiment.h.

3212  {
3213  for (bool has_interaction : projectile_target_interact_) {
3214  if (has_interaction) {
3216  }
3217  }
3218 }
int nonempty_ensembles_
Number of ensembles containing an interaction.
Definition: experiment.h:577

◆ is_finished()

template<typename Modus >
bool smash::Experiment< Modus >::is_finished
private

Checks wether the desired number events have been calculated.

Returns
wether the experiment is is_finished

Definition at line 3221 of file experiment.h.

3221  {
3223  return event_ >= nevents_;
3224  }
3227  return true;
3228  }
3229  if (event_ >= max_events_) {
3230  logg[LExperiment].warn()
3231  << "Maximum number of events (" << max_events_
3232  << ") exceeded. Stopping calculation. "
3233  << "The fraction of empty ensembles is "
3234  << (1.0 - static_cast<double>(nonempty_ensembles_) /
3236  << ". If this fraction is expected, try increasing the "
3237  "Maximum_Ensembles_Run.";
3238  return true;
3239  }
3240  return false;
3241  }
3242  throw std::runtime_error("Event counting option is invalid");
3243  return false;
3244 }
int minimum_nonempty_ensembles_
The number of ensembles, in which interactions take place, to be calculated.
Definition: experiment.h:563
int max_events_
Maximum number of events to be calculated in order obtain the desired number of non-empty events usin...
Definition: experiment.h:583
EventCounting event_counting_
The way in which the number of calculated events is specified.
Definition: experiment.h:571
int nevents_
Number of events.
Definition: experiment.h:553
@ FixedNumber
The desired number of events is simulated disregarding of whether an interaction took place.
@ MinimumNonEmpty
Events are simulated until there are at least a given number of ensembles in which an interaction too...

Friends And Related Function Documentation

◆ ExperimentBase

template<typename Modus >
friend class ExperimentBase
friend

Definition at line 193 of file experiment.h.

Member Data Documentation

◆ parameters_

template<typename Modus >
ExperimentParameters smash::Experiment< Modus >::parameters_
private

Struct of several member variables.

These variables are combined into a struct for efficient input to functions outside of this class.

Definition at line 372 of file experiment.h.

◆ density_param_

template<typename Modus >
DensityParameters smash::Experiment< Modus >::density_param_
private

Structure to precalculate and hold parameters for density computations.

Definition at line 375 of file experiment.h.

◆ modus_

template<typename Modus >
Modus smash::Experiment< Modus >::modus_
private

Instance of the Modus template parameter.

May store modus-specific data and contains modus-specific function implementations.

Definition at line 381 of file experiment.h.

◆ ensembles_

template<typename Modus >
std::vector<Particles> smash::Experiment< Modus >::ensembles_
private

Complete particle list, all ensembles in one vector.

Definition at line 384 of file experiment.h.

◆ potentials_

template<typename Modus >
std::unique_ptr<Potentials> smash::Experiment< Modus >::potentials_
private

An instance of potentials class, that stores parameters of potentials, calculates them and their gradients.

Definition at line 390 of file experiment.h.

◆ pauli_blocker_

template<typename Modus >
std::unique_ptr<PauliBlocker> smash::Experiment< Modus >::pauli_blocker_
private

An instance of PauliBlocker class that stores parameters needed for Pauli blocking calculations and computes phase-space density.

Definition at line 396 of file experiment.h.

◆ outputs_

template<typename Modus >
OutputsList smash::Experiment< Modus >::outputs_
private

A list of output formaters.

They will be called to write the state of the particles to file.

Definition at line 402 of file experiment.h.

◆ dilepton_output_

template<typename Modus >
OutputPtr smash::Experiment< Modus >::dilepton_output_
private

The Dilepton output.

Definition at line 405 of file experiment.h.

◆ photon_output_

template<typename Modus >
OutputPtr smash::Experiment< Modus >::photon_output_
private

The Photon output.

Definition at line 408 of file experiment.h.

◆ projectile_target_interact_

template<typename Modus >
std::vector<bool> smash::Experiment< Modus >::projectile_target_interact_
private

Whether the projectile and the target collided.

One value for each ensemble.

Definition at line 414 of file experiment.h.

◆ beam_momentum_

template<typename Modus >
std::vector<FourVector> smash::Experiment< Modus >::beam_momentum_ = {}
private

The initial nucleons in the ColliderModus propagate with beam_momentum_, if Fermi motion is frozen.

It's only valid in the ColliderModus, so is set as an empty vector by default.

Definition at line 421 of file experiment.h.

◆ action_finders_

template<typename Modus >
std::vector<std::unique_ptr<ActionFinderInterface> > smash::Experiment< Modus >::action_finders_
private

The Action finder objects.

Definition at line 424 of file experiment.h.

◆ dilepton_finder_

template<typename Modus >
std::unique_ptr<DecayActionsFinderDilepton> smash::Experiment< Modus >::dilepton_finder_
private

The Dilepton Action Finder.

Definition at line 427 of file experiment.h.

◆ photon_finder_

template<typename Modus >
std::unique_ptr<ActionFinderInterface> smash::Experiment< Modus >::photon_finder_
private

The (Scatter) Actions Finder for Direct Photons.

Definition at line 430 of file experiment.h.

◆ n_fractional_photons_

template<typename Modus >
int smash::Experiment< Modus >::n_fractional_photons_
private

Number of fractional photons produced per single reaction.

Definition at line 433 of file experiment.h.

◆ j_QBS_lat_

template<typename Modus >
std::unique_ptr<DensityLattice> smash::Experiment< Modus >::j_QBS_lat_
private

4-current for j_QBS lattice output

Definition at line 436 of file experiment.h.

◆ jmu_B_lat_

template<typename Modus >
std::unique_ptr<DensityLattice> smash::Experiment< Modus >::jmu_B_lat_
private

Baryon density on the lattice.

Definition at line 439 of file experiment.h.

◆ jmu_I3_lat_

template<typename Modus >
std::unique_ptr<DensityLattice> smash::Experiment< Modus >::jmu_I3_lat_
private

Isospin projection density on the lattice.

Definition at line 442 of file experiment.h.

◆ jmu_el_lat_

template<typename Modus >
std::unique_ptr<DensityLattice> smash::Experiment< Modus >::jmu_el_lat_
private

Electric charge density on the lattice.

Definition at line 445 of file experiment.h.

◆ fields_lat_

template<typename Modus >
std::unique_ptr<FieldsLattice> smash::Experiment< Modus >::fields_lat_
private

Mean-field A^mu on the lattice.

Definition at line 448 of file experiment.h.

◆ jmu_custom_lat_

template<typename Modus >
std::unique_ptr<DensityLattice> smash::Experiment< Modus >::jmu_custom_lat_
private

Custom density on the lattices.

In the config user asks for some kind of density for printout. Baryon and isospin projection density are anyway needed for potentials. If user asks for some other density type for printout, it will be handled using jmu_custom variable.

Definition at line 457 of file experiment.h.

◆ dens_type_lattice_printout_

template<typename Modus >
DensityType smash::Experiment< Modus >::dens_type_lattice_printout_ = DensityType::None
private

Type of density for lattice printout.

Definition at line 460 of file experiment.h.

◆ UB_lat_

template<typename Modus >
std::unique_ptr<RectangularLattice<FourVector> > smash::Experiment< Modus >::UB_lat_ = nullptr
private

Lattices for Skyrme or VDF potentials (evaluated in the local rest frame) times the baryon flow 4-velocity.

Definition at line 466 of file experiment.h.

◆ UI3_lat_

template<typename Modus >
std::unique_ptr<RectangularLattice<FourVector> > smash::Experiment< Modus >::UI3_lat_ = nullptr
private

Lattices for symmetry potentials (evaluated in the local rest frame) times the isospin flow 4-velocity.

Definition at line 472 of file experiment.h.

◆ FB_lat_

template<typename Modus >
std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector> > > smash::Experiment< Modus >::FB_lat_
private

Lattices for the electric and magnetic components of the Skyrme or VDF force.

Definition at line 479 of file experiment.h.

◆ FI3_lat_

template<typename Modus >
std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector> > > smash::Experiment< Modus >::FI3_lat_
private

Lattices for the electric and magnetic component of the symmetry force.

Definition at line 483 of file experiment.h.

◆ EM_lat_

template<typename Modus >
std::unique_ptr<RectangularLattice<std::pair<ThreeVector, ThreeVector> > > smash::Experiment< Modus >::EM_lat_
private

Lattices for electric and magnetic field in fm^-2.

Definition at line 487 of file experiment.h.

◆ Tmn_

template<typename Modus >
std::unique_ptr<RectangularLattice<EnergyMomentumTensor> > smash::Experiment< Modus >::Tmn_
private

Lattices of energy-momentum tensors for printout.

Definition at line 490 of file experiment.h.

◆ old_jmu_auxiliary_

template<typename Modus >
std::unique_ptr<RectangularLattice<FourVector> > smash::Experiment< Modus >::old_jmu_auxiliary_
private

Auxiliary lattice for values of jmu at a time step t0.

Definition at line 493 of file experiment.h.

◆ new_jmu_auxiliary_

template<typename Modus >
std::unique_ptr<RectangularLattice<FourVector> > smash::Experiment< Modus >::new_jmu_auxiliary_
private

Auxiliary lattice for values of jmu at a time step t0 + dt.

Definition at line 495 of file experiment.h.

◆ four_gradient_auxiliary_

template<typename Modus >
std::unique_ptr<RectangularLattice<std::array<FourVector, 4> > > smash::Experiment< Modus >::four_gradient_auxiliary_
private

Auxiliary lattice for calculating the four-gradient of jmu.

Definition at line 498 of file experiment.h.

◆ old_fields_auxiliary_

template<typename Modus >
std::unique_ptr<RectangularLattice<FourVector> > smash::Experiment< Modus >::old_fields_auxiliary_
private

Auxiliary lattice for values of Amu at a time step t0.

Definition at line 501 of file experiment.h.

◆ new_fields_auxiliary_

template<typename Modus >
std::unique_ptr<RectangularLattice<FourVector> > smash::Experiment< Modus >::new_fields_auxiliary_
private

Auxiliary lattice for values of Amu at a time step t0 + dt.

Definition at line 503 of file experiment.h.

◆ fields_four_gradient_auxiliary_

template<typename Modus >
std::unique_ptr<RectangularLattice<std::array<FourVector, 4> > > smash::Experiment< Modus >::fields_four_gradient_auxiliary_
private

Auxiliary lattice for calculating the four-gradient of Amu.

Definition at line 506 of file experiment.h.

◆ printout_rho_eckart_

template<typename Modus >
bool smash::Experiment< Modus >::printout_rho_eckart_ = false
private

Whether to print the Eckart rest frame density.

Definition at line 509 of file experiment.h.

◆ printout_tmn_

template<typename Modus >
bool smash::Experiment< Modus >::printout_tmn_ = false
private

Whether to print the energy-momentum tensor.

Definition at line 512 of file experiment.h.

◆ printout_tmn_landau_

template<typename Modus >
bool smash::Experiment< Modus >::printout_tmn_landau_ = false
private

Whether to print the energy-momentum tensor in Landau frame.

Definition at line 515 of file experiment.h.

◆ printout_v_landau_

template<typename Modus >
bool smash::Experiment< Modus >::printout_v_landau_ = false
private

Whether to print the 4-velocity in Landau frame.

Definition at line 518 of file experiment.h.

◆ printout_j_QBS_

template<typename Modus >
bool smash::Experiment< Modus >::printout_j_QBS_ = false
private

Whether to print the Q, B, S 4-currents.

Definition at line 521 of file experiment.h.

◆ printout_lattice_td_

template<typename Modus >
bool smash::Experiment< Modus >::printout_lattice_td_ = false
private

Whether to print the thermodynamics quantities evaluated on the lattices.

Definition at line 524 of file experiment.h.

◆ printout_full_lattice_any_td_

template<typename Modus >
bool smash::Experiment< Modus >::printout_full_lattice_any_td_ = false
private

Whether to print the thermodynamics quantities evaluated on the lattices, point by point, in any format.

Definition at line 528 of file experiment.h.

◆ thermalizer_

template<typename Modus >
std::unique_ptr<GrandCanThermalizer> smash::Experiment< Modus >::thermalizer_
private

Instance of class used for forced thermalization.

Definition at line 531 of file experiment.h.

◆ process_string_ptr_

template<typename Modus >
StringProcess* smash::Experiment< Modus >::process_string_ptr_
private

Pointer to the string process class object, which is used to set the random seed for PYTHIA objects in each event.

Definition at line 537 of file experiment.h.

◆ nevents_

template<typename Modus >
int smash::Experiment< Modus >::nevents_ = 0
private

Number of events.

Event is a single simulation of a physical phenomenon: elementary particle or nucleus-nucleus collision. Result of a single SMASH event is random (by construction) as well as result of one collision in nature. To compare simulation with experiment one has to take ensemble averages, i.e. perform simulation and real experiment many times and compare average results.

nevents_ is number of times single phenomenon (particle or nucleus-nucleus collision) will be simulated.

Definition at line 553 of file experiment.h.

◆ minimum_nonempty_ensembles_

template<typename Modus >
int smash::Experiment< Modus >::minimum_nonempty_ensembles_ = 0
private

The number of ensembles, in which interactions take place, to be calculated.

Can be specified as an inout instead of the number of events. In this case events will be calculated until this number of ensembles is reached.

Definition at line 563 of file experiment.h.

◆ event_counting_

template<typename Modus >
EventCounting smash::Experiment< Modus >::event_counting_ = EventCounting::Invalid
private

The way in which the number of calculated events is specified.

Can be either a fixed number of simulated events or a minimum number of events that contain interactions.

Definition at line 571 of file experiment.h.

◆ event_

template<typename Modus >
int smash::Experiment< Modus >::event_ = 0
private

Current event.

Definition at line 574 of file experiment.h.

◆ nonempty_ensembles_

template<typename Modus >
int smash::Experiment< Modus >::nonempty_ensembles_ = 0
private

Number of ensembles containing an interaction.

Definition at line 577 of file experiment.h.

◆ max_events_

template<typename Modus >
int smash::Experiment< Modus >::max_events_ = 0
private

Maximum number of events to be calculated in order obtain the desired number of non-empty events using the MinimumNonemptyEnsembles option.

Definition at line 583 of file experiment.h.

◆ end_time_

template<typename Modus >
const double smash::Experiment< Modus >::end_time_
private

simulation time at which the evolution is stopped.

Definition at line 586 of file experiment.h.

◆ delta_time_startup_

template<typename Modus >
const double smash::Experiment< Modus >::delta_time_startup_
private

The clock's timestep size at start up.

Stored here so that the next event will remember this.

Definition at line 593 of file experiment.h.

◆ force_decays_

template<typename Modus >
const bool smash::Experiment< Modus >::force_decays_
private

This indicates whether we force all resonances to decay in the last timestep.

Definition at line 599 of file experiment.h.

◆ use_grid_

template<typename Modus >
const bool smash::Experiment< Modus >::use_grid_
private

This indicates whether to use the grid.

Definition at line 602 of file experiment.h.

◆ metric_

template<typename Modus >
const ExpansionProperties smash::Experiment< Modus >::metric_
private

This struct contains information on the metric to be used.

Definition at line 605 of file experiment.h.

◆ dileptons_switch_

template<typename Modus >
const bool smash::Experiment< Modus >::dileptons_switch_
private

This indicates whether dileptons are switched on.

Definition at line 608 of file experiment.h.

◆ photons_switch_

template<typename Modus >
const bool smash::Experiment< Modus >::photons_switch_
private

This indicates whether photons are switched on.

Definition at line 611 of file experiment.h.

◆ bremsstrahlung_switch_

template<typename Modus >
const bool smash::Experiment< Modus >::bremsstrahlung_switch_
private

This indicates whether bremsstrahlung is switched on.

Definition at line 614 of file experiment.h.

◆ IC_switch_

template<typename Modus >
const bool smash::Experiment< Modus >::IC_switch_
private

This indicates whether the experiment will be used as initial condition for hydrodynamics.

Currently only the Collider modus can achieve this.

Definition at line 620 of file experiment.h.

◆ IC_dynamic_

template<typename Modus >
const bool smash::Experiment< Modus >::IC_dynamic_
private

This indicates if the IC is dynamic.

Definition at line 623 of file experiment.h.

◆ time_step_mode_

template<typename Modus >
const TimeStepMode smash::Experiment< Modus >::time_step_mode_
private

This indicates whether to use time steps.

Definition at line 626 of file experiment.h.

◆ max_transverse_distance_sqr_

template<typename Modus >
double smash::Experiment< Modus >::max_transverse_distance_sqr_ = std::numeric_limits<double>::max()
private

Maximal distance at which particles can interact in case of the geometric criterion, squared.

Definition at line 632 of file experiment.h.

◆ conserved_initial_

template<typename Modus >
QuantumNumbers smash::Experiment< Modus >::conserved_initial_
private

The conserved quantities of the system.

This struct carries the sums of the single particle's various quantities as measured at the beginning of the evolution and can be used to regularly check if they are still good.

Definition at line 641 of file experiment.h.

◆ initial_mean_field_energy_

template<typename Modus >
double smash::Experiment< Modus >::initial_mean_field_energy_
private

The initial total mean field energy in the system.

Note: will only be calculated if lattice is on.

Definition at line 647 of file experiment.h.

◆ time_start_

template<typename Modus >
SystemTimePoint smash::Experiment< Modus >::time_start_ = SystemClock::now()
private

system starting time of the simulation

Definition at line 650 of file experiment.h.

◆ dens_type_

template<typename Modus >
DensityType smash::Experiment< Modus >::dens_type_ = DensityType::None
private

Type of density to be written to collision headers.

Definition at line 653 of file experiment.h.

◆ interactions_total_

template<typename Modus >
uint64_t smash::Experiment< Modus >::interactions_total_ = 0
private

Total number of interactions for current timestep.

For timestepless mode the whole run time is considered as one timestep.

Definition at line 659 of file experiment.h.

◆ previous_interactions_total_

template<typename Modus >
uint64_t smash::Experiment< Modus >::previous_interactions_total_ = 0
private

Total number of interactions for previous timestep.

For timestepless mode the whole run time is considered as one timestep.

Definition at line 665 of file experiment.h.

◆ wall_actions_total_

template<typename Modus >
uint64_t smash::Experiment< Modus >::wall_actions_total_ = 0
private

Total number of wall-crossings for current timestep.

For timestepless mode the whole run time is considered as one timestep.

Definition at line 671 of file experiment.h.

◆ previous_wall_actions_total_

template<typename Modus >
uint64_t smash::Experiment< Modus >::previous_wall_actions_total_ = 0
private

Total number of wall-crossings for previous timestep.

For timestepless mode the whole run time is considered as one timestep.

Definition at line 677 of file experiment.h.

◆ total_pauli_blocked_

template<typename Modus >
uint64_t smash::Experiment< Modus >::total_pauli_blocked_ = 0
private

Total number of Pauli-blockings for current timestep.

For timestepless mode the whole run time is considered as one timestep.

Definition at line 683 of file experiment.h.

◆ total_hypersurface_crossing_actions_

template<typename Modus >
uint64_t smash::Experiment< Modus >::total_hypersurface_crossing_actions_ = 0
private

Total number of particles removed from the evolution in hypersurface crossing actions.

Definition at line 689 of file experiment.h.

◆ discarded_interactions_total_

template<typename Modus >
uint64_t smash::Experiment< Modus >::discarded_interactions_total_ = 0
private

Total number of discarded interactions, because they were invalidated before they could be performed.

Definition at line 695 of file experiment.h.

◆ total_energy_removed_

template<typename Modus >
double smash::Experiment< Modus >::total_energy_removed_ = 0.0
private

Total energy removed from the system in hypersurface crossing actions.

Definition at line 700 of file experiment.h.

◆ total_energy_violated_by_Pythia_

template<typename Modus >
double smash::Experiment< Modus >::total_energy_violated_by_Pythia_ = 0.0
private

Total energy violation introduced by Pythia.

Definition at line 705 of file experiment.h.

◆ kinematic_cuts_for_IC_output_

template<typename Modus >
bool smash::Experiment< Modus >::kinematic_cuts_for_IC_output_ = false
private

This indicates whether kinematic cuts are enabled for the IC output.

Definition at line 708 of file experiment.h.

◆ seed_

template<typename Modus >
int64_t smash::Experiment< Modus >::seed_ = -1
private

random seed for the next event.

Definition at line 711 of file experiment.h.


The documentation for this class was generated from the following file: