30 static constexpr
int LCollider = LogArea::Collider::id;
334 if (modus_cfg.
has_value({
"Calculation_Frame"})) {
335 frame_ = modus_cfg.
take({
"Calculation_Frame"});
339 if (modus_cfg.
has_value({
"Collisions_Within_Nucleus"})) {
346 bool same_file =
false;
351 }
else if (proj_cfg.
has_value({
"Custom"})) {
354 make_unique<CustomNucleus>(proj_cfg, params.
testparticles, same_file);
359 throw ColliderEmpty(
"Input Error: Projectile nucleus is empty.");
365 }
else if (targ_cfg.
has_value({
"Custom"})) {
367 make_unique<CustomNucleus>(targ_cfg, params.
testparticles, same_file);
372 throw ColliderEmpty(
"Input Error: Target nucleus is empty.");
376 if (modus_cfg.
has_value({
"Fermi_Motion"})) {
385 int energy_input = 0;
387 const double mass_target =
target_->mass();
389 const double mass_a =
391 const double mass_b =
target_->mass() /
target_->number_of_particles();
398 "Input Error: sqrt(s_NN) is not larger than masses:\n" +
399 std::to_string(
sqrt_s_NN_) +
" GeV <= " + std::to_string(mass_a) +
400 " GeV + " + std::to_string(mass_b) +
" GeV.");
404 mass_projec * mass_target / (mass_a * mass_b) +
405 mass_projec * mass_projec + mass_target * mass_target;
411 const double e_tot = modus_cfg.
take({
"E_Tot"});
415 "E_Tot must be nonnegative.");
419 mass_projec, mass_target);
426 const double e_kin = modus_cfg.
take({
"E_Kin"});
430 "E_Kin must be nonnegative.");
434 mass_projec, mass_target);
440 const double p_lab = modus_cfg.
take({
"P_Lab"});
444 "P_Lab must be nonnegative.");
448 mass_projec, mass_target);
454 const double e_tot_p = proj_cfg.
take({
"E_Tot"});
455 const double e_tot_t = targ_cfg.
take({
"E_tot"});
456 if (e_tot_p < 0 || e_tot_t < 0) {
459 "E_Tot must be nonnegative.");
462 e_tot_t *
target_->number_of_particles(),
463 mass_projec, mass_target);
469 const double e_kin_p = proj_cfg.
take({
"E_Kin"});
470 const double e_kin_t = targ_cfg.
take({
"E_Kin"});
471 if (e_kin_p < 0 || e_kin_t < 0) {
474 "E_Kin must be nonnegative.");
477 e_kin_t *
target_->number_of_particles(),
478 mass_projec, mass_target);
484 const double p_lab_p = proj_cfg.
take({
"P_Lab"});
485 const double p_lab_t = targ_cfg.
take({
"P_Lab"});
486 if (p_lab_p < 0 || p_lab_t < 0) {
489 "P_Lab must be nonnegative.");
492 p_lab_t *
target_->number_of_particles(),
493 mass_projec, mass_target);
497 if (energy_input == 0) {
498 throw std::domain_error(
499 "Input Error: Non-existent collision energy. "
500 "Please provide one of Sqrtsnn/E_Kin/P_Lab.");
502 if (energy_input > 1) {
503 throw std::domain_error(
504 "Input Error: Redundant collision energy. "
505 "Please provide only one of Sqrtsnn/E_Kin/P_Lab.");
510 if (modus_cfg.
has_value({
"Impact",
"Value"})) {
516 if (modus_cfg.
has_value({
"Impact",
"Sample"})) {
519 if (!(modus_cfg.
has_value({
"Impact",
"Values"}) ||
520 modus_cfg.
has_value({
"Impact",
"Yields"}))) {
521 throw std::domain_error(
522 "Input Error: Need impact parameter spectrum for custom "
524 "Please provide Values and Yields.");
526 const std::vector<double> impacts =
527 modus_cfg.
take({
"Impact",
"Values"});
528 const std::vector<double> yields = modus_cfg.
take({
"Impact",
"Yields"});
529 if (impacts.size() != yields.size()) {
530 throw std::domain_error(
531 "Input Error: Need as many impact parameter values as yields. "
532 "Please make sure that Values and Yields have the same length.");
537 const auto imp_minmax =
538 std::minmax_element(impacts.begin(), impacts.end());
541 yield_max_ = *std::max_element(yields.begin(), yields.end());
544 if (modus_cfg.
has_value({
"Impact",
"Range"})) {
545 const std::array<double, 2> range = modus_cfg.
take({
"Impact",
"Range"});
549 if (modus_cfg.
has_value({
"Impact",
"Max"})) {
557 modus_cfg.
take({
"Impact",
"Random_Reaction_Plane"},
false);
559 if (modus_cfg.
has_value({
"Initial_Distance"})) {
568 return out <<
"-- Collider Modus:\n"
569 <<
"sqrt(S) (nucleus-nucleus) = "
578 Configuration &nucleus_cfg,
int ntest,
const std::string &nucleus_type) {
579 bool auto_deform = nucleus_cfg.
take({
"Deformed",
"Automatic"});
580 bool is_beta2 = nucleus_cfg.
has_value({
"Deformed",
"Beta_2"}) ?
true :
false;
581 bool is_beta4 = nucleus_cfg.
has_value({
"Deformed",
"Beta_4"}) ?
true :
false;
582 std::unique_ptr<DeformedNucleus> nucleus;
584 if ((auto_deform && (!is_beta2 && !is_beta4)) ||
585 (!auto_deform && (is_beta2 && is_beta4))) {
586 nucleus = make_unique<DeformedNucleus>(nucleus_cfg, ntest, auto_deform);
589 throw std::domain_error(
"Deformation of " + nucleus_type +
590 " nucleus not configured "
591 "properly, please check whether all necessary "
592 "parameters are set.");
613 if (v_a >= 1.0 || v_b >= 1.0) {
614 throw std::domain_error(
615 "Found velocity equal to or larger than 1 in "
616 "ColliderModus::initial_conditions.\nConsider using "
617 "the center of velocity reference frame.");
633 target_->generate_fermi_momenta();
643 throw std::domain_error(
"Invalid Fermi_Motion input.");
653 const double d_a = std::max(0.,
projectile_->get_diffusiveness());
654 const double d_b = std::max(0.,
target_->get_diffusiveness());
655 const double r_a =
projectile_->get_nuclear_radius();
656 const double r_b =
target_->get_nuclear_radius();
659 const double simulation_time = -dz / std::abs(v_a);
660 const double proj_z = -dz - std::sqrt(1.0 - v_a * v_a) * (r_a + d_a);
661 const double targ_z =
662 +dz * std::abs(v_b / v_a) + std::sqrt(1.0 - v_b * v_b) * (r_b + d_b);
672 target_->copy_particles(particles);
674 return simulation_time;
683 p.set_3position(pos);
684 p.set_3momentum(mom);
701 double probability_random = 1;
702 double probability = 0;
704 while (probability_random > probability) {
706 probability = (*impact_interpolation_)(b) /
yield_max_;
707 assert(probability < 1.);
732 v_a =
pCM / std::sqrt(m_a * m_a +
pCM *
pCM);
733 v_b = -
pCM / std::sqrt(m_b * m_b +
pCM *
pCM);
739 throw std::domain_error(
740 "Invalid reference frame in "
741 "ColliderModus::get_velocities.");
743 return std::make_pair(v_a, v_b);
747 const std::string &file_name) {
749 if (file_directory.back() ==
'/') {
750 return file_directory + file_name;
752 return file_directory +
'/' + file_name;
761 if (!targ_config.
has_value({
"Custom"})) {
764 std::string projectile_file_directory =
765 proj_config.
read({
"Custom",
"File_Directory"});
766 std::string target_file_directory =
767 targ_config.
read({
"Custom",
"File_Directory"});
768 std::string projectile_file_name = proj_config.
read({
"Custom",
"File_Name"});
769 std::string target_file_name = targ_config.
read({
"Custom",
"File_Name"});
771 std::string proj_path =
773 std::string targ_path =
775 if (proj_path == targ_path) {