14 #include "gsl/gsl_sf_ellint.h"
27 :
Action(in_plist, time), total_probability_(0.) {}
39 double xsec_scaling = 1.0;
41 xsec_scaling *= in_part.xsec_scaling_factor();
47 double xsec_scaling = 1.0;
49 xsec_scaling *= in_part.xsec_scaling_factor();
55 double dt,
const double gcell_vol,
86 int sym_factor_in = 1;
97 *type_eta_prime, dt, gcell_vol,
117 if (type_deuteron && type_anti_deuteron) {
126 ParticleList::iterator it = std::find_if(
131 const double spin_degn =
136 type_pi, *type_deuteron,
150 ParticleList::iterator it = std::find_if(
155 const double spin_degn =
160 type_pi, *type_anti_deuteron,
162 gcell_vol, spin_degn),
173 int symmetry_factor = 1;
175 ParticleList::iterator it =
178 return x.pdgcode().antiparticle_sign() == -1;
185 if (pdg_a == pdg_b) {
194 const double spin_degn =
199 type_N, *type_deuteron,
201 symmetry_factor * spin_degn),
212 int symmetry_factor = 1;
214 ParticleList::iterator it =
217 return x.pdgcode().antiparticle_sign() == 1;
224 if (pdg_a == pdg_b) {
233 const double spin_degn =
238 type_N, *type_anti_deuteron,
240 gcell_vol, symmetry_factor * spin_degn),
249 std::map<PdgCode, int> c;
250 int spin_factor_inc = 1;
253 spin_factor_inc *= data.pdgcode().spin_degeneracy();
256 const int n_possible_catalysts_incoming =
270 const int n_nucleus_components_that_can_be_catalysts =
271 pdg_nucleus.nucleus_p() + pdg_nucleus.nucleus_ap() +
272 pdg_nucleus.nucleus_n() + pdg_nucleus.nucleus_an();
273 const bool incoming_contain_nucleus_components =
274 c[
pdg::p] >= pdg_nucleus.nucleus_p() &&
275 c[-
pdg::p] >= pdg_nucleus.nucleus_ap() &&
276 c[
pdg::n] >= pdg_nucleus.nucleus_n() &&
277 c[-
pdg::n] >= pdg_nucleus.nucleus_an() &&
280 const bool can_form_nucleus =
281 type_nucleus && incoming_contain_nucleus_components &&
282 n_possible_catalysts_incoming -
283 n_nucleus_components_that_can_be_catalysts ==
286 if (!can_form_nucleus) {
290 std::map<PdgCode, int> catalyst_count = c;
291 catalyst_count[
pdg::p] -= pdg_nucleus.nucleus_p();
292 catalyst_count[-
pdg::p] -= pdg_nucleus.nucleus_ap();
293 catalyst_count[
pdg::n] -= pdg_nucleus.nucleus_n();
294 catalyst_count[-
pdg::n] -= pdg_nucleus.nucleus_an();
295 catalyst_count[
pdg::Lambda] -= pdg_nucleus.nucleus_La();
296 catalyst_count[-
pdg::Lambda] -= pdg_nucleus.nucleus_aLa();
298 for (
const auto i : catalyst_count) {
300 pdg_catalyst = i.first;
306 pdg_nucleus,
" from ",
311 const double spin_degn =
314 double symmetry_factor = 1.0;
315 for (
const auto i : c) {
316 symmetry_factor *= (i.second == 3) ? 6.0
317 : (i.second == 2) ? 2.0
319 if (i.second > 3 || i.second < 0) {
326 *type_catalyst, *type_nucleus,
328 symmetry_factor * spin_degn),
336 const int spin_factor_inc =
342 const double symmetry_factor = 4.0;
349 const double spin_degn =
353 if (type_p && type_n) {
355 type_p->
mass(), dt, gcell_vol,
356 symmetry_factor * spin_degn);
358 *type_p, *type_anti_p, prob,
361 *type_n, *type_anti_n, prob,
396 "ScatterActionMulti::generate_final_state: Invalid process type " +
397 std::to_string(
static_cast<int>(
process_type_)) +
" was requested.");
405 new_particle.boost_momentum(
408 new_particle.set_4position(middle_point);
417 if (sqrts < m1 + m2 + m3) {
420 const double x1 = (m1 - m2) * (m1 - m2), x2 = (m1 + m2) * (m1 + m2),
421 x3 = (sqrts - m3) * (sqrts - m3),
422 x4 = (sqrts + m3) * (sqrts + m3);
423 const double qmm = x3 - x1, qmp = x3 - x2, qpm = x4 - x1, qpp = x4 - x2;
424 const double kappa = std::sqrt(qpm * qmp / (qpp * qmm));
425 const double tmp = std::sqrt(qmm * qpp);
427 4.0 * m1 * m2 * std::sqrt(qmm / qpp) * (x4 - m3 * sqrts + m1 * m2);
428 const double c2 = 0.5 * (m1 * m1 + m2 * m2 + m3 * m3 + sqrts * sqrts) * tmp;
429 const double c3 = 8 * m1 * m2 / tmp *
430 ((m1 * m1 + m2 * m2) * (m3 * m3 + sqrts * sqrts) -
431 2 * m1 * m1 * m2 * m2 - 2 * m3 * m3 * sqrts * sqrts);
434 const double precision = 1.e-6;
436 c1 * gsl_sf_ellint_Kcomp(kappa, precision) +
437 c2 * gsl_sf_ellint_Ecomp(kappa, precision) +
438 c3 * gsl_sf_ellint_Pcomp(kappa, -qmp / qmm, precision) +
439 c4 * gsl_sf_ellint_Pcomp(kappa, -x1 * qmp / (x2 * qmm), precision);
444 const ParticleType& type_out,
double dt,
const double gcell_vol,
445 const int degen_sym_factor)
const {
449 const double sqrts =
sqrt_s();
456 const double ph_sp_3 =
457 1. / (8 * M_PI * M_PI * M_PI) * 1. / (16 * sqrts * sqrts) * I_3;
461 return dt / (gcell_vol * gcell_vol) * M_PI / (4. * e1 * e2 * e3) *
462 gamma_decay / ph_sp_3 * spec_f_val * std::pow(
hbarc, 5.0) *
468 const double gcell_vol,
const double degen_sym_factor)
const {
472 const double m4 = type_out1.
mass();
473 const double m5 = type_out2.
mass();
475 const double sqrts =
sqrt_s();
478 const double lamb =
lambda_tilde(sqrts * sqrts, m4 * m4, m5 * m5);
481 const double ph_sp_3 =
482 1. / (8 * M_PI * M_PI * M_PI) * 1. / (16 * sqrts * sqrts) * I_3;
484 return dt / (gcell_vol * gcell_vol) * 1. / (4. * e1 * e2 * e3) * lamb /
485 (ph_sp_3 * 8 * M_PI * sqrts * sqrts) * xs * std::pow(
hbarc, 5.0) *
491 const double gcell_vol,
const double degen_sym_factor)
const {
496 const double m5 = type_out1.
mass();
497 const double m6 = type_out2.
mass();
502 const double lamb =
lambda_tilde(man_s, m5 * m5, m6 * m6);
505 return dt / std::pow(gcell_vol, 3.0) * 1. / (16. * e1 * e2 * e3 * e4) * xs /
506 (4. * M_PI * man_s) * lamb / ph_sp_4 * std::pow(
hbarc, 8.0) *
511 int n_nucleons = 0, n_pions = 0, n_lambdas = 0;
512 double sum_m = 0.0, prod_m = 1.0;
514 const PdgCode pdg = data.type().pdgcode();
518 sum_m += data.type().mass();
519 prod_m *= data.type().mass();
521 const double x = 1.0 - sum_m / std::sqrt(man_s);
522 const double x2 = x * x;
523 const double x3 = x2 * x;
526 if (n_nucleons == 3 && n_pions == 1) {
527 g = (1.0 + 0.862432 * x - 3.4853 * x2 + 1.70259 * x3) /
528 (1.0 + 0.387376 * x - 1.34128 * x2 + 0.154489 * x3);
529 }
else if (n_nucleons == 4) {
530 g = (1.0 - 1.72285 * x + 0.728331 * x2) /
531 (1.0 - 0.967146 * x - 0.0103633 * x2);
532 }
else if (n_nucleons == 2 && n_lambdas == 1 && n_pions == 1) {
533 g = (1.0 + 0.937064 * x - 3.56864 * x2 + 1.721 * x3) /
534 (1.0 + 0.365202 * x - 1.2854 * x2 + 0.138444 * x3);
535 }
else if (n_nucleons == 3 && n_lambdas == 1) {
536 g = (1.0 + 0.882401 * x - 3.4074 * x2 + 1.62454 * x3) /
537 (1.0 + 1.61741 * x - 2.12543 * x2 - 0.0902067 * x3);
541 return (std::sqrt(prod_m) * sum_m * sum_m * std::pow(x, 3.5) * g) /
542 (840. * std::sqrt(2) * std::pow(M_PI, 4.0) * std::pow(1 - x, 4.0));
551 const double mout,
double dt,
const double gcell_vol,
552 const double degen_sym_factor)
const {
560 const double lamb =
lambda_tilde(man_s, mout * mout, mout * mout);
567 return dt / std::pow(gcell_vol, 4.0) * 1. / (32. * e1 * e2 * e3 * e4 * e5) *
568 xs / (4. * M_PI * man_s) * lamb / ph_sp_5 * std::pow(
hbarc, 11.0) *
575 const double fit_a = 2.1018e-10;
576 const double fit_alpha = 1.982;
577 return fit_a * std::pow(man_s - s_zero, 5.0) *
578 std::pow(1 + man_s / s_zero, -fit_alpha);
585 "Incorrect number of particles in final state: ";
617 (pdg_a != pdg_b && pdg_b != pdg_c && pdg_c != pdg_a);
642 const bool all_inc_pi =
644 [](
const ParticleData& data) { return data.is_pion(); });
645 const int no_of_piz = std::count_if(
647 [](
const ParticleData& data) { return data.pdgcode() == pdg::pi_z; });
649 int total_state_charge = 0;
651 total_state_charge += part.pdgcode().charge();
654 return (all_inc_pi && total_state_charge == 0 && no_of_piz == 1);
660 out <<
" (not performed)";
Action is the base class for a generic process that takes a number of incoming particles and transfor...
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.
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.
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...
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.
ScatterActionMulti(const ParticleList &in_plist, double time)
Construct a ScatterActionMulti object.
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.
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.
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.