22 :
Action({
p}, time), total_width_(0.) {}
33 const auto &log = logger<LogArea::DecayModes>();
41 log.debug(
"Note: Doing 1->3 decay!");
43 const double mass_a = outgoing_a_type.
mass();
44 const double mass_b = outgoing_b_type.
mass();
45 const double mass_c = outgoing_c_type.
mass();
49 const double s_ab_max = (mass_resonance - mass_c) * (mass_resonance - mass_c);
50 const double s_ab_min = (mass_a + mass_b) * (mass_a + mass_b);
51 const double s_bc_max = (mass_resonance - mass_a) * (mass_resonance - mass_a);
52 const double s_bc_min = (mass_b + mass_c) * (mass_b + mass_c);
54 log.debug(
"s_ab limits: ", s_ab_min,
" ", s_ab_max);
55 log.debug(
"s_bc limits: ", s_bc_min,
" ", s_bc_max);
59 double dalitz_bc_max = 0.0, dalitz_bc_min = 1.0;
60 double s_ab = 0.0, s_bc = 0.5;
61 while (s_bc > dalitz_bc_max || s_bc < dalitz_bc_min) {
64 const double e_b_rest =
65 (s_ab - mass_a * mass_a + mass_b * mass_b) / (2 * std::sqrt(s_ab));
66 const double e_c_rest =
67 (mass_resonance * mass_resonance - s_ab - mass_c * mass_c) /
68 (2 * std::sqrt(s_ab));
69 dalitz_bc_max = (e_b_rest + e_c_rest) * (e_b_rest + e_c_rest) -
70 (std::sqrt(e_b_rest * e_b_rest - mass_b * mass_b) -
71 std::sqrt(e_c_rest * e_c_rest - mass_c * mass_c)) *
72 (std::sqrt(e_b_rest * e_b_rest - mass_b * mass_b) -
73 std::sqrt(e_c_rest * e_c_rest - mass_c * mass_c));
74 dalitz_bc_min = (e_b_rest + e_c_rest) * (e_b_rest + e_c_rest) -
75 (std::sqrt(e_b_rest * e_b_rest - mass_b * mass_b) +
76 std::sqrt(e_c_rest * e_c_rest - mass_c * mass_c)) *
77 (std::sqrt(e_b_rest * e_b_rest - mass_b * mass_b) +
78 std::sqrt(e_c_rest * e_c_rest - mass_c * mass_c));
81 log.debug(
"s_ab: ", s_ab,
" s_bc: ", s_bc,
" min: ", dalitz_bc_min,
82 " max: ", dalitz_bc_max);
85 const double energy_a =
86 (mass_resonance * mass_resonance + mass_a * mass_a - s_bc) /
88 const double energy_c =
89 (mass_resonance * mass_resonance + mass_c * mass_c - s_ab) /
91 const double energy_b =
92 (s_ab + s_bc - mass_a * mass_a - mass_c * mass_c) / (2 * mass_resonance);
93 const double momentum_a = std::sqrt(energy_a * energy_a - mass_a * mass_a);
94 const double momentum_c = std::sqrt(energy_c * energy_c - mass_c * mass_c);
95 const double momentum_b = std::sqrt(energy_b * energy_b - mass_b * mass_b);
97 const double total_energy =
sqrt_s();
98 if (std::abs(energy_a + energy_b + energy_c - total_energy) >
really_small) {
99 log.warn(
"1->3: Ea + Eb + Ec: ", energy_a + energy_b + energy_c,
100 " Total E: ", total_energy);
102 log.debug(
"Calculating the angles...");
108 outgoing_a.set_4momentum(mass_a, phitheta.
threevec() * momentum_a);
111 double theta_ab = std::acos(
112 (energy_a * energy_b - 0.5 * (s_ab - mass_a * mass_a - mass_b * mass_b)) /
113 (momentum_a * momentum_b));
114 log.debug(
"theta_ab: ", theta_ab,
" Ea: ", energy_a,
" Eb: ", energy_b,
115 " sab: ", s_ab,
" pa: ", momentum_a,
" pb: ", momentum_b);
120 double theta_bc = std::acos(
121 (energy_b * energy_c - 0.5 * (s_bc - mass_b * mass_b - mass_c * mass_c)) /
122 (momentum_b * momentum_c));
123 log.debug(
"theta_bc: ", theta_bc,
" Eb: ", energy_b,
" Ec: ", energy_c,
124 " sbc: ", s_bc,
" pb: ", momentum_b,
" pc: ", momentum_c);
135 log.warn(
"1->3 energy not conserved! Before: ", total_energy,
136 " After: ", ptot.
x0());
141 log.warn(
"1->3 momentum check failed. Total momentum: ", ptot.
threevec());
144 log.debug(
"outgoing_a: ", outgoing_a.momentum(),
145 "\noutgoing_b: ", outgoing_b.
momentum(),
146 "\noutgoing_c: ", outgoing_c.
momentum());
150 const auto &log = logger<LogArea::DecayModes>();
151 log.debug(
"Process: Resonance decay. ");
178 "DecayAction::perform: Only 1->2 or 1->3 processes are supported. " 181 " was requested. (PDGcode=" +
188 log.debug(
"particle momenta in lrf ",
p);
193 log.debug(
"particle momenta in comp ",
p);
200 double kinetic_energy_cm)
const {
205 std::pair<double, double> masses = {t_a.
mass(), t_b.
mass()};
208 const std::string reaction =
211 reaction +
": not enough energy, " + std::to_string(kinetic_energy_cm) +
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...
int angular_momentum() const
Thrown when DecayAction is called to perform with 0 or more than 2 entries in outgoing_particles.
constexpr double really_small
Numerical error tolerance.
double sample_resonance_mass(const double mass_stable, const double cms_energy, int L=0) const
Resonance mass sampling for 2-particle final state with one resonance (type given by 'this') and one ...
ProcessType process_type_
type of process
void add_decay(DecayBranchPtr p)
Add one new decay.
ThreeVector threevec() const
virtual void one_to_three()
Kinematics of a 1-to-3 decay process.
void add_decays(DecayBranchList pv)
Add several new decays at once.
const FourVector & momentum() const
Get the particle's 4-momentum.
DecayAction(const ParticleData &p, double time)
Construct a DecayAction from a particle p.
DecayBranchList decay_channels_
List of possible decays.
double total_width_
total decay width
ThreeVector threevec() const
ParticleList particle_list() const
int L_
Angular momentum of the decay.
ParticleList outgoing_particles_
Initially this stores only the PDG codes of final-state particles.
Particle type contains the static properties of a particle species.
void set_4momentum(const FourVector &momentum_vector)
Set the particle's 4-momentum directly.
ParticleList incoming_particles_
List with data of incoming particles.
FourVector total_momentum_of_outgoing_particles() const
Calculate the total kinetic momentum of the outgoing particles.
std::pair< double, double > sample_resonance_masses(const ParticleType &t2, const double cms_energy, int L=0) const
Resonance mass sampling for 2-particle final state with two resonances.
Action is the base class for a generic process that takes a number of incoming particles and transfor...
DecayBranch is a derivative of ProcessBranch, which is used to represent decay channels.
void generate_final_state() override
Generate the final state of the decay process.
bool add_to_theta(const double delta)
Advance polar angle.
const ParticleType & type() const
Get the type of the particle.
void sample_2body_phasespace()
Sample the full 2-body phase-space (masses, momenta, angles) in the center-of-mass frame for the fina...
ProcessType get_type() const override
double min_mass_kinematic() const
The minimum mass of the resonance that is kinematically allowed.
Angles provides a common interface for generating directions: i.e., two angles that should be interpr...
void distribute_isotropically()
Populate the object with a new direction.
std::pair< double, double > sample_masses(double kinetic_energy_cm) const override
Sample the masses of the final particles.
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
double partial_width_
partial decay width to the chosen outgoing channel
ParticleData contains the dynamic information of a certain particle.
const double time_of_execution_
Time at which the action is supposed to be performed (absolute time in the lab frame in fm/c)...
void format_debug_output(std::ostream &out) const override
Writes information about this decay action to the out stream.
double sqrt_s() const
Determine the total energy in the center-of-mass frame [GeV].
const std::string & name() const