14 #include "gsl/gsl_sf_ellint.h"
26 const ParticleList& in_plist,
double time,
29 total_probability_(0.),
30 spin_interaction_type_(spin_interaction_type) {}
42 double xsec_scaling = 1.0;
44 xsec_scaling *= in_part.xsec_scaling_factor();
50 double xsec_scaling = 1.0;
52 xsec_scaling *= in_part.xsec_scaling_factor();
58 double dt,
const double gcell_vol,
89 int sym_factor_in = 1;
100 *type_eta_prime, dt, gcell_vol,
120 if (type_deuteron && type_anti_deuteron) {
129 ParticleList::iterator it = std::find_if(
134 const double spin_degn =
139 type_pi, *type_deuteron,
153 ParticleList::iterator it = std::find_if(
158 const double spin_degn =
163 type_pi, *type_anti_deuteron,
165 gcell_vol, spin_degn),
176 int symmetry_factor = 1;
178 ParticleList::iterator it =
181 return x.pdgcode().antiparticle_sign() == -1;
188 if (pdg_a == pdg_b) {
197 const double spin_degn =
202 type_N, *type_deuteron,
204 symmetry_factor * spin_degn),
215 int symmetry_factor = 1;
217 ParticleList::iterator it =
220 return x.pdgcode().antiparticle_sign() == 1;
227 if (pdg_a == pdg_b) {
236 const double spin_degn =
241 type_N, *type_anti_deuteron,
243 gcell_vol, symmetry_factor * spin_degn),
252 std::map<PdgCode, int> c;
253 int spin_factor_inc = 1;
256 spin_factor_inc *= data.pdgcode().spin_degeneracy();
259 const int n_possible_catalysts_incoming =
273 const int n_nucleus_components_that_can_be_catalysts =
274 pdg_nucleus.nucleus_p() + pdg_nucleus.nucleus_ap() +
275 pdg_nucleus.nucleus_n() + pdg_nucleus.nucleus_an();
276 const bool incoming_contain_nucleus_components =
277 c[
pdg::p] >= pdg_nucleus.nucleus_p() &&
278 c[-
pdg::p] >= pdg_nucleus.nucleus_ap() &&
279 c[
pdg::n] >= pdg_nucleus.nucleus_n() &&
280 c[-
pdg::n] >= pdg_nucleus.nucleus_an() &&
283 const bool can_form_nucleus =
284 type_nucleus && incoming_contain_nucleus_components &&
285 n_possible_catalysts_incoming -
286 n_nucleus_components_that_can_be_catalysts ==
289 if (!can_form_nucleus) {
293 std::map<PdgCode, int> catalyst_count = c;
294 catalyst_count[
pdg::p] -= pdg_nucleus.nucleus_p();
295 catalyst_count[-
pdg::p] -= pdg_nucleus.nucleus_ap();
296 catalyst_count[
pdg::n] -= pdg_nucleus.nucleus_n();
297 catalyst_count[-
pdg::n] -= pdg_nucleus.nucleus_an();
298 catalyst_count[
pdg::Lambda] -= pdg_nucleus.nucleus_La();
299 catalyst_count[-
pdg::Lambda] -= pdg_nucleus.nucleus_aLa();
301 for (
const auto i : catalyst_count) {
303 pdg_catalyst = i.first;
309 pdg_nucleus,
" from ",
314 const double spin_degn =
317 double symmetry_factor = 1.0;
318 for (
const auto i : c) {
319 symmetry_factor *= (i.second == 3) ? 6.0
320 : (i.second == 2) ? 2.0
322 if (i.second > 3 || i.second < 0) {
329 *type_catalyst, *type_nucleus,
331 symmetry_factor * spin_degn),
339 const int spin_factor_inc =
345 const double symmetry_factor = 4.0;
352 const double spin_degn =
356 if (type_p && type_n) {
358 type_p->
mass(), dt, gcell_vol,
359 symmetry_factor * spin_degn);
361 *type_p, *type_anti_p, prob,
364 *type_n, *type_anti_n, prob,
399 "ScatterActionMulti::generate_final_state: Invalid process type " +
408 new_particle.boost_momentum(
411 new_particle.set_4position(middle_point);
420 if (sqrts < m1 + m2 + m3) {
423 const double x1 = (m1 - m2) * (m1 - m2), x2 = (m1 + m2) * (m1 + m2),
424 x3 = (sqrts - m3) * (sqrts - m3),
425 x4 = (sqrts + m3) * (sqrts + m3);
426 const double qmm = x3 - x1, qmp = x3 - x2, qpm = x4 - x1, qpp = x4 - x2;
427 const double kappa = std::sqrt(qpm * qmp / (qpp * qmm));
428 const double tmp = std::sqrt(qmm * qpp);
430 4.0 * m1 * m2 * std::sqrt(qmm / qpp) * (x4 - m3 * sqrts + m1 * m2);
431 const double c2 = 0.5 * (m1 * m1 + m2 * m2 + m3 * m3 + sqrts * sqrts) * tmp;
432 const double c3 = 8 * m1 * m2 / tmp *
433 ((m1 * m1 + m2 * m2) * (m3 * m3 + sqrts * sqrts) -
434 2 * m1 * m1 * m2 * m2 - 2 * m3 * m3 * sqrts * sqrts);
438 c1 * gsl_sf_ellint_Kcomp(kappa, GSL_PREC_DOUBLE) +
439 c2 * gsl_sf_ellint_Ecomp(kappa, GSL_PREC_DOUBLE) +
440 c3 * gsl_sf_ellint_Pcomp(kappa, -qmp / qmm, GSL_PREC_DOUBLE) +
441 c4 * gsl_sf_ellint_Pcomp(kappa, -x1 * qmp / (x2 * qmm), GSL_PREC_DOUBLE);
446 const ParticleType& type_out,
double dt,
const double gcell_vol,
447 const int degen_sym_factor)
const {
451 const double sqrts =
sqrt_s();
458 const double ph_sp_3 =
459 1. / (8 * M_PI * M_PI * M_PI) * 1. / (16 * sqrts * sqrts) * I_3;
463 return dt / (gcell_vol * gcell_vol) * M_PI / (4. * e1 * e2 * e3) *
464 gamma_decay / ph_sp_3 * spec_f_val * std::pow(
hbarc, 5.0) *
470 const double gcell_vol,
const double degen_sym_factor)
const {
474 const double m4 = type_out1.
mass();
475 const double m5 = type_out2.
mass();
477 const double sqrts =
sqrt_s();
480 const double lamb =
lambda_tilde(sqrts * sqrts, m4 * m4, m5 * m5);
483 const double ph_sp_3 =
484 1. / (8 * M_PI * M_PI * M_PI) * 1. / (16 * sqrts * sqrts) * I_3;
486 return dt / (gcell_vol * gcell_vol) * 1. / (4. * e1 * e2 * e3) * lamb /
487 (ph_sp_3 * 8 * M_PI * sqrts * sqrts) * xs * std::pow(
hbarc, 5.0) *
493 const double gcell_vol,
const double degen_sym_factor)
const {
498 const double m5 = type_out1.
mass();
499 const double m6 = type_out2.
mass();
504 const double lamb =
lambda_tilde(man_s, m5 * m5, m6 * m6);
507 return dt / std::pow(gcell_vol, 3.0) * 1. / (16. * e1 * e2 * e3 * e4) * xs /
508 (4. * M_PI * man_s) * lamb / ph_sp_4 * std::pow(
hbarc, 8.0) *
513 int n_nucleons = 0, n_pions = 0, n_lambdas = 0;
514 double sum_m = 0.0, prod_m = 1.0;
516 const PdgCode pdg = data.type().pdgcode();
520 sum_m += data.type().mass();
521 prod_m *= data.type().mass();
523 const double x = 1.0 - sum_m / std::sqrt(man_s);
524 const double x2 = x * x;
525 const double x3 = x2 * x;
528 if (n_nucleons == 3 && n_pions == 1) {
529 g = (1.0 + 0.862432 * x - 3.4853 * x2 + 1.70259 * x3) /
530 (1.0 + 0.387376 * x - 1.34128 * x2 + 0.154489 * x3);
531 }
else if (n_nucleons == 4) {
532 g = (1.0 - 1.72285 * x + 0.728331 * x2) /
533 (1.0 - 0.967146 * x - 0.0103633 * x2);
534 }
else if (n_nucleons == 2 && n_lambdas == 1 && n_pions == 1) {
535 g = (1.0 + 0.937064 * x - 3.56864 * x2 + 1.721 * x3) /
536 (1.0 + 0.365202 * x - 1.2854 * x2 + 0.138444 * x3);
537 }
else if (n_nucleons == 3 && n_lambdas == 1) {
538 g = (1.0 + 0.882401 * x - 3.4074 * x2 + 1.62454 * x3) /
539 (1.0 + 1.61741 * x - 2.12543 * x2 - 0.0902067 * x3);
543 return (std::sqrt(prod_m) * sum_m * sum_m * std::pow(x, 3.5) * g) /
544 (840. * std::sqrt(2) * std::pow(M_PI, 4.0) * std::pow(1 - x, 4.0));
553 const double mout,
double dt,
const double gcell_vol,
554 const double degen_sym_factor)
const {
562 const double lamb =
lambda_tilde(man_s, mout * mout, mout * mout);
569 return dt / std::pow(gcell_vol, 4.0) * 1. / (32. * e1 * e2 * e3 * e4 * e5) *
570 xs / (4. * M_PI * man_s) * lamb / ph_sp_5 * std::pow(
hbarc, 11.0) *
577 const double fit_a = 2.1018e-10;
578 const double fit_alpha = 1.982;
579 return fit_a * std::pow(man_s - s_zero, 5.0) *
580 std::pow(1 + man_s / s_zero, -fit_alpha);
587 "Incorrect number of particles in final state: ";
625 (pdg_a != pdg_b && pdg_b != pdg_c && pdg_c != pdg_a);
650 const bool all_inc_pi =
652 [](
const ParticleData& data) { return data.is_pion(); });
653 const int no_of_piz = std::count_if(
655 [](
const ParticleData& data) { return data.pdgcode() == pdg::pi_z; });
657 int total_state_charge = 0;
659 total_state_charge += part.pdgcode().charge();
662 return (all_inc_pi && total_state_charge == 0 && no_of_piz == 1);
668 out <<
" (not performed)";
Action is the base class for a generic process that takes a number of incoming particles and transfor...
virtual void sample_2body_phasespace()
Sample the full 2-body phase-space (masses, momenta, angles) in the center-of-mass frame for the fina...
FourVector total_momentum_of_outgoing_particles() const
Calculate the total kinetic momentum of the outgoing particles.
void assign_formation_time_to_outgoing_particles()
Assign the formation time to the outgoing particles.
ParticleList outgoing_particles_
Initially this stores only the PDG codes of final-state particles.
void assign_unpolarized_spin_vector_to_outgoing_particles()
Assign an unpolarized spin vector to all outgoing particles.
double sqrt_s() const
Determine the total energy in the center-of-mass frame [GeV].
ParticleList incoming_particles_
List with data of incoming particles.
FourVector get_interaction_point() const
Get the interaction point.
static double lambda_tilde(double a, double b, double c)
Little helper function that calculates the lambda function (sometimes written with a tilde to better ...
ProcessType process_type_
type of process
CollisionBranch is a derivative of ProcessBranch, which is used to represent particular final-state c...
ProcessType get_type() const override
static double two_to_three_xs(const ParticleType &type_in1, const ParticleType &type_in2, double sqrts)
Determine 2->3 cross section for the scattering of the given particle types.
static double two_to_four_xs(const ParticleType &type_in1, const ParticleType &type_in2, double sqrts)
Determine 2->4 cross section for the scattering of the given particle types.
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
ParticleData contains the dynamic information of a certain particle.
PdgCode pdgcode() const
Get the pdgcode of the particle.
A pointer-like interface to global references to ParticleType objects.
Particle type contains the static properties of a particle species.
double spectral_function(double m) const
Full spectral function of the resonance (relativistic Breit-Wigner distribution with mass-dependent ...
double get_partial_width(const double m, const ParticleTypePtrList dlist) const
Get the mass-dependent partial width of a resonance with mass m, decaying into two given daughter par...
static const ParticleTypePtr try_find(PdgCode pdgcode)
Returns the ParticleTypePtr for the given pdgcode.
unsigned int spin_degeneracy() const
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
static PdgCode invalid()
PdgCode 0x0 is guaranteed not to be valid by the PDG standard, but it passes all tests here,...
unsigned int spin_degeneracy() const
ParticleList particle_list() const
Thrown when ScatterActionMulti is called to perform with unknown combination of incoming and outgoing...
double probability_four_to_two(const ParticleType &type_out1, const ParticleType &type_out2, double dt, const double gcell_vol, const double degen_sym_factor=1.0) const
Calculate the probability for a 4-to-2 reaction according to the stochastic collision criterion as gi...
double total_probability_
Total probability of reaction.
bool two_pions_eta(const ParticleData &data_a, const ParticleData &data_b, const ParticleData &data_c) const
Check wether the three incoming particles are π⁺,π⁻,η or π⁰,π⁰,η in any order.
double probability_three_to_one(const ParticleType &type_out, double dt, const double gcell_vol, const int degen_sym_factor=1) const
Calculate the probability for a 3m-to-1 reaction according to the stochastic collision criterion as g...
bool all_incoming_particles_are_pions_have_zero_charge_only_one_piz() const
Check if 5 incoming particles match intial pion state for 5-to-2, which is pi+ pi- pi+ pi- pi0 in ord...
void generate_final_state() override
Generate the final-state of the multi-particle scattering process.
double get_partial_weight() const override
Get the partial probability for the chosen channel (scaled with the cross section scaling factors of ...
double react_degen_factor(const int spin_factor_inc, const int spin_degen_out1, const int spin_degen_out2) const
Determine the spin degeneracy factor ( ) for the N->2 reaction.
void format_debug_output(std::ostream &out) const override
Writes information about this action to the out stream.
void add_reactions(CollisionBranchList pv)
Add several new reaction channels at once.
void add_possible_reactions(double dt, const double gcell_vol, const MultiParticleReactionsBitSet incl_multi)
Add all possible multi-particle reactions for the given incoming particles.
double probability_five_to_two(const double m_out, double dt, const double gcell_vol, const double degen_sym_factor=1.0) const
Calculate the probability for a 5-to-2 reaction according to the stochastic collision criterion as gi...
CollisionBranchList reaction_channels_
List of possible collisions.
double probability_three_to_two(const ParticleType &type_out1, const ParticleType &type_out2, double dt, const double gcell_vol, const double degen_sym_factor=1.0) const
Calculate the probability for a 3-to-2 reaction according to the stochastic collision criterion as gi...
double calculate_I3(const double sqrts) const
Calculate the integration necessary for the three-body phase space.
ScatterActionMulti(const ParticleList &in_plist, double time, const SpinInteractionType spin_interaction_type=SpinInteractionType::Off)
Construct a ScatterActionMulti object.
double parametrizaton_phi5_pions(const double man_s) const
Calculate the parametrized 5-pion phase space.
double get_total_weight() const override
Get the total probability for the reaction (scaled with the cross section scaling factors of the inco...
SpinInteractionType spin_interaction_type_
Spin interaction type.
bool three_different_pions(const ParticleData &data_a, const ParticleData &data_b, const ParticleData &data_c) const
Check wether the three incoming particles are π⁺,π⁻,π⁰ in any order.
void add_reaction(CollisionBranchPtr p)
Add a new reaction channel.
double partial_probability_
Partial probability of the chosen outgoing channel.
void n_to_two()
Perform a n->2 process.
void annihilation()
Perform a n->1 annihilation process.
double parametrizaton_phi4(const double man_s) const
Calculate the parametrized 4-body relativistic phase space integral.
std::bitset< 4 > MultiParticleReactionsBitSet
Container for the n to m reactions in the code.
SpinInteractionType
Possible spin interaction types.
@ Off
No spin interactions.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
constexpr int64_t antideuteron
Anti-deuteron in decimal digits.
constexpr int64_t triton
Triton.
constexpr int64_t antihe3
Anti-He-3.
constexpr int64_t hypertriton
Hypertriton.
constexpr int64_t antihypertriton
Anti-Hypertriton.
constexpr int64_t antitriton
Anti-triton.
constexpr int64_t deuteron
Deuteron.
constexpr int64_t he3
He-3.
constexpr double gev2_mb
GeV^-2 <-> mb conversion factor.
double ppbar_total(double mandelstam_s)
ppbar total cross section parametrization Source: Bass:1998ca
static constexpr int LScatterActionMulti
double ppbar_elastic(double mandelstam_s)
ppbar elastic cross section parametrization Source: Bass:1998ca
@ MultiParticleThreeToTwo
See here for a short description.
@ MultiParticleThreeMesonsToOne
See here for a short description.
@ MultiParticleFourToTwo
See here for a short description.
@ MultiParticleFiveToTwo
See here for a short description.
bool all_of(Container &&c, UnaryPredicate &&p)
Convenience wrapper for std::all_of that operates on a complete container.
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
constexpr T pow_int(const T base, unsigned const exponent)
Efficient template for calculating integer powers using squaring.
constexpr double pion_mass
Pion mass in GeV.
constexpr double hbarc
GeV <-> fm conversion factor.