Version: SMASH-2.0
decaymodes.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2020
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/decaymodes.h"
11 
12 #include <vector>
13 
14 #include "smash/clebschgordan.h"
15 #include "smash/constants.h"
16 #include "smash/cxx14compat.h"
17 #include "smash/inputfunctions.h"
18 #include "smash/isoparticletype.h"
19 #include "smash/logging.h"
20 #include "smash/stringfunctions.h"
21 
22 namespace smash {
23 static constexpr int LDecayModes = LogArea::DecayModes::id;
24 
26 std::vector<DecayModes> *DecayModes::all_decay_modes = nullptr;
28 std::vector<DecayTypePtr> *all_decay_types = nullptr;
29 
30 void DecayModes::add_mode(ParticleTypePtr mother, double ratio, int L,
31  ParticleTypePtrList particle_types) {
32  DecayType *type = get_decay_type(mother, particle_types, L);
33  // Check if mode already exists: if yes, add weight.
34  for (auto &mode : decay_modes_) {
35  if (type == &mode->type()) {
36  mode->set_weight(mode->weight() + ratio);
37  return;
38  }
39  }
40  // Add new mode.
41  decay_modes_.push_back(make_unique<DecayBranch>(*type, ratio));
42 }
43 
45  ParticleTypePtrList particle_types,
46  int L) {
47  assert(all_decay_types != nullptr);
48 
49  // check if the decay type already exisits
50  for (const auto &type : *all_decay_types) {
51  if (type->has_mother(mother) && type->has_particles(particle_types) &&
52  type->angular_momentum() == L) {
53  return type.get();
54  }
55  }
56 
57  // if the type does not exist yet, create a new one
58  switch (particle_types.size()) {
59  case 2:
60  if (is_dilepton(particle_types[0]->pdgcode(),
61  particle_types[1]->pdgcode())) {
62  all_decay_types->emplace_back(
63  make_unique<TwoBodyDecayDilepton>(particle_types, L));
64  } else if (particle_types[0]->is_stable() &&
65  particle_types[1]->is_stable()) {
66  all_decay_types->emplace_back(
67  make_unique<TwoBodyDecayStable>(particle_types, L));
68  } else if (particle_types[0]->is_stable() ||
69  particle_types[1]->is_stable()) {
70  all_decay_types->emplace_back(
71  make_unique<TwoBodyDecaySemistable>(particle_types, L));
72  } else {
73  all_decay_types->emplace_back(
74  make_unique<TwoBodyDecayUnstable>(particle_types, L));
75  }
76  break;
77  case 3:
78  if (has_lepton_pair(particle_types[0]->pdgcode(),
79  particle_types[1]->pdgcode(),
80  particle_types[2]->pdgcode())) {
81  all_decay_types->emplace_back(
82  make_unique<ThreeBodyDecayDilepton>(mother, particle_types, L));
83  } else {
84  all_decay_types->emplace_back(
85  make_unique<ThreeBodyDecay>(particle_types, L));
86  }
87  break;
88  default:
89  throw InvalidDecay(
90  "DecayModes::get_decay_type was instructed to add a decay mode "
91  "with " +
92  std::to_string(particle_types.size()) +
93  " particles. This is an invalid input.");
94  }
95 
96  return all_decay_types->back().get();
97 }
98 
99 bool DecayModes::renormalize(const std::string &name) {
100  double sum = 0.;
101  bool is_large_renormalization = false;
102  for (auto &mode : decay_modes_) {
103  sum += mode->weight();
104  }
105  if (std::abs(sum - 1.) < really_small) {
106  logg[LDecayModes].debug("Particle ", name,
107  ": Extremely small renormalization constant: ", sum,
108  "\n=> Skipping the renormalization.");
109  } else {
110  is_large_renormalization = (std::abs(sum - 1.) > 0.01);
111  logg[LDecayModes].debug("Particle ", name,
112  ": Renormalizing decay modes with ", sum);
113  double new_sum = 0.0;
114  for (auto &mode : decay_modes_) {
115  mode->set_weight(mode->weight() / sum);
116  new_sum += mode->weight();
117  }
118  logg[LDecayModes].debug("After renormalization sum of ratios is ", new_sum);
119  }
120  return is_large_renormalization;
121 }
122 
123 /* unnamed namespace; its content is accessible only in this file.
124  * This is identically the same as have a static function, but if one
125  * wanted to specify a file-local type, this would be the way to go. */
126 namespace {
133 inline std::size_t find_offset(PdgCode pdg) {
134  return std::addressof(ParticleType::find(pdg)) -
135  std::addressof(ParticleType::list_all()[0]);
136 }
137 } // unnamed namespace
138 
139 static int min_angular_momentum(int s0, int s1, int s2) {
140  int min_L = std::min(std::abs(s0 - s1 - s2), std::abs(s0 - s1 + s2));
141  min_L = std::min(min_L, std::abs(s0 + s1 - s2));
142  if (min_L % 2 != 0) {
143  throw std::runtime_error(
144  "min_angular_momentum: sum of spins should be integer");
145  }
146  return min_L / 2.;
147 }
148 
149 static int min_angular_momentum(int s0, int s1, int s2, int s3) {
150  int min_L =
151  std::min(std::abs(s0 - s1 + s2 + s3), std::abs(s0 + s1 - s2 + s3));
152  min_L = std::min(min_L, std::abs(s0 + s1 + s2 - s3));
153  min_L = std::min(min_L, std::abs(s0 - s1 - s2 + s3));
154  min_L = std::min(min_L, std::abs(s0 - s1 + s2 - s3));
155  min_L = std::min(min_L, std::abs(s0 + s1 - s2 - s3));
156  min_L = std::min(min_L, std::abs(s0 - s1 - s2 - s3));
157  if (min_L % 2 != 0) {
158  throw std::runtime_error(
159  "min_angular_momentum: sum of spins should be integer");
160  }
161  return min_L / 2.;
162 }
163 
164 void DecayModes::load_decaymodes(const std::string &input) {
165  // create the DecayType vector first, then it outlives the DecayModes vector,
166  // which references the DecayType objects.
167  static std::vector<DecayTypePtr> decaytypes;
168  decaytypes.clear(); // in case an exception was thrown and should try again
169  // ten decay types per decay mode should be a good guess.
170  decaytypes.reserve(10 * ParticleType::list_all().size());
171  all_decay_types = &decaytypes;
172 
173  static std::vector<DecayModes> decaymodes;
174  decaymodes.clear(); // in case an exception was thrown and should try again
175  decaymodes.resize(ParticleType::list_all().size());
176  all_decay_modes = &decaymodes;
177 
178  const IsoParticleType *isotype_mother = nullptr;
179  ParticleTypePtrList mother_states;
180  std::vector<DecayModes> decay_modes_to_add; // one for each mother state
181  int total_large_renormalized = 0;
182 
183  const auto end_of_decaymodes = [&]() {
184  if (isotype_mother == nullptr) { // at the start of the file
185  return;
186  }
187  // Loop over all states in the mother multiplet and add modes
188  for (size_t m = 0; m < mother_states.size(); m++) {
189  if (decay_modes_to_add[m].is_empty() && !mother_states[m]->is_stable()) {
190  throw MissingDecays("No decay modes found for particle " +
191  mother_states[m]->name());
192  }
193  bool is_large_renorm =
194  decay_modes_to_add[m].renormalize(mother_states[m]->name());
195  total_large_renormalized += is_large_renorm;
196  PdgCode pdgcode = mother_states[m]->pdgcode();
197  /* Add the list of decay modes for this particle type */
198  decaymodes[find_offset(pdgcode)] = std::move(decay_modes_to_add[m]);
199  }
200  if (isotype_mother->has_anti_multiplet()) {
201  /* Construct the decay modes for the anti-multiplet. */
202  logg[LDecayModes].debug("generating decay modes for anti-multiplet: " +
203  isotype_mother->name());
204  for (const auto &state : mother_states) {
205  PdgCode pdg = state->pdgcode();
206  PdgCode pdg_anti = pdg.get_antiparticle();
207  const ParticleType &type_anti = ParticleType::find(pdg_anti);
208  DecayModes &decay_modes_orig = decaymodes[find_offset(pdg)];
209  DecayModes &decay_modes_anti = decaymodes[find_offset(pdg_anti)];
210  for (const auto &mode : decay_modes_orig.decay_mode_list()) {
211  ParticleTypePtrList list = mode->particle_types();
212  for (auto &type : list) {
213  if (type->has_antiparticle()) {
214  type = type->get_antiparticle();
215  }
216  }
217  decay_modes_anti.add_mode(&type_anti, mode->weight(),
218  mode->angular_momentum(), list);
219  }
220  }
221  }
222  };
223 
224  // Track the line number for better error messages.
225  // FIXME: At the moment this does not include comments and empty lines.
226  uint64_t linenumber = 1;
227  for (const Line &line : line_parser(input)) {
228  const auto trimmed = trim(line.text);
229  assert(!trimmed.empty()); // trim(line.text) is never empty,
230  // else line_parser is broken
231  if (trimmed.find_first_of(" \t") == std::string::npos) {
232  // a single record on one line signifies a new decay mode section
233  end_of_decaymodes();
234  std::string name = trim(line.text);
235  isotype_mother = &IsoParticleType::find(name);
236  mother_states = isotype_mother->get_states();
237  decay_modes_to_add.clear();
238  decay_modes_to_add.resize(mother_states.size());
239  logg[LDecayModes].debug("reading decay modes for " + name);
240  // check if any of the states have decay modes already
241  for (size_t m = 0; m < mother_states.size(); m++) {
242  PdgCode pdgcode = mother_states[m]->pdgcode();
243  if (!decaymodes[find_offset(pdgcode)].is_empty()) {
244  throw LoadFailure("Duplicate entry for " + name +
245  " in decaymodes.txt:" + std::to_string(linenumber));
246  }
247  }
248  } else {
249  std::istringstream lineinput(line.text);
250  std::vector<std::string> decay_particles;
251  decay_particles.reserve(3);
252  double ratio;
253  lineinput >> ratio;
254 
255  int L;
256  lineinput >> L;
257  if (L < 0) {
258  throw LoadFailure("Invalid angular momentum '" + std::to_string(L) +
259  "' in decaymodes.txt:" + std::to_string(line.number) +
260  ": '" + line.text + "'");
261  }
262 
263  std::string name;
264  lineinput >> name;
265  bool multi = true;
266  while (lineinput) {
267  decay_particles.emplace_back(name);
268  const auto isotype = IsoParticleType::try_find(name);
269  const bool is_multiplet = isotype;
270  const bool is_state = ParticleType::exists(name);
271  if (!is_multiplet && !is_state) {
272  throw InvalidDecay(
273  "Daughter " + name +
274  " is neither an isospin multiplet nor a particle." + " (line " +
275  std::to_string(linenumber) + ": \"" + trimmed + "\")");
276  }
277  const bool is_hadronic_multiplet =
278  is_multiplet && isotype->get_states()[0]->is_hadron();
279  multi &= is_hadronic_multiplet;
280  lineinput >> name;
281  }
282  Parity parity;
283  const int s0 = isotype_mother->spin();
284  int min_L = 0;
285  int max_L = 0;
286  if (multi) {
287  /* References to isospin multiplets: Automatically determine all valid
288  * combinations and calculate Clebsch-Gordan factors */
289  switch (decay_particles.size()) {
290  case 2: {
291  const IsoParticleType &isotype_daughter_1 =
292  IsoParticleType::find(decay_particles[0]);
293  const IsoParticleType &isotype_daughter_2 =
294  IsoParticleType::find(decay_particles[1]);
295  parity = isotype_daughter_1.parity() * isotype_daughter_2.parity();
296  const int s1 = isotype_daughter_1.spin();
297  const int s2 = isotype_daughter_2.spin();
298  min_L = min_angular_momentum(s0, s1, s2);
299  max_L = (s0 + s1 + s2) / 2;
300  // loop through multiplets
301  bool forbidden_by_isospin = true;
302  for (size_t m = 0; m < mother_states.size(); m++) {
303  for (const auto &daughter1 : isotype_daughter_1.get_states()) {
304  for (const auto &daughter2 : isotype_daughter_2.get_states()) {
305  // calculate Clebsch-Gordan factor
306  const double cg_sqr = isospin_clebsch_gordan_sqr_2to1(
307  *daughter1, *daughter2, *mother_states[m]);
308  if (cg_sqr > 0.) {
309  // add mode
310  logg[LDecayModes].debug(
311  "decay mode generated: " + mother_states[m]->name() +
312  " -> " + daughter1->name() + " " + daughter2->name() +
313  " (" + std::to_string(ratio * cg_sqr) + ")");
314  decay_modes_to_add[m].add_mode(mother_states[m],
315  ratio * cg_sqr, L,
316  {daughter1, daughter2});
317  forbidden_by_isospin = false;
318  }
319  }
320  }
321  }
322  if (forbidden_by_isospin) {
323  std::stringstream s;
324  s << ",\nwhere isospin mother: " << isotype_mother->isospin()
325  << ", daughters: " << isotype_daughter_1.isospin() << " "
326  << isotype_daughter_2.isospin();
327  throw InvalidDecay(isotype_mother->name() +
328  " decay mode is forbidden by isospin: \"" +
329  line.text + "\"" + s.str());
330  }
331  break;
332  }
333  case 3: {
334  const IsoParticleType &isotype_daughter_1 =
335  IsoParticleType::find(decay_particles[0]);
336  const IsoParticleType &isotype_daughter_2 =
337  IsoParticleType::find(decay_particles[1]);
338  const IsoParticleType &isotype_daughter_3 =
339  IsoParticleType::find(decay_particles[2]);
340  parity = isotype_daughter_1.parity() * isotype_daughter_2.parity() *
341  isotype_daughter_3.parity();
342  const int s1 = isotype_daughter_1.spin();
343  const int s2 = isotype_daughter_2.spin();
344  const int s3 = isotype_daughter_2.spin();
345  min_L = min_angular_momentum(s0, s1, s2, s3);
346  max_L = (s0 + s1 + s2 + s3) / 2;
347  // loop through multiplets
348  for (size_t m = 0; m < mother_states.size(); m++) {
349  for (const auto &daughter1 : isotype_daughter_1.get_states()) {
350  for (const auto &daughter2 : isotype_daughter_2.get_states()) {
351  for (const auto &daughter3 :
352  isotype_daughter_3.get_states()) {
353  const double cg_sqr = isospin_clebsch_gordan_sqr_3to1(
354  *daughter1, *daughter2, *daughter3, *mother_states[m]);
355  if (cg_sqr > 0.) {
356  // add mode
357  logg[LDecayModes].debug(
358  "decay mode generated: " + mother_states[m]->name() +
359  " -> " + daughter1->name() + " " + daughter2->name() +
360  " " + daughter3->name() + " (" +
361  std::to_string(ratio * cg_sqr) + ")");
362  decay_modes_to_add[m].add_mode(
363  mother_states[m], ratio * cg_sqr, L,
364  {daughter1, daughter2, daughter3});
365  }
366  }
367  }
368  }
369  }
370  break;
371  }
372  default:
373  throw std::runtime_error(
374  "References to isospin multiplets only "
375  "allowed in two-body or three-body decays: " +
376  line.text + " (line " + std::to_string(linenumber) + ": \"" +
377  trimmed + "\")");
378  }
379  } else {
380  /* References to specific states, not multiplets:
381  * Loop over all mother states and check charge conservation. */
382  ParticleTypePtrList types;
383  int charge = 0;
384  parity = Parity::Pos;
385  for (auto part : decay_particles) {
386  try {
387  types.push_back(IsoParticleType::find_state(part));
388  } catch (std::runtime_error &e) {
389  throw std::runtime_error(std::string() + e.what() + " (line " +
390  std::to_string(linenumber) + ": \"" +
391  trimmed + "\")");
392  }
393  charge += types.back()->charge();
394  parity *= types.back()->parity();
395  }
396  if (types.size() == 2) {
397  const int s1 = types[0]->spin();
398  const int s2 = types[1]->spin();
399  min_L = min_angular_momentum(s0, s1, s2);
400  max_L = (s0 + s1 + s2) / 2;
401  } else if (types.size() == 3) {
402  const int s1 = types[0]->spin();
403  const int s2 = types[1]->spin();
404  const int s3 = types[2]->spin();
405  min_L = min_angular_momentum(s0, s1, s2, s3);
406  max_L = (s0 + s1 + s2 + s3) / 2;
407  } else {
408  throw InvalidDecay(isotype_mother->name() +
409  " decay mode has an invalid number of particles"
410  " in the final state " +
411  "(line " + std::to_string(linenumber) + ": \"" +
412  trimmed + "\")");
413  }
414  bool no_decays = true;
415  for (size_t m = 0; m < mother_states.size(); m++) {
416  if (mother_states[m]->charge() == charge) {
417  logg[LDecayModes].debug(
418  "decay mode found: ", mother_states[m]->name(), " -> ",
419  decay_particles.size());
420  decay_modes_to_add[m].add_mode(mother_states[m], ratio, L, types);
421  no_decays = false;
422  }
423  }
424  if (no_decays) {
425  throw InvalidDecay(isotype_mother->name() +
426  " decay mode violates charge conservation " +
427  "(line " + std::to_string(linenumber) + ": \"" +
428  trimmed + "\")");
429  }
430  }
431  // Take angular momentum into account.
432  // FIXME: At the moment this is not correct for 3-body decays (see #517),
433  // therefore only check paritiy for 2-body decays below.
434  if (L % 2 == 1) {
435  parity = -parity;
436  }
437  // Make sure the decay has the correct parity for 2-body decays
438  if (decay_particles.size() == 2 && parity != mother_states[0]->parity()) {
439  throw InvalidDecay(mother_states[0]->name() +
440  " decay mode violates parity conservation " +
441  "(line " + std::to_string(linenumber) + ": \"" +
442  trimmed + "\")");
443  }
444  // Make sure the decay has a correct angular momentum.
445  if (L < min_L || L > max_L) {
446  throw InvalidDecay(
447  mother_states[0]->name() +
448  " decay mode violates angular momentum conservation: " +
449  std::to_string(L) + " not in [" + std::to_string(min_L) + ", " +
450  std::to_string(max_L) + "] (line " + std::to_string(linenumber) +
451  ": \"" + trimmed + "\")");
452  }
453  }
454  linenumber++;
455  }
456  end_of_decaymodes();
457 
458  // Check whether the mother's pole mass is strictly larger than the minimal
459  // masses of the daughters. This is required by the Manley-Saleski ansatz.
460  const auto &particles = ParticleType::list_all();
461  for (const auto &mother : particles) {
462  if (mother.is_stable()) {
463  continue;
464  }
465  const auto &decays = mother.decay_modes().decay_mode_list();
466  for (const auto &decay : decays) {
467  if (mother.mass() <= decay->threshold()) {
468  std::stringstream s;
469  s << mother.name() << " → ";
470  for (const auto &p : decay->particle_types()) {
471  s << p->name();
472  }
473  s << " with " << mother.mass() << " ≤ " << decay->threshold();
474  throw InvalidDecay(
475  "For all decays, the minimum mass of daughters"
476  "must be smaller\nthan the mother's pole mass "
477  "(Manley-Saleski Ansatz)\n"
478  "Violated by the following decay: " +
479  s.str());
480  }
481  }
482  }
483  if (total_large_renormalized > 0) {
484  logg[LDecayModes].warn(
485  "Branching ratios of ", total_large_renormalized,
486  " hadrons were renormalized by more than 1% to have sum 1.");
487  }
488 }
489 
490 } // namespace smash
smash::line_parser
build_vector_< Line > line_parser(const std::string &input)
Helper function for parsing particles.txt and decaymodes.txt.
Definition: inputfunctions.cc:21
smash::anonymous_namespace{decaymodes.cc}::find_offset
std::size_t find_offset(PdgCode pdg)
Passes back the address offset of a particletype in the list of all particles.
Definition: decaymodes.cc:133
smash
Definition: action.h:24
smash::ParticleType::exists
static bool exists(PdgCode pdgcode)
Definition: particletype.cc:107
smash::PdgCode::get_antiparticle
PdgCode get_antiparticle() const
Construct the antiparticle to a given PDG code.
Definition: pdgcode.h:257
smash::DecayModes::load_decaymodes
static void load_decaymodes(const std::string &input)
Loads the DecayModes map as described in the input string.
Definition: decaymodes.cc:164
smash::IsoParticleType::isospin
int isospin() const
Returns twice the total isospin of the multiplet.
Definition: isoparticletype.h:75
smash::DecayModes::decay_modes_
DecayBranchList decay_modes_
Vector of decay modes.
Definition: decaymodes.h:123
smash::IsoParticleType::parity
Parity parity() const
Definition: isoparticletype.h:86
smash::IsoParticleType::find
static const IsoParticleType & find(const std::string &name)
Returns the IsoParticleType object for the given name.
Definition: isoparticletype.cc:61
smash::DecayType
DecayType is the abstract base class for all decay types.
Definition: decaytype.h:23
smash::DecayModes::renormalize
bool renormalize(const std::string &name)
Renormalize the branching ratios to add up to 1.
Definition: decaymodes.cc:99
smash::IsoParticleType::name
const std::string & name() const
Returns the name of the multiplet.
Definition: isoparticletype.h:66
smash::DecayModes::decay_mode_list
const DecayBranchList & decay_mode_list() const
Definition: decaymodes.h:63
smash::all_decay_types
std::vector< DecayTypePtr > * all_decay_types
Global pointer to the decay types list.
Definition: decaymodes.cc:28
cxx14compat.h
smash::IsoParticleType::has_anti_multiplet
bool has_anti_multiplet() const
Check if there is a multiplet of antiparticles, which is different from the original multiplet.
Definition: isoparticletype.cc:119
smash::Line
Line consists of a line number and the contents of that line.
Definition: inputfunctions.h:23
smash::IsoParticleType::spin
unsigned int spin() const
Returns twice the spin of the multiplet.
Definition: isoparticletype.h:81
clebschgordan.h
smash::DecayModes::get_decay_type
static DecayType * get_decay_type(ParticleTypePtr mother, ParticleTypePtrList particle_types, int L)
Retrieve a decay type.
Definition: decaymodes.cc:44
smash::logg
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
smash::really_small
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
smash::ParticleType::find
static const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
Definition: particletype.cc:99
smash::DecayModes::InvalidDecay
Definition: decaymodes.h:101
smash::ParticleTypePtr
Definition: particletype.h:665
smash::min_angular_momentum
static int min_angular_momentum(int s0, int s1, int s2)
Definition: decaymodes.cc:139
smash::IsoParticleType::find_state
static const ParticleTypePtr find_state(const std::string &name)
Returns the ParticleType object for the given name, by first finding the correct multiplet and then l...
Definition: isoparticletype.cc:123
smash::LDecayModes
static constexpr int LDecayModes
Definition: decayaction.cc:17
smash::DecayModes::LoadFailure
Definition: decaymodes.h:105
isoparticletype.h
smash::IsoParticleType
Definition: isoparticletype.h:28
smash::ParticleType
Definition: particletype.h:97
smash::PdgCode
Definition: pdgcode.h:108
smash::DecayModes::is_empty
bool is_empty() const
Definition: decaymodes.h:60
smash::Parity::Pos
Positive parity.
smash::IsoParticleType::try_find
static const IsoParticleType * try_find(const std::string &name)
Returns the IsoParticleType pointer for the given name.
Definition: isoparticletype.cc:57
smash::DecayModes
Definition: decaymodes.h:29
smash::DecayModes::add_mode
void add_mode(ParticleTypePtr mother, double ratio, int L, ParticleTypePtrList particle_types)
Add a decay mode using all necessary information.
Definition: decaymodes.cc:30
smash::has_lepton_pair
bool has_lepton_pair(const PdgCode pdg1, const PdgCode pdg2, const PdgCode pdg3)
Definition: pdgcode.h:1004
constants.h
logging.h
smash::trim
std::string trim(const std::string &s)
Strip leading and trailing whitespaces.
Definition: stringfunctions.cc:75
smash::DecayModes::all_decay_modes
static std::vector< DecayModes > * all_decay_modes
A list of all DecayModes objects using the same indexing as all_particle_types.
Definition: decaymodes.h:132
smash::isospin_clebsch_gordan_sqr_3to1
double isospin_clebsch_gordan_sqr_3to1(const ParticleType &p_a, const ParticleType &p_b, const ParticleType &p_c, const ParticleType &Res)
Calculate the squared isospin Clebsch-Gordan coefficient for three particles p_a, p_b and p_c couplin...
Definition: clebschgordan.cc:51
smash::Parity
Parity
Represent the parity of a particle type.
Definition: particletype.h:24
smash::pdg::p
constexpr int p
Proton.
Definition: pdgcode_constants.h:28
smash::isospin_clebsch_gordan_sqr_2to1
double isospin_clebsch_gordan_sqr_2to1(const ParticleType &p_a, const ParticleType &p_b, const ParticleType &Res)
Calculate the squared isospin Clebsch-Gordan coefficient for two particles p_a and p_b coupling to a ...
Definition: clebschgordan.h:42
smash::DecayModes::MissingDecays
Definition: decaymodes.h:109
inputfunctions.h
stringfunctions.h
smash::is_dilepton
bool is_dilepton(const PdgCode pdg1, const PdgCode pdg2)
Definition: pdgcode.h:992
smash::IsoParticleType::get_states
ParticleTypePtrList get_states() const
Returns list of states that form part of the multiplet.
Definition: isoparticletype.h:94
smash::ParticleType::list_all
static const ParticleTypeList & list_all()
Definition: particletype.cc:51
decaymodes.h