264 if (modus_cfg.
has_value({
"Calculation_Frame"})) {
265 frame_ = modus_cfg.
take({
"Calculation_Frame"});
269 if (modus_cfg.
has_value({
"Collisions_Within_Nucleus"})) {
276 bool same_file =
false;
281 }
else if (proj_cfg.
has_value({
"Custom"})) {
284 make_unique<CustomNucleus>(proj_cfg, params.
testparticles, same_file);
289 throw ColliderEmpty(
"Input Error: Projectile nucleus is empty.");
295 }
else if (targ_cfg.
has_value({
"Custom"})) {
297 make_unique<CustomNucleus>(targ_cfg, params.
testparticles, same_file);
302 throw ColliderEmpty(
"Input Error: Target nucleus is empty.");
306 if (modus_cfg.
has_value({
"Fermi_Motion"})) {
315 int energy_input = 0;
317 const double mass_target =
target_->mass();
319 const double mass_a =
321 const double mass_b =
target_->mass() /
target_->number_of_particles();
328 "Input Error: sqrt(s_NN) is not larger than masses:\n" +
329 std::to_string(
sqrt_s_NN_) +
" GeV <= " + std::to_string(mass_a) +
330 " GeV + " + std::to_string(mass_b) +
" GeV.");
334 mass_projec * mass_target / (mass_a * mass_b) +
335 mass_projec * mass_projec + mass_target * mass_target;
341 const double e_kin = modus_cfg.
take({
"E_Kin"});
345 "E_Kin must be nonnegative.");
349 mass_projec, mass_target);
355 const double p_lab = modus_cfg.
take({
"P_Lab"});
359 "P_Lab must be nonnegative.");
363 mass_projec, mass_target);
367 if (energy_input == 0) {
368 throw std::domain_error(
369 "Input Error: Non-existent collision energy. " 370 "Please provide one of Sqrtsnn/E_Kin/P_Lab.");
372 if (energy_input > 1) {
373 throw std::domain_error(
374 "Input Error: Redundant collision energy. " 375 "Please provide only one of Sqrtsnn/E_Kin/P_Lab.");
380 if (modus_cfg.
has_value({
"Impact",
"Value"})) {
386 if (modus_cfg.
has_value({
"Impact",
"Sample"})) {
389 if (!(modus_cfg.
has_value({
"Impact",
"Values"}) ||
390 modus_cfg.
has_value({
"Impact",
"Yields"}))) {
391 throw std::domain_error(
392 "Input Error: Need impact parameter spectrum for custom " 394 "Please provide Values and Yields.");
396 const std::vector<double> impacts =
397 modus_cfg.
take({
"Impact",
"Values"});
398 const std::vector<double> yields = modus_cfg.
take({
"Impact",
"Yields"});
399 if (impacts.size() != yields.size()) {
400 throw std::domain_error(
401 "Input Error: Need as many impact parameter values as yields. " 402 "Please make sure that Values and Yields have the same length.");
407 const auto imp_minmax =
408 std::minmax_element(impacts.begin(), impacts.end());
411 yield_max_ = *std::max_element(yields.begin(), yields.end());
414 if (modus_cfg.
has_value({
"Impact",
"Range"})) {
415 const std::array<double, 2> range = modus_cfg.
take({
"Impact",
"Range"});
419 if (modus_cfg.
has_value({
"Impact",
"Max"})) {
427 if (modus_cfg.
has_value({
"Initial_Distance"})) {
436 return out <<
"-- Collider Modus:\n" 437 <<
"sqrt(S) (nucleus-nucleus) = " 446 Configuration &nucleus_cfg,
int ntest,
const std::string &nucleus_type) {
447 bool auto_deform = nucleus_cfg.
take({
"Deformed",
"Automatic"});
448 bool is_beta2 = nucleus_cfg.
has_value({
"Deformed",
"Beta_2"}) ?
true :
false;
449 bool is_beta4 = nucleus_cfg.
has_value({
"Deformed",
"Beta_4"}) ?
true :
false;
450 std::unique_ptr<DeformedNucleus> nucleus;
452 if ((auto_deform && (!is_beta2 && !is_beta4)) ||
453 (!auto_deform && (is_beta2 && is_beta4))) {
454 nucleus = make_unique<DeformedNucleus>(nucleus_cfg, ntest, auto_deform);
457 throw std::domain_error(
"Deformation of " + nucleus_type +
458 " nucleus not configured " 459 "properly, please check whether all necessary " 460 "parameters are set.");
466 const auto &log = logger<LogArea::Collider>();
469 log.info() <<
"Impact parameter = " <<
format(
impact_,
"fm");
482 if (v_a >= 1.0 || v_b >= 1.0) {
483 throw std::domain_error(
484 "Found velocity equal to or larger than 1 in " 485 "ColliderModus::initial_conditions.\nConsider using " 486 "the center of velocity reference frame.");
502 target_->generate_fermi_momenta();
504 log.info() <<
"Fermi motion is ON.";
506 log.info() <<
"FROZEN Fermi motion is on.";
510 log.info() <<
"Fermi motion is OFF.";
512 throw std::domain_error(
"Invalid Fermi_Motion input.");
522 const double d_a = std::max(0.,
projectile_->get_diffusiveness());
523 const double d_b = std::max(0.,
target_->get_diffusiveness());
524 const double r_a =
projectile_->get_nuclear_radius();
525 const double r_b =
target_->get_nuclear_radius();
528 const double simulation_time = -dz / std::abs(v_a);
529 const double proj_z = -dz - std::sqrt(1.0 - v_a * v_a) * (r_a + d_a);
530 const double targ_z =
531 +dz * std::abs(v_b / v_a) + std::sqrt(1.0 - v_b * v_b) * (r_b + d_b);
537 target_->copy_particles(particles);
538 return simulation_time;
554 double probability_random = 1;
555 double probability = 0;
557 while (probability_random > probability) {
559 probability = (*impact_interpolation_)(b) /
yield_max_;
560 assert(probability < 1.);
585 v_a = pCM / std::sqrt(m_a * m_a + pCM * pCM);
586 v_b = -pCM / std::sqrt(m_b * m_b + pCM * pCM);
592 throw std::domain_error(
593 "Invalid reference frame in " 594 "ColliderModus::get_velocities.");
596 return std::make_pair(v_a, v_b);
600 const std::string &file_name) {
602 if (file_directory.back() ==
'/') {
603 return file_directory + file_name;
605 return file_directory +
'/' + file_name;
614 if (!targ_config.
has_value({
"Custom"})) {
617 std::string projectile_file_directory =
618 proj_config.
read({
"Custom",
"File_Directory"});
619 std::string target_file_directory =
620 targ_config.
read({
"Custom",
"File_Directory"});
621 std::string projectile_file_name = proj_config.
read({
"Custom",
"File_Name"});
622 std::string target_file_name = targ_config.
read({
"Custom",
"File_Name"});
624 std::string proj_path =
626 std::string targ_path =
628 if (proj_path == targ_path) {
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...
double yield_max_
Maximum value of yield. Needed for custom impact parameter sampling.
Thrown when the requested energy is smaller than the masses of two particles.
double fixed_target_projectile_v(double s, double ma, double mb)
double velocity_target_
Beam velocity of the target.
static std::unique_ptr< DeformedNucleus > create_deformed_nucleus(Configuration &nucleus_cfg, const int ntest, const std::string &nucleus_type)
Configure Deformed Nucleus.
double center_of_velocity_v(double s, double ma, double mb)
double impact_
Impact parameter.
T pCM_from_s(const T s, const T mass_a, const T mass_b) noexcept
Value read(std::initializer_list< const char * > keys) const
Additional interface for SMASH to read configuration values without removing them.
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...
Interface to the SMASH configuration files.
std::unique_ptr< InterpolateDataLinear< double > > impact_interpolation_
Pointer to the impact parameter interpolation.
double imp_min_
Minimum value of impact parameter.
bool has_value(std::initializer_list< const char * > keys) const
Returns whether there is a non-empty value behind the requested keys.
Generic numerical functions.
ColliderModus(Configuration modus_config, const ExperimentParameters ¶meters)
Constructor.
std::unique_ptr< Nucleus > projectile_
Projectile.
Sample from uniform distribution.
Sampling sampling_
Method used for sampling of impact parameter.
Thrown when either projectile_ or target_ nuclei are empty.
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...
Sample from custom, user-defined distribution.
Value take(std::initializer_list< const char * > keys)
The default interface for SMASH to read configuration values.
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.
FermiMotion fermi_motion_
An option to include Fermi motion ("off", "on", "frozen")
double initial_z_displacement_
Initial z-displacement of nuclei.
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 ...
Sample from areal / quadratic distribution.
Don't use fermi motion.
ColliderModus: Provides a modus for colliding nuclei.
double sqrt_s_NN_
Center-of-mass energy of a nucleon-nucleon collision.
Use fermi motion without potentials.
bool cll_in_nucleus_
An option to accept first collisions within the same nucleus.
double initial_conditions(Particles *particles, const ExperimentParameters ¶meters)
Generates initial state of the particles in the system.
std::unique_ptr< Nucleus > target_
Target.
double velocity_projectile_
Beam velocity of the projectile.
void sample_impact()
Sample impact parameter.
int testparticles
Number of test particle.
friend std::ostream & operator<<(std::ostream &, const ColliderModus &)
Writes the initial state for the ColliderModus to the output stream.
The Particles class abstracts the storage and manipulation of particles.
T pCM(const T sqrts, const T mass_a, const T mass_b) noexcept
double imp_max_
Maximum value of impact parameter.
Helper structure for Experiment.
Use fermi motion in combination with potentials.
CalculationFrame frame_
Reference frame for the system, as specified from config.
double total_s_
Center-of-mass energy squared of the nucleus-nucleus collision.
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...