33 static constexpr
int LCollider = LogArea::Collider::id;
49 bool same_file =
false;
59 logg[
LCollider].info() <<
"Projectile is alpha-clustered with woods-saxon "
60 "parameters for the He-clusters listed below.";
67 throw ColliderEmpty(
"Input Error: Projectile nucleus is empty.");
78 logg[
LCollider].info() <<
"Target is alpha-clustered with woods-saxon "
79 "parameters for the He-clusters listed below.";
103 int energy_input = 0;
105 const double mass_target =
target_->mass();
107 const double mass_a =
109 const double mass_b =
target_->mass() /
target_->number_of_particles();
116 "Input Error: sqrt(s_NN) is not larger than masses:\n" +
122 mass_projec * mass_target / (mass_a * mass_b) +
123 mass_projec * mass_projec + mass_target * mass_target;
133 "E_Tot must be nonnegative.");
137 mass_projec, mass_target);
148 "E_Kin must be nonnegative.");
152 mass_projec, mass_target);
162 "P_Lab must be nonnegative.");
166 mass_projec, mass_target);
173 const double e_tot_p =
176 if (e_tot_p < 0 || e_tot_t < 0) {
179 "E_Tot must be nonnegative.");
182 e_tot_t *
target_->number_of_particles(),
183 mass_projec, mass_target);
190 const double e_kin_p =
193 if (e_kin_p < 0 || e_kin_t < 0) {
196 "E_Kin must be nonnegative.");
199 e_kin_t *
target_->number_of_particles(),
200 mass_projec, mass_target);
207 const double p_lab_p =
210 if (p_lab_p < 0 || p_lab_t < 0) {
213 "P_Lab must be nonnegative.");
216 p_lab_t *
target_->number_of_particles(),
217 mass_projec, mass_target);
221 if (energy_input == 0) {
222 throw std::domain_error(
223 "Input Error: Non-existent collision energy. "
224 "Please provide one of Sqrtsnn/E_Kin/P_Lab.");
226 if (energy_input > 1) {
227 throw std::invalid_argument(
228 "Input Error: Redundant collision energy. "
229 "Please provide only one of Sqrtsnn/E_Kin/P_Lab.");
245 throw std::invalid_argument(
246 "Input Error: Need impact parameter spectrum for custom sampling."
247 " Please provide Values and Yields.");
249 const std::vector<double> impacts =
251 const std::vector<double> yields =
253 if (impacts.size() != yields.size()) {
254 throw std::invalid_argument(
255 "Input Error: Need as many impact parameter values as yields. "
256 "Please make sure that Values and Yields have the same length.");
261 const auto imp_minmax =
262 std::minmax_element(impacts.begin(), impacts.end());
265 yield_max_ = *std::max_element(yields.begin(), yields.end());
269 const std::array<double, 2> range =
313 double threshold = modus_cfg.
take(
321 double form_time_fraction = modus_cfg.
take(
323 if (threshold <= 0 || max_time < min_time || min_time < 0 || cells < 2 ||
324 form_time_fraction < 0) {
326 <<
"Bad parameters chosen for dynamic initial conditions. At least "
327 "one of the following inequalities is violated:\n"
328 <<
" Energy_Density_Threshold = " << threshold <<
" > 0\n"
329 <<
" Maximum_Time = " << max_time <<
" > " << min_time
330 <<
" = Minimum_Time > 0\n"
331 "Fluidization_Cells = "
333 <<
" Formation_Time_Fraction < 0";
334 throw std::invalid_argument(
"Please adjust the configuration file.");
340 double min_size = std::max(min_time, 40.);
341 std::array<double, 3>
length{2 * min_size, 2 * min_size, 2 * min_size};
342 std::array<double, 3> origin{-min_size, -min_size, -min_size};
343 std::array<int, 3> cell_array{cells, cells, cells};
346 std::make_unique<RectangularLattice<EnergyMomentumTensor>>(
355 <<
"Preparing dynamic Initial Conditions with threshold " << threshold
356 <<
" GeV/fm³ in energy density, between " << min_time <<
" and "
357 << max_time <<
" fm.";
368 bool bad_cuts =
false;
373 if (rapidity < 0.0) {
375 <<
"Rapidity cut for initial conditions configured as |y| < "
377 <<
" is unreasonable. \nPlease choose a positive, non-zero value or "
378 "employ SMASH without rapidity cut.";
383 <<
"Transverse momentum cut for initial conditions configured as pT < "
385 <<
" is unreasonable. \nPlease choose a positive, non-zero value or "
386 "employ SMASH without pT cut.";
390 throw std::runtime_error(
391 "Kinematic cut for initial conditions malconfigured.");
394 std::ostringstream message{
"Extracting iso-tau initial conditions ",
396 std::vector<std::string> cuts{};
397 if (rapidity > 0.0) {
398 cuts.emplace_back(
"|y| <= ");
402 cuts.emplace_back(
"pT <= ");
405 if (cuts.size() > 0) {
406 message <<
"in kinematic range: " <<
join(cuts,
"; ") <<
".";
408 message <<
"without kinematic cuts.";
414 return out <<
"-- Collider Modus:\n"
415 <<
"sqrt(S) (nucleus-nucleus) = "
424 Configuration &nucleus_cfg,
int ntest,
const std::string &nucleus_type) {
427 const auto &[automatic_key, beta2_key, beta3_key, beta4_key,
428 gamma_key] = [&is_projectile]() {
444 bool automatic_deformation = nucleus_cfg.
take(automatic_key);
445 bool was_any_beta_given = nucleus_cfg.
has_value(beta2_key) ||
448 bool was_any_deformation_parameter_given =
449 was_any_beta_given || nucleus_cfg.
has_value(gamma_key);
450 bool was_gamma_given_without_beta_2 =
453 if (automatic_deformation && was_any_deformation_parameter_given) {
454 throw std::invalid_argument(
455 "Automatic deformation of " + nucleus_type +
456 " nucleus requested, but deformation parameter(s) were provided as"
457 " well. Please, check the 'Deformed' section in your input file.");
458 }
else if (!automatic_deformation && !was_any_beta_given) {
459 throw std::invalid_argument(
460 "Manual deformation of " + nucleus_type +
461 " nucleus requested, but no deformation beta parameter was provided."
462 " Please, check the 'Deformed' section in your input file.");
463 }
else if (!automatic_deformation && was_gamma_given_without_beta_2) {
464 throw std::invalid_argument(
465 "Manual deformation of " + nucleus_type +
466 " nucleus requested, but 'Gamma' parameter was provided without "
467 "providing a value of 'Beta_2' having hence no deformation effect. "
468 "Please, check the 'Deformed' section in your input file.");
470 return std::make_unique<DeformedNucleus>(nucleus_cfg, ntest,
471 automatic_deformation);
475 std::unique_ptr<AlphaClusteredNucleus>
478 const std::string &nucleus_type) {
480 const auto &[automatic_key, side_length_key] = [&is_projectile]() {
484 modi_collider_projectile_alphaClustered_automatic,
486 modi_collider_projectile_alphaClustered_sideLength)
492 bool automatic_alphaclustering = nucleus_cfg.
take(automatic_key);
493 bool was_sidelength_given = nucleus_cfg.
has_value(side_length_key);
495 if (automatic_alphaclustering && was_sidelength_given) {
496 throw std::invalid_argument(
497 "Automatic alpha-clustering of " + nucleus_type +
498 " nucleus requested, but a sidelength was provided as"
499 " well. Please, check the 'Alpha_Clustered' section in your input "
501 }
else if (!automatic_alphaclustering && !was_sidelength_given) {
502 throw std::invalid_argument(
503 "Manual alpha-clustering of " + nucleus_type +
504 " nucleus requested, but no sidelength was provided."
505 " Please, check the 'Alpha_Clustered' section in your input file.");
507 return std::make_unique<AlphaClusteredNucleus>(nucleus_cfg, ntest,
508 automatic_alphaclustering);
526 if (v_a >= 1.0 || v_b >= 1.0) {
527 throw std::domain_error(
528 "Found velocity equal to or larger than 1 in "
529 "ColliderModus::initial_conditions.\nConsider using "
530 "the center of velocity reference frame.");
546 target_->generate_fermi_momenta();
549 throw std::invalid_argument(
"Invalid Fermi_Motion input.");
559 const double d_a = std::max(0.,
projectile_->get_diffusiveness());
560 const double d_b = std::max(0.,
target_->get_diffusiveness());
561 const double r_a =
projectile_->get_nuclear_radius();
562 const double r_b =
target_->get_nuclear_radius();
565 const double simulation_time = -dz / std::abs(v_a);
566 const double proj_z = -dz - std::sqrt(1.0 - v_a * v_a) * (r_a + d_a);
567 const double targ_z =
568 +dz * std::abs(v_b / v_a) + std::sqrt(1.0 - v_b * v_b) * (r_b + d_b);
578 target_->copy_particles(particles);
580 return simulation_time;
589 p.set_3position(pos);
590 p.set_3momentum(mom);
607 double probability_random = 1;
608 double probability = 0;
610 while (probability_random > probability) {
612 probability = (*impact_interpolation_)(b) /
yield_max_;
613 assert(probability < 1.);
638 v_a =
pCM / std::sqrt(m_a * m_a +
pCM *
pCM);
639 v_b = -
pCM / std::sqrt(m_b * m_b +
pCM *
pCM);
645 throw std::invalid_argument(
646 "Invalid reference frame in "
647 "ColliderModus::get_velocities.");
649 return std::make_pair(v_a, v_b);
653 const std::string &file_name) {
655 if (file_directory.back() ==
'/') {
656 return file_directory + file_name;
658 return file_directory +
'/' + file_name;
671 std::string projectile_file_directory = proj_config.
read(
673 std::string target_file_directory =
675 std::string projectile_file_name =
677 std::string target_file_name =
680 std::string proj_path =
682 std::string targ_path =
684 if (proj_path == targ_path) {
692 const double t,
const std::vector<Particles> &ensembles,
695 throw std::logic_error(
696 "Trying to build fluidization lattice with unset pointer in "
699 if (t < IC_parameters_->min_time.value() ||
703 const double resizing_rate = 5;
706 side += resizing_rate;
707 std::array<double, 3> new_length{2 * side, 2 * side, 2 * side};
708 std::array<double, 3> new_origin{-side, -side, -side};
709 fluid_lattice_->reset_and_resize(new_length, new_origin, std::nullopt);
710 logg[
LCollider].debug() <<
"Fluidization lattice resizing at " << t
711 <<
" fm to " << 2 * side <<
" fm";
716 dens_par, ensembles,
false);
ColliderModus: Provides a modus for colliding nuclei.
CalculationFrame frame_
Reference frame for the system, as specified from config.
double imp_min_
Minimum value of impact parameter.
double initial_z_displacement_
Initial z-displacement of nuclei.
bool IC_for_hybrid_
Whether the particles will serve as initial conditions for hydrodynamics.
double yield_max_
Maximum value of yield. Needed for custom impact parameter sampling.
bool random_reaction_plane_
Whether the reaction plane should be randomized.
void rotate_reaction_plane(double phi, Particles *particles)
Rotate the reaction plane about the angle phi.
std::pair< double, double > get_velocities(double mandelstam_s, double m_a, double m_b)
Get the frame dependent velocity for each nucleus, using the current reference frame.
void sample_impact()
Sample impact parameter.
std::unique_ptr< Nucleus > projectile_
Projectile.
std::unique_ptr< InterpolateDataLinear< double > > impact_interpolation_
Pointer to the impact parameter interpolation.
FermiMotion fermi_motion_
An option to include Fermi motion ("off", "on", "frozen")
static std::unique_ptr< AlphaClusteredNucleus > create_alphaclustered_nucleus(Configuration &nucleus_cfg, const int ntest, const std::string &nucleus_type)
Configure Alpha-Clustered Nucleus.
double velocity_projectile_
Beam velocity of the projectile.
Sampling sampling_
Method used for sampling of impact parameter.
std::unique_ptr< RectangularLattice< EnergyMomentumTensor > > fluid_lattice_
Energy-momentum tensor lattice for dynamic fluidization.
std::string custom_file_path(const std::string &file_directory, const std::string &file_name)
Creates full path string consisting of file_directory and file_name Needed to initialize a customnucl...
double total_s_
Center-of-mass energy squared of the nucleus-nucleus collision.
std::unique_ptr< Nucleus > target_
Target.
ColliderModus(Configuration modus_config, const ExperimentParameters ¶meters)
Constructor.
double impact_
Impact parameter.
double sqrt_s_NN_
Center-of-mass energy of a nucleon-nucleon collision.
double initial_conditions(Particles *particles, const ExperimentParameters ¶meters)
Generates initial state of the particles in the system.
void build_fluidization_lattice(double t, const std::vector< Particles > &ensembles, const DensityParameters &dens_par)
Build lattice of energy momentum tensor.
bool same_inputfile(Configuration &proj_config, Configuration &targ_config)
Checks if target and projectile are read from the same external file if they are both initialized as ...
std::unique_ptr< std::map< int32_t, double > > fluid_background_
Energy density background from hydrodynamic evolution, with particle indices as keys.
void validate_IC_kinematic_range()
Validate whether the input kinematic range for the Initial Conditions output is valid and inform the ...
static std::unique_ptr< DeformedNucleus > create_deformed_nucleus(Configuration &nucleus_cfg, const int ntest, const std::string &nucleus_type)
Configure Deformed Nucleus.
double velocity_target_
Beam velocity of the target.
std::unique_ptr< InitialConditionParameters > IC_parameters_
Plain Old Data type to hold parameters for initial conditions.
double imp_max_
Maximum value of impact parameter.
Interface to the SMASH configuration files.
T read(const Key< T > &key) const
Additional interface for SMASH to read configuration values without removing them.
bool has_value(const Key< T > &key) const
Return whether there is a non-empty value behind the requested key (which is supposed not to refer to...
bool has_section(const KeyLabels &labels) const
Return whether there is a (possibly empty) section with the given labels.
Configuration extract_complete_sub_configuration(KeyLabels section, Configuration::GetEmpty empty_if_not_existing=Configuration::GetEmpty::No)
Alternative method to extract a sub-configuration, which retains the labels from the top-level in the...
T take(const Key< T > &key)
The default interface for SMASH to read configuration values.
A class to pre-calculate and store parameters relevant for density calculation.
static bool remove_particle_
Whether fluidization actions remove the particle from the evolution.
Represent a piecewise linear interpolation.
ParticleData contains the dynamic information of a certain particle.
The Particles class abstracts the storage and manipulation of particles.
The ThreeVector class represents a physical three-vector with the components .
void rotate_around_z(double theta)
Rotate the vector around the z axis by the given angle theta.
@ On
Use fermi motion in combination with potentials.
@ Frozen
Use fermi motion without potentials.
@ Off
Don't use fermi motion.
@ ConstantTau
Hypersurface crossed at a fixed proper time.
@ Dynamic
Dynamic fluidization based on local densities.
@ Quadratic
Sample from areal / quadratic distribution.
@ Custom
Sample from custom, user-defined distribution.
@ Uniform
Sample from uniform distribution.
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
FormattingHelper< T > format(const T &value, const char *unit, int width=-1, int precision=-1)
Acts as a stream modifier for std::ostream to output an object with an optional suffix string and wit...
T pCM(const T sqrts, const T mass_a, const T mass_b) noexcept
static constexpr int LInitialConditions
double fixed_target_projectile_v(double s, double ma, double mb)
double s_from_Ekin(double e_kin, double m_P, double m_T)
Convert E_kin to Mandelstam-s for a fixed-target setup, with a projectile of mass m_P and a kinetic e...
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.
std::string join(const std::vector< std::string > &v, const std::string &delim)
Join strings using delimiter.
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
double center_of_velocity_v(double s, double ma, double mb)
bool has_projectile_or_target(const Configuration &config)
Find out whether a configuration has a projectile or a target sub-section.
bool is_about_projectile(const Configuration &config)
Find out whether a configuration is about projectile or target.
T pCM_from_s(const T s, const T mass_a, const T mass_b) noexcept
static constexpr int LCollider
double s_from_Etot(double e_tot, double m_P, double m_T)
Convert E_tot to Mandelstam-s for a fixed-target setup, with a projectile of mass m_P and a total ene...
double s_from_plab(double plab, double m_P, double m_T)
Convert p_lab to Mandelstam-s for a fixed-target setup, with a projectile of mass m_P and momentum pl...
Thrown when either projectile_ or target_ nuclei are empty.
Helper structure for Experiment.
int testparticles
Number of test-particles.
double gaussian_sigma
Width of gaussian Wigner density of particles.
Thrown when the requested energy is smaller than the masses of two particles.