Version: SMASH-3.4
decayaction.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2013-2021,2024-2026
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/decayaction.h"
11 
12 #include "smash/decaymodes.h"
13 #include "smash/logging.h"
14 #include "smash/pdgcode.h"
16 
17 namespace smash {
18 
19 static constexpr int LDecayModes = LogArea::DecayModes::id;
20 
22  SpinInteractionType spin_interaction_type)
23  : Action({p}, time),
24  total_width_(0.),
25  spin_interaction_type_(spin_interaction_type) {}
26 
27 void DecayAction::add_decays(DecayBranchList pv) {
28  add_processes<DecayBranch>(std::move(pv), decay_channels_, total_width_);
29 }
30 
31 void DecayAction::add_decay(DecayBranchPtr p) {
32  add_process<DecayBranch>(p, decay_channels_, total_width_);
33 }
34 
36  logg[LDecayModes].debug("Process: Resonance decay of", incoming_particles_);
37  /* Execute a decay process for the selected particle.
38  *
39  * randomly select one of the decay modes of the particle
40  * according to their relative weights. Then decay the particle
41  * by calling function sample_2body_phasespace or sample_manybody_phasespace.
42  */
43  const DecayBranch *proc =
44  choose_channel<DecayBranch>(decay_channels_, total_width_);
46  logg[LDecayModes].debug("Channel: ", outgoing_particles_);
47  assert(std::accumulate(outgoing_particles_.begin(), outgoing_particles_.end(),
48  0., [](double sum, const ParticleData &p) {
49  return sum + p.type().min_mass_spectral();
50  }) <= incoming_particles_[0].effective_mass());
51 
52  // set positions of the outgoing particles
53  for (auto &p : outgoing_particles_) {
54  p.set_4position(incoming_particles_[0].position());
55  }
56  process_type_ = proc->get_type();
57  L_ = proc->angular_momentum();
58  partial_width_ = proc->weight();
59 
60  switch (outgoing_particles_.size()) {
61  case 2:
63  if (pot_pointer) {
65  } else {
66  return true;
67  }
68  case 3:
70  return true;
71  default:
72  throw InvalidDecay(
73  "DecayAction::perform: Only 1->2 or 1->3 processes are supported. "
74  "Decay from 1->" +
76  " was requested. (PDGcode=" +
77  incoming_particles_[0].pdgcode().string() + ", mass=" +
78  std::to_string(incoming_particles_[0].effective_mass()) + ")");
79  }
80 }
81 
83  int n_try = 1000;
84  while (n_try--) {
86  break;
87  }
88 
89  const bool core_in_incoming = incoming_particles_[0].is_core();
90  // Set formation time.
91  for (auto &p : outgoing_particles_) {
92  logg[LDecayModes].debug("particle momenta in lrf ", p);
93  // assuming decaying particles are always fully formed
94  p.set_formation_time(time_of_execution_);
95  // Boost to the computational frame
96  p.boost_momentum(-total_momentum_of_outgoing_particles().velocity());
97  logg[LDecayModes].debug("particle momenta in comp ", p);
98  if (core_in_incoming) {
99  p.fluidize();
100  }
101  if (p.type().pdgcode().is_heavy_flavor()) {
102  p.set_perturbative_weight(incoming_particles_[0].perturbative_weight());
103  }
104  }
105 
106  /*
107  * @brief Σ* → Λ + π decay: propagate Λ polarization from the intermediate
108  * resonance.
109  *
110  * During Λ+π → Σ* formation we stored the incoming Λ polarization by
111  * writing it into the Σ* spin 4-vector (optionally applying a Λ spin-flip
112  * probability, cf. arXiv:2404.15890v2). At decay, we must hand this
113  * polarization back to the outgoing Λ to transport Λ polarization through the
114  * resonance stage.
115  */
117  outgoing_particles_.size() == 2) {
118  // Check for Σ* → Λ + π decay channel
119  int lambda_idx = -1;
120  int pion_idx = -1;
121  const bool is_sigmastar_decay = is_sigmastar_to_lambda_pion_decay(
123  lambda_idx, pion_idx);
124 
125  if (is_sigmastar_decay) {
126  auto &sigma_star = incoming_particles_[0];
127  auto &lambda = outgoing_particles_[lambda_idx];
128  auto &pion = outgoing_particles_[pion_idx];
129  // Copy spin vector from Σ* to Λ and boost it to the Λ frame
130  FourVector final_spin_vector =
131  sigma_star.spin_vector().lorentz_boost(lambda.velocity());
132  lambda.set_spin_vector(final_spin_vector);
133  pion.set_spin_vector(FourVector{0., 0., 0., 0.});
134  } else {
135  // Set unpolarized spin vectors
137  }
139  outgoing_particles_.size() != 2) {
140  // Set unpolarized spin vectors
142  }
143 }
144 
146  assert(outgoing_particles_.size() == 2);
148  const double cm_kin_energy = p_tot.abs();
149  const std::pair<double, double> masses = sample_masses(cm_kin_energy);
150 
151  const bool is_valid = !std::isnan(masses.first) && !std::isnan(masses.second);
152 
153  if (pot_pointer) {
155  }
156 
157  sample_angles(masses, cm_kin_energy);
158 }
159 
160 /* This is overridden from the Action class in order to
161  * take care of the angular momentum L_. */
162 std::pair<double, double> DecayAction::sample_masses(
163  double kinetic_energy_cm) const {
164  const ParticleType &t_a = outgoing_particles_[0].type();
165  const ParticleType &t_b = outgoing_particles_[1].type();
166 
167  // start with pole masses
168  std::pair<double, double> masses = {t_a.mass(), t_b.mass()};
169 
170  const bool below_threshold_energy =
171  kinetic_energy_cm < t_a.min_mass_kinematic() + t_b.min_mass_kinematic();
172 
173  const bool return_nan_on_failure = pot_pointer != nullptr;
174 
175  if (below_threshold_energy) {
176  if (return_nan_on_failure) {
177  return {smash_NaN<double>, smash_NaN<double>};
178  } else {
179  const std::string reaction =
180  incoming_particles_[0].type().name() + "→" + t_a.name() + t_b.name();
182  reaction + ": not enough energy, " +
183  std::to_string(kinetic_energy_cm) + " < " +
184  std::to_string(t_a.min_mass_kinematic()) + " + " +
186  }
187  }
188  // If one of the particles is a resonance, sample its mass.
189  if (!t_a.is_stable() && t_b.is_stable()) {
190  masses.first = t_a.sample_resonance_mass(t_b.mass(), kinetic_energy_cm, L_);
191  } else if (!t_b.is_stable() && t_a.is_stable()) {
192  masses.second =
193  t_b.sample_resonance_mass(t_a.mass(), kinetic_energy_cm, L_);
194  } else if (!t_a.is_stable() && !t_b.is_stable()) {
195  // two resonances in final state
196  masses = sample_two_resonance_masses(t_a, t_b, kinetic_energy_cm, L_);
197  }
198 
199  return masses;
200 }
201 
202 void DecayAction::format_debug_output(std::ostream &out) const {
203  out << "Decay of " << incoming_particles_ << " to " << outgoing_particles_
204  << ", sqrt(s)=" << format(sqrt_s(), "GeV", 11, 9);
205 }
206 
207 } // namespace smash
Thrown for example when ScatterAction is called to perform with a wrong number of final-state particl...
Definition: action.h:330
Action is the base class for a generic process that takes a number of incoming particles and transfor...
Definition: action.h:35
FourVector total_momentum_of_outgoing_particles() const
Calculate the total kinetic momentum of the outgoing particles.
Definition: action.cc:163
virtual void sample_angles(std::pair< double, double > masses, double kinetic_energy_cm)
Sample final-state momenta in general X->2 processes (here: using an isotropical angular distribution...
Definition: action.cc:285
ParticleList outgoing_particles_
Initially this stores only the PDG codes of final-state particles.
Definition: action.h:363
virtual void sample_manybody_phasespace()
Sample the full n-body phase-space (masses, momenta, angles) in the center-of-mass frame for the fina...
Definition: action.cc:319
const double time_of_execution_
Time at which the action is supposed to be performed (absolute time in the lab frame in fm).
Definition: action.h:369
void assign_unpolarized_spin_vector_to_outgoing_particles()
Assign an unpolarized spin vector to all outgoing particles.
Definition: action.cc:339
double sqrt_s() const
Determine the total energy in the center-of-mass frame [GeV].
Definition: action.h:271
ParticleList incoming_particles_
List with data of incoming particles.
Definition: action.h:355
ProcessType process_type_
type of process
Definition: action.h:372
bool is_valid(const Particles &particles) const
Check whether the action still applies.
Definition: action.cc:32
Thrown when DecayAction is called to perform with 0 or more than 2 entries in outgoing_particles.
Definition: decayaction.h:106
double partial_width_
partial decay width to the chosen outgoing channel
Definition: decayaction.h:184
double total_width_
total decay width
Definition: decayaction.h:181
bool sample_outgoing_particles()
Sample outgoing particle types, masses and angles return success of sampling.
Definition: decayaction.cc:35
SpinInteractionType spin_interaction_type_
Spin interaction type.
Definition: decayaction.h:191
void add_decays(DecayBranchList pv)
Add several new decays at once.
Definition: decayaction.cc:27
DecayAction(const ParticleData &p, double time, SpinInteractionType spin_interaction_type=SpinInteractionType::Off)
Construct a DecayAction from a particle p.
Definition: decayaction.cc:21
std::optional< bool > was_2body_phase_space_sampled_with_potentials_as_valid_
Optional success flag for sampling outgoing particles.
Definition: decayaction.h:125
void generate_final_state() override
Generate the final state of the decay process.
Definition: decayaction.cc:82
void add_decay(DecayBranchPtr p)
Add one new decay.
Definition: decayaction.cc:31
DecayBranchList decay_channels_
List of possible decays.
Definition: decayaction.h:178
int L_
Angular momentum of the decay.
Definition: decayaction.h:187
void sample_2body_phasespace() override
Sample the full 2-body phase space (masses, momenta, angles) in the center-of-mass frame for the fina...
Definition: decayaction.cc:145
static bool is_sigmastar_to_lambda_pion_decay(const ParticleData &parent, const ParticleData &daughter0, const ParticleData &daughter1, int &lambda_idx, int &pion_idx)
Check for the decay Σ*→Λπ.
Definition: decayaction.h:138
std::pair< double, double > sample_masses(double kinetic_energy_cm) const override
Sample the masses of the final particles.
Definition: decayaction.cc:162
DecayBranch is a derivative of ProcessBranch, which is used to represent decay channels.
ProcessType get_type() const override
int angular_momentum() const
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
double abs() const
calculate the lorentz invariant absolute value
Definition: fourvector.h:464
FourVector lorentz_boost(const ThreeVector &v) const
Returns the FourVector boosted with velocity v.
Definition: fourvector.cc:17
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:59
Particle type contains the static properties of a particle species.
Definition: particletype.h:100
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 ...
double min_mass_kinematic() const
The minimum mass of the resonance that is kinematically allowed.
const std::string & name() const
Definition: particletype.h:144
bool is_stable() const
Definition: particletype.h:251
double mass() const
Definition: particletype.h:147
ParticleList particle_list() const
double weight() const
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.
Definition: logging.h:245
void format_debug_output(std::ostream &out) const override
Writes information about this decay action to the out stream.
Definition: decayaction.cc:202
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...
Definition: logging.h:217
constexpr int p
Proton.
Definition: action.h:24
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
Definition: stringify.cc:26
Potentials * pot_pointer
Pointer to a Potential class.
static constexpr int LDecayModes
Definition: decayaction.cc:19
std::pair< double, double > sample_two_resonance_masses(const ParticleType &t1, const ParticleType &t2, const double cms_energy, int L=0)
Resonance mass sampling for 2-particle final state with two resonances.