Version: SMASH-2.1
scatteractionmulti.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2021
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
11 
12 #include "smash/crosssections.h"
13 #include "smash/integrate.h"
14 #include "smash/logging.h"
15 #include "smash/parametrizations.h"
16 
17 namespace smash {
18 static constexpr int LScatterActionMulti = LogArea::ScatterActionMulti::id;
19 
20 ScatterActionMulti::ScatterActionMulti(const ParticleList& in_plist,
21  double time)
22  : Action(in_plist, time), total_probability_(0.) {}
23 
24 void ScatterActionMulti::add_reaction(CollisionBranchPtr p) {
25  add_process<CollisionBranch>(p, reaction_channels_, total_probability_);
26 }
27 
28 void ScatterActionMulti::add_reactions(CollisionBranchList pv) {
29  add_processes<CollisionBranch>(std::move(pv), reaction_channels_,
31 }
32 
34  double xsec_scaling = 1.0;
35  for (const ParticleData& in_part : incoming_particles_) {
36  xsec_scaling *= in_part.xsec_scaling_factor();
37  }
38  return total_probability_ * xsec_scaling;
39 }
40 
42  double xsec_scaling = 1.0;
43  for (const ParticleData& in_part : incoming_particles_) {
44  xsec_scaling *= in_part.xsec_scaling_factor();
45  }
46  return partial_probability_ * xsec_scaling;
47 }
48 
50  double dt, const double gcell_vol,
51  const MultiParticleReactionsBitSet incl_multi) {
52  // 3 -> m
53  if (incoming_particles_.size() == 3) {
54  // 3 -> 1
55  if (incl_multi[IncludedMultiParticleReactions::Meson_3to1] == 1) {
57  incoming_particles_[2])) {
58  // 3pi -> omega
59  const ParticleTypePtr type_omega = ParticleType::try_find(0x223);
60  if (type_omega) {
61  add_reaction(make_unique<CollisionBranch>(
62  *type_omega,
63  probability_three_to_one(*type_omega, dt, gcell_vol,
64  type_omega->spin_degeneracy()),
66  }
67  // 3pi -> phi
68  const ParticleTypePtr type_phi = ParticleType::try_find(0x333);
69  if (type_phi) {
70  add_reaction(make_unique<CollisionBranch>(
71  *type_phi,
72  probability_three_to_one(*type_phi, dt, gcell_vol,
73  type_phi->spin_degeneracy()),
75  }
77  incoming_particles_[2])) {
78  // eta2pi -> eta-prime
79  const ParticleTypePtr type_eta_prime = ParticleType::try_find(0x331);
80 
81  int sym_factor_in = 1;
82  if (incoming_particles_[0].type() == incoming_particles_[1].type() ||
83  incoming_particles_[1].type() == incoming_particles_[2].type() ||
84  incoming_particles_[2].type() == incoming_particles_[0].type()) {
85  sym_factor_in = 2; // 2 factorial
86  }
87 
88  if (type_eta_prime) {
89  add_reaction(make_unique<CollisionBranch>(
90  *type_eta_prime,
92  *type_eta_prime, dt, gcell_vol,
93  sym_factor_in * type_eta_prime->spin_degeneracy()),
95  }
96  }
97  }
98  // 3 -> 2
99  if (incl_multi[IncludedMultiParticleReactions::Deuteron_3to2] == 1) {
100  const PdgCode pdg_a = incoming_particles_[0].pdgcode();
101  const PdgCode pdg_b = incoming_particles_[1].pdgcode();
102  const PdgCode pdg_c = incoming_particles_[2].pdgcode();
103  const ParticleTypePtr type_deuteron =
105  const ParticleTypePtr type_anti_deuteron =
107 
108  const int spin_factor_inc = pdg_a.spin_degeneracy() *
109  pdg_b.spin_degeneracy() *
110  pdg_c.spin_degeneracy();
111 
112  if (type_deuteron && type_anti_deuteron) {
113  // πpn → πd
114  if ((pdg_a.is_pion() && pdg_b == pdg::p && pdg_c == pdg::n) ||
115  (pdg_a.is_pion() && pdg_b == pdg::n && pdg_c == pdg::p) ||
116  (pdg_a == pdg::p && pdg_b.is_pion() && pdg_c == pdg::n) ||
117  (pdg_a == pdg::n && pdg_b.is_pion() && pdg_c == pdg::p) ||
118  (pdg_a == pdg::p && pdg_b == pdg::n && pdg_c.is_pion()) ||
119  (pdg_a == pdg::n && pdg_b == pdg::p && pdg_c.is_pion())) {
120  // Get type of incoming π
121  ParticleList::iterator it = std::find_if(
123  [](ParticleData x) { return x.is_pion(); });
124  const ParticleType& type_pi = it->type();
125 
126  const double spin_degn =
127  react_degen_factor(spin_factor_inc, type_pi.spin_degeneracy(),
128  type_deuteron->spin_degeneracy());
129 
130  add_reaction(make_unique<CollisionBranch>(
131  type_pi, *type_deuteron,
132  probability_three_to_two(type_pi, *type_deuteron, dt, gcell_vol,
133  spin_degn),
135  }
136 
137  // πp̅n̅ → πd̅
138  if ((pdg_a.is_pion() && pdg_b == -pdg::p && pdg_c == -pdg::n) ||
139  (pdg_a.is_pion() && pdg_b == -pdg::n && pdg_c == -pdg::p) ||
140  (pdg_a == -pdg::p && pdg_b.is_pion() && pdg_c == -pdg::n) ||
141  (pdg_a == -pdg::n && pdg_b.is_pion() && pdg_c == -pdg::p) ||
142  (pdg_a == -pdg::p && pdg_b == -pdg::n && pdg_c.is_pion()) ||
143  (pdg_a == -pdg::n && pdg_b == -pdg::p && pdg_c.is_pion())) {
144  // Get type of incoming π
145  ParticleList::iterator it = std::find_if(
147  [](ParticleData x) { return x.is_pion(); });
148  const ParticleType& type_pi = it->type();
149 
150  const double spin_degn =
151  react_degen_factor(spin_factor_inc, type_pi.spin_degeneracy(),
152  type_anti_deuteron->spin_degeneracy());
153 
154  add_reaction(make_unique<CollisionBranch>(
155  type_pi, *type_anti_deuteron,
156  probability_three_to_two(type_pi, *type_anti_deuteron, dt,
157  gcell_vol, spin_degn),
159  }
160 
161  // Nnp → Nd, N̅np → N̅d
162  if ((pdg_a.is_nucleon() && pdg_b == pdg::p && pdg_c == pdg::n) ||
163  (pdg_a.is_nucleon() && pdg_b == pdg::n && pdg_c == pdg::p) ||
164  (pdg_a == pdg::p && pdg_b.is_nucleon() && pdg_c == pdg::n) ||
165  (pdg_a == pdg::n && pdg_b.is_nucleon() && pdg_c == pdg::p) ||
166  (pdg_a == pdg::p && pdg_b == pdg::n && pdg_c.is_nucleon()) ||
167  (pdg_a == pdg::n && pdg_b == pdg::p && pdg_c.is_nucleon())) {
168  int symmetry_factor = 1; // already true for N̅np → N̅d case
169 
170  ParticleList::iterator it =
171  std::find_if(incoming_particles_.begin(),
172  incoming_particles_.end(), [](ParticleData x) {
173  return x.pdgcode().antiparticle_sign() == -1;
174  });
175  if (it == incoming_particles_.end()) {
176  /* Meaning no anti-N found by find_if,
177  * therefore not N̅np → N̅d, but Nnp → Nd. */
178  symmetry_factor = 2; // for Nnp → Nd (2 factorial)
179  // It is already clear here that we have a double of two N
180  if (pdg_a == pdg_b) {
181  it = incoming_particles_.begin();
182  } else {
183  // If a and b are not the double, then c has to be part of it
184  it = incoming_particles_.begin() + 2;
185  }
186  }
187  const ParticleType& type_N = it->type();
188 
189  const double spin_degn =
190  react_degen_factor(spin_factor_inc, type_N.spin_degeneracy(),
191  type_deuteron->spin_degeneracy());
192 
193  add_reaction(make_unique<CollisionBranch>(
194  type_N, *type_deuteron,
195  probability_three_to_two(type_N, *type_deuteron, dt, gcell_vol,
196  symmetry_factor * spin_degn),
198  }
199 
200  // Np̅n̅ → Nd̅, N̅p̅n̅ → N̅d̅
201  if ((pdg_a.is_nucleon() && pdg_b == -pdg::p && pdg_c == -pdg::n) ||
202  (pdg_a.is_nucleon() && pdg_b == -pdg::n && pdg_c == -pdg::p) ||
203  (pdg_a == -pdg::p && pdg_b.is_nucleon() && pdg_c == -pdg::n) ||
204  (pdg_a == -pdg::n && pdg_b.is_nucleon() && pdg_c == -pdg::p) ||
205  (pdg_a == -pdg::p && pdg_b == -pdg::n && pdg_c.is_nucleon()) ||
206  (pdg_a == -pdg::n && pdg_b == -pdg::p && pdg_c.is_nucleon())) {
207  int symmetry_factor = 1; // already true for Np̅n̅ → Nd̅ case
208 
209  ParticleList::iterator it =
210  std::find_if(incoming_particles_.begin(),
211  incoming_particles_.end(), [](ParticleData x) {
212  return x.pdgcode().antiparticle_sign() == 1;
213  });
214  if (it == incoming_particles_.end()) {
215  /* Meaning no N found by find_if,
216  * therefore not Np̅n̅ → Nd̅, but N̅p̅n̅ → N̅d̅. */
217  symmetry_factor = 2; // for N̅p̅n̅ → N̅d̅ (2 factorial)
218  // It is already clear here that we have a double of two N̅
219  if (pdg_a == pdg_b) {
220  it = incoming_particles_.begin();
221  } else {
222  // If a and b are not the double, then c has to be part of it
223  it = incoming_particles_.begin() + 2;
224  }
225  }
226  const ParticleType& type_N = it->type();
227 
228  const double spin_degn =
229  react_degen_factor(spin_factor_inc, type_N.spin_degeneracy(),
230  type_anti_deuteron->spin_degeneracy());
231 
232  add_reaction(make_unique<CollisionBranch>(
233  type_N, *type_anti_deuteron,
234  probability_three_to_two(type_N, *type_anti_deuteron, dt,
235  gcell_vol, symmetry_factor * spin_degn),
237  }
238  }
239  }
240  }
241  // 5 -> 2
242  if (incoming_particles_.size() == 5) {
243  if (incl_multi[IncludedMultiParticleReactions::NNbar_5to2] == 1) {
245  const int spin_factor_inc =
246  incoming_particles_[0].pdgcode().spin_degeneracy() *
247  incoming_particles_[1].pdgcode().spin_degeneracy() *
248  incoming_particles_[2].pdgcode().spin_degeneracy() *
249  incoming_particles_[3].pdgcode().spin_degeneracy() *
250  incoming_particles_[4].pdgcode().spin_degeneracy();
251  const double symmetry_factor = 4.0; // 2! * 2!
252 
254  const ParticleTypePtr type_anti_p = ParticleType::try_find(-pdg::p);
256  const ParticleTypePtr type_anti_n = ParticleType::try_find(-pdg::n);
257 
258  const double spin_degn =
259  react_degen_factor(spin_factor_inc, type_p->spin_degeneracy(),
260  type_anti_p->spin_degeneracy());
261 
262  if (type_p && type_n) {
263  const double prob = probability_five_to_two(
264  type_p->mass(), dt, gcell_vol,
265  symmetry_factor * spin_degn); // same for ppbar and nnbar
266  add_reaction(make_unique<CollisionBranch>(
267  *type_p, *type_anti_p, prob,
269  add_reaction(make_unique<CollisionBranch>(
270  *type_n, *type_anti_n, prob,
272  }
273  }
274  }
275  }
276 }
277 
279  logg[LScatterActionMulti].debug("Incoming particles for ScatterActionMulti: ",
281 
282  /* Decide for a particular final state. */
283  const CollisionBranch* proc =
284  choose_channel<CollisionBranch>(reaction_channels_, total_probability_);
285  process_type_ = proc->get_type();
287  partial_probability_ = proc->weight();
288 
289  logg[LScatterActionMulti].debug("Chosen channel: ", process_type_,
291 
292  switch (process_type_) {
294  /* n->1 annihilation */
295  annihilation();
296  break;
298  /* 3->2 scattering */
299  three_to_two();
300  break;
302  /* 5->2 scattering */
303  five_to_two();
304  break;
305  default:
307  "ScatterActionMulti::generate_final_state: Invalid process type " +
308  std::to_string(static_cast<int>(process_type_)) + " was requested.");
309  }
310 
311  /* The production point of the new particles. */
312  FourVector middle_point = get_interaction_point();
313 
314  for (ParticleData& new_particle : outgoing_particles_) {
315  // Boost to the computational frame
316  new_particle.boost_momentum(
318  /* Set positions of the outgoing particles */
319  new_particle.set_4position(middle_point);
320  }
321 }
322 
323 double ScatterActionMulti::calculate_I3(const double sqrts) const {
324  static Integrator integrate;
325  const double m1 = incoming_particles_[0].effective_mass();
326  const double m2 = incoming_particles_[1].effective_mass();
327  const double m3 = incoming_particles_[2].effective_mass();
328  const double lower_bound = (m1 + m2) * (m1 + m2);
329  const double upper_bound = (sqrts - m3) * (sqrts - m3);
330  const auto result = integrate(lower_bound, upper_bound, [&](double m12_sqr) {
331  const double m12 = std::sqrt(m12_sqr);
332  const double e2_star = (m12_sqr - m1 * m1 + m2 * m2) / (2 * m12);
333  const double e3_star = (sqrts * sqrts - m12_sqr - m3 * m3) / (2 * m12);
334  const double m23_sqr_min =
335  (e2_star + e3_star) * (e2_star + e3_star) -
336  std::pow(std::sqrt(e2_star * e2_star - m2 * m2) +
337  std::sqrt(e3_star * e3_star - m3 * m3),
338  2.0);
339  const double m23_sqr_max =
340  (e2_star + e3_star) * (e2_star + e3_star) -
341  std::pow(std::sqrt(e2_star * e2_star - m2 * m2) -
342  std::sqrt(e3_star * e3_star - m3 * m3),
343  2.0);
344  return m23_sqr_max - m23_sqr_min;
345  });
346 
347  return result;
348 }
349 
351  const ParticleType& type_out, double dt, const double gcell_vol,
352  const int degen_factor) const {
353  const double e1 = incoming_particles_[0].momentum().x0();
354  const double e2 = incoming_particles_[1].momentum().x0();
355  const double e3 = incoming_particles_[2].momentum().x0();
356  const double sqrts = sqrt_s();
357 
358  const double gamma_decay = type_out.get_partial_width(
359  sqrts, {&incoming_particles_[0].type(), &incoming_particles_[1].type(),
360  &incoming_particles_[2].type()});
361 
362  const double I_3 = calculate_I3(sqrts);
363  const double ph_sp_3 =
364  1. / (8 * M_PI * M_PI * M_PI) * 1. / (16 * sqrts * sqrts) * I_3;
365 
366  const double spec_f_val = type_out.spectral_function(sqrts);
367 
368  return dt / (gcell_vol * gcell_vol) * M_PI / (4. * e1 * e2 * e3) *
369  gamma_decay / ph_sp_3 * spec_f_val * std::pow(hbarc, 5.0) *
370  degen_factor;
371 }
372 
374  const ParticleType& type_out1, const ParticleType& type_out2, double dt,
375  const double gcell_vol, const double degen_factor) const {
376  const double e1 = incoming_particles_[0].momentum().x0();
377  const double e2 = incoming_particles_[1].momentum().x0();
378  const double e3 = incoming_particles_[2].momentum().x0();
379  const double m4 = type_out1.mass();
380  const double m5 = type_out2.mass();
381 
382  const double sqrts = sqrt_s();
383  const double xs =
384  CrossSections::two_to_three_xs(type_out1, type_out2, sqrts) / gev2_mb;
385  const double lamb = lambda_tilde(sqrts * sqrts, m4 * m4, m5 * m5);
386 
387  const double I_3 = calculate_I3(sqrts);
388  const double ph_sp_3 =
389  1. / (8 * M_PI * M_PI * M_PI) * 1. / (16 * sqrts * sqrts) * I_3;
390 
391  return dt / (gcell_vol * gcell_vol) * 1. / (4. * e1 * e2 * e3) * lamb /
392  (ph_sp_3 * 8 * M_PI * sqrts * sqrts) * xs * std::pow(hbarc, 5.0) *
393  degen_factor;
394 }
395 
397  const double mout, double dt, const double gcell_vol,
398  const double degen_factor) const {
399  const double e1 = incoming_particles_[0].momentum().x0();
400  const double e2 = incoming_particles_[1].momentum().x0();
401  const double e3 = incoming_particles_[2].momentum().x0();
402  const double e4 = incoming_particles_[3].momentum().x0();
403  const double e5 = incoming_particles_[4].momentum().x0();
404 
405  const double man_s = sqrt_s() * sqrt_s();
406  const double lamb = lambda_tilde(man_s, mout * mout, mout * mout);
407  const double ph_sp_5 = parametrizaton_phi5_pions(man_s);
408 
409  // Matching the NNbar anihilation cross section defintion for 2-to-5
410  const double xs =
411  std::max(0., ppbar_total(man_s) - ppbar_elastic(man_s)) / gev2_mb;
412 
413  return dt / std::pow(gcell_vol, 4.0) * 1. / (32. * e1 * e2 * e3 * e4 * e5) *
414  xs / (4. * M_PI * man_s) * lamb / ph_sp_5 * std::pow(hbarc, 11.0) *
415  degen_factor;
416 }
417 
418 double ScatterActionMulti::parametrizaton_phi5_pions(const double man_s) const {
419  // see function documentation for parameter naming
420  const double s_zero = 25 * pion_mass * pion_mass;
421  const double fit_a = 2.1018e-10;
422  const double fit_alpha = 1.982;
423  return fit_a * std::pow(man_s - s_zero, 5.0) *
424  std::pow(1 + man_s / s_zero, -fit_alpha);
425 }
426 
428  if (outgoing_particles_.size() != 1) {
429  std::string s =
430  "Annihilation: "
431  "Incorrect number of particles in final state: ";
432  s += std::to_string(outgoing_particles_.size()) + ".";
433  throw InvalidScatterActionMulti(s);
434  }
435  // Set the momentum of the formed particle in its rest frame.
436  outgoing_particles_[0].set_4momentum(
437  total_momentum_of_outgoing_particles().abs(), 0., 0., 0.);
438  // Make sure to assign formation times before boost to the computational frame
440 
441  logg[LScatterActionMulti].debug("Momentum of the new particle: ",
442  outgoing_particles_[0].momentum());
443 }
444 
447  // Make sure to assign formation times before boost to the computational frame
449  logg[LScatterActionMulti].debug("3->2 scattering:", incoming_particles_,
450  " -> ", outgoing_particles_);
451 }
452 
455  // Make sure to assign formation times before boost to the computational frame
457  logg[LScatterActionMulti].debug("5->2 scattering:", incoming_particles_,
458  " -> ", outgoing_particles_);
459 }
460 
462  const ParticleData& data_a, const ParticleData& data_b,
463  const ParticleData& data_c) const {
464  // We want a combination of pi+, pi- and pi0
465  const PdgCode pdg_a = data_a.pdgcode();
466  const PdgCode pdg_b = data_b.pdgcode();
467  const PdgCode pdg_c = data_c.pdgcode();
468 
469  return (pdg_a.is_pion() && pdg_b.is_pion() && pdg_c.is_pion()) &&
470  (pdg_a != pdg_b && pdg_b != pdg_c && pdg_c != pdg_a);
471 }
472 
474  const ParticleData& data_b,
475  const ParticleData& data_c) const {
476  // We want a combination of pi0, pi0 and eta or pi+, pi- and eta
477  const PdgCode pdg_a = data_a.pdgcode();
478  const PdgCode pdg_b = data_b.pdgcode();
479  const PdgCode pdg_c = data_c.pdgcode();
480 
481  return (pdg_a == pdg::pi_z && pdg_b == pdg::pi_z && pdg_c == pdg::eta) ||
482  (pdg_a == pdg::pi_z && pdg_b == pdg::eta && pdg_c == pdg::pi_z) ||
483  (pdg_a == pdg::eta && pdg_b == pdg::pi_z && pdg_c == pdg::pi_z) ||
484 
485  (pdg_a == pdg::eta && pdg_b == pdg::pi_m && pdg_c == pdg::pi_p) ||
486  (pdg_a == pdg::eta && pdg_b == pdg::pi_p && pdg_c == pdg::pi_m) ||
487  (pdg_a == pdg::pi_m && pdg_b == pdg::pi_p && pdg_c == pdg::eta) ||
488  (pdg_a == pdg::pi_m && pdg_b == pdg::eta && pdg_c == pdg::pi_p) ||
489  (pdg_a == pdg::pi_p && pdg_b == pdg::pi_m && pdg_c == pdg::eta) ||
490  (pdg_a == pdg::pi_p && pdg_b == pdg::eta && pdg_c == pdg::pi_m);
491 }
492 
495  const bool all_inc_pi =
497  [](const ParticleData& data) { return data.is_pion(); });
498  const int no_of_piz = std::count_if(
500  [](const ParticleData& data) { return data.pdgcode() == pdg::pi_z; });
501 
502  int total_state_charge = 0;
503  for (const ParticleData& part : incoming_particles_) {
504  total_state_charge += part.pdgcode().charge();
505  }
506 
507  return (all_inc_pi && total_state_charge == 0 && no_of_piz == 1);
508 }
509 
510 void ScatterActionMulti::format_debug_output(std::ostream& out) const {
511  out << "MultiParticleScatter of " << incoming_particles_;
512  if (outgoing_particles_.empty()) {
513  out << " (not performed)";
514  } else {
515  out << " to " << outgoing_particles_;
516  }
517 }
518 
519 } // namespace smash
Action is the base class for a generic process that takes a number of incoming particles and transfor...
Definition: action.h:35
void sample_2body_phasespace()
Sample the full 2-body phase-space (masses, momenta, angles) in the center-of-mass frame for the fina...
Definition: action.cc:297
FourVector total_momentum_of_outgoing_particles() const
Calculate the total kinetic momentum of the outgoing particles.
Definition: action.cc:152
void assign_formation_time_to_outgoing_particles()
Assign the formation time to the outgoing particles.
Definition: action.cc:183
ParticleList outgoing_particles_
Initially this stores only the PDG codes of final-state particles.
Definition: action.h:339
double sqrt_s() const
Determine the total energy in the center-of-mass frame [GeV].
Definition: action.h:266
ParticleList incoming_particles_
List with data of incoming particles.
Definition: action.h:331
FourVector get_interaction_point() const
Get the interaction point.
Definition: action.cc:67
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 ...
Definition: action.h:310
ProcessType process_type_
type of process
Definition: action.h:348
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.
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
A C++ interface for numerical integration in one dimension with the GSL CQUAD integration functions.
Definition: integrate.h:106
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:58
PdgCode pdgcode() const
Get the pdgcode of the particle.
Definition: particledata.h:87
A pointer-like interface to global references to ParticleType objects.
Definition: particletype.h:665
Particle type contains the static properties of a particle species.
Definition: particletype.h:97
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.
Definition: particletype.cc:89
unsigned int spin_degeneracy() const
Definition: particletype.h:194
double mass() const
Definition: particletype.h:144
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
Definition: pdgcode.h:108
bool is_pion() const
Definition: pdgcode.h:384
static PdgCode from_decimal(const int pdgcode_decimal)
Construct PDG code from decimal number.
Definition: pdgcode.h:269
bool is_nucleon() const
Definition: pdgcode.h:324
unsigned int spin_degeneracy() const
Definition: pdgcode.h:542
ParticleList particle_list() const
double weight() const
Thrown when ScatterActionMulti is called to perform with unknown combination of incoming and outgoing...
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.
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 3->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_three_to_one(const ParticleType &type_out, double dt, const double gcell_vol, const int degen_factor=1) const
Calculate the probability for a 3m-to-1 reaction according to the stochastic collision criterion as g...
CollisionBranchList reaction_channels_
List of possible collisions.
double calculate_I3(const double sqrts) const
Calculate the integration necessary for the three-body phase space.
void three_to_two()
Perform a 3->2 process.
void five_to_two()
Perform a 5->2 process.
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.
double probability_three_to_two(const ParticleType &type_out1, const ParticleType &type_out2, double dt, const double gcell_vol, const double degen_factor=1.0) const
Calculate the probability for a 3-to-2 reaction according to the stochastic collision criterion as gi...
double probability_five_to_two(const double m_out, double dt, const double gcell_vol, const double degen_factor=1.0) const
Calculate the probability for a 5-to-2 reaction according to the stochastic collision criterion as gi...
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 annihilation()
Perform a n->1 annihilation process.
@ NNbar_5to2
@ Deuteron_3to2
@ Meson_3to1
std::bitset< 3 > 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.
Definition: logging.cc:39
constexpr int pi_p
π⁺.
constexpr int p
Proton.
constexpr int eta
η.
constexpr int pi_z
π⁰.
constexpr int n
Neutron.
constexpr int pi_m
π⁻.
constexpr int decimal_antid
Anti-deuteron in decimal digits.
constexpr int decimal_d
Deuteron in decimal digits.
Definition: action.h:24
constexpr double gev2_mb
GeV^-2 <-> mb conversion factor.
Definition: constants.h:31
double ppbar_total(double mandelstam_s)
ppbar total cross section parametrization Source: Bass:1998ca
static constexpr int LScatterActionMulti
static Integrator integrate
Definition: decaytype.cc:144
double ppbar_elastic(double mandelstam_s)
ppbar elastic cross section parametrization Source: Bass:1998ca
@ MultiParticleThreeMesonsToOne
multi particle scattering
bool all_of(Container &&c, UnaryPredicate &&p)
Convenience wrapper for std::all_of that operates on a complete container.
Definition: algorithms.h:80
constexpr double pion_mass
Pion mass in GeV.
Definition: constants.h:65
constexpr double hbarc
GeV <-> fm conversion factor.
Definition: constants.h:25