167   static std::vector<DecayTypePtr> decaytypes;
 
  173   static std::vector<DecayModes> decaymodes;
 
  178   const IsoParticleType *isotype_mother = 
nullptr;
 
  179   ParticleTypePtrList mother_states;
 
  180   std::vector<DecayModes> decay_modes_to_add;  
 
  181   int total_large_renormalized = 0;
 
  183   const auto end_of_decaymodes = [&]() {
 
  184     if (isotype_mother == 
nullptr) {  
 
  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());
 
  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();
 
  198       decaymodes[
find_offset(pdgcode)] = std::move(decay_modes_to_add[m]);
 
  200     if (isotype_mother->has_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();
 
  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();
 
  217           decay_modes_anti.add_mode(&type_anti, mode->weight(),
 
  218                                     mode->angular_momentum(), list);
 
  226   uint64_t linenumber = 1;
 
  228     const auto trimmed = 
trim(line.text);
 
  229     assert(!trimmed.empty());  
 
  231     if (trimmed.find_first_of(
" \t") == std::string::npos) {
 
  234       std::string name = 
trim(line.text);
 
  236       mother_states = isotype_mother->get_states();
 
  237       decay_modes_to_add.clear();
 
  238       decay_modes_to_add.resize(mother_states.size());
 
  241       for (
size_t m = 0; m < mother_states.size(); m++) {
 
  242         PdgCode pdgcode = mother_states[m]->pdgcode();
 
  244           throw LoadFailure(
"Duplicate entry for " + name +
 
  245                             " in decaymodes.txt:" + std::to_string(linenumber));
 
  249       std::istringstream lineinput(line.text);
 
  250       std::vector<std::string> decay_particles;
 
  251       decay_particles.reserve(3);
 
  258         throw LoadFailure(
"Invalid angular momentum '" + std::to_string(L) +
 
  259                           "' in decaymodes.txt:" + std::to_string(line.number) +
 
  260                           ": '" + line.text + 
"'");
 
  267         decay_particles.emplace_back(name);
 
  269         const bool is_multiplet = isotype;
 
  271         if (!is_multiplet && !is_state) {
 
  274               " is neither an isospin multiplet nor a particle." + 
" (line " +
 
  275               std::to_string(linenumber) + 
": \"" + trimmed + 
"\")");
 
  277         const bool is_hadronic_multiplet =
 
  278             is_multiplet && isotype->get_states()[0]->is_hadron();
 
  279         multi &= is_hadronic_multiplet;
 
  283       const int s0 = isotype_mother->spin();
 
  289         switch (decay_particles.size()) {
 
  291             const IsoParticleType &isotype_daughter_1 =
 
  293             const IsoParticleType &isotype_daughter_2 =
 
  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();
 
  299             max_L = (s0 + s1 + s2) / 2;
 
  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()) {
 
  307                       *daughter1, *daughter2, *mother_states[m]);
 
  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],
 
  316                                                    {daughter1, daughter2});
 
  317                     forbidden_by_isospin = 
false;
 
  322             if (forbidden_by_isospin) {
 
  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());
 
  334             const IsoParticleType &isotype_daughter_1 =
 
  336             const IsoParticleType &isotype_daughter_2 =
 
  338             const IsoParticleType &isotype_daughter_3 =
 
  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();
 
  346             max_L = (s0 + s1 + s2 + s3) / 2;
 
  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()) {
 
  354                         *daughter1, *daughter2, *daughter3, *mother_states[m]);
 
  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});
 
  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) + 
": \"" +
 
  382         ParticleTypePtrList types;
 
  385         for (
auto part : decay_particles) {
 
  388           } 
catch (std::runtime_error &e) {
 
  389             throw std::runtime_error(std::string() + e.what() + 
" (line " +
 
  390                                      std::to_string(linenumber) + 
": \"" +
 
  393           charge += types.back()->charge();
 
  394           parity *= types.back()->parity();
 
  396         if (types.size() == 2) {
 
  397           const int s1 = types[0]->spin();
 
  398           const int s2 = types[1]->spin();
 
  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();
 
  406           max_L = (s0 + s1 + s2 + s3) / 2;
 
  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) + 
": \"" +
 
  414         bool no_decays = 
true;
 
  415         for (
size_t m = 0; m < mother_states.size(); m++) {
 
  416           if (mother_states[m]->charge() == charge) {
 
  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);
 
  425           throw InvalidDecay(isotype_mother->name() +
 
  426                              " decay mode violates charge conservation " +
 
  427                              "(line " + std::to_string(linenumber) + 
": \"" +
 
  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) + 
": \"" +
 
  445       if (L < min_L || L > max_L) {
 
  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 + 
"\")");
 
  461   for (
const auto &mother : particles) {
 
  462     if (mother.is_stable()) {
 
  465     const auto &decays = mother.decay_modes().decay_mode_list();
 
  466     for (
const auto &decay : decays) {
 
  467       if (mother.mass() <= decay->threshold()) {
 
  469         s << mother.name() << 
" →  ";
 
  470         for (
const auto &
p : decay->particle_types()) {
 
  473         s << 
" with " << mother.mass() << 
" ≤ " << decay->threshold();
 
  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: " +
 
  483   if (total_large_renormalized > 0) {
 
  485         "Branching ratios of ", total_large_renormalized,
 
  486         " hadrons were renormalized by more than 1% to have sum 1.");
 
static std::vector< DecayModes > * all_decay_modes
A list of all DecayModes objects using the same indexing as all_particle_types.
 
static const IsoParticleType * try_find(const std::string &name)
Returns the IsoParticleType pointer for the given name.
 
static const IsoParticleType & find(const std::string &name)
Returns the IsoParticleType object for the given name.
 
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...
 
static const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
 
static bool exists(PdgCode pdgcode)
 
static const ParticleTypeList & list_all()
 
std::size_t find_offset(PdgCode pdg)
Passes back the address offset of a particletype in the list of all particles.
 
static int min_angular_momentum(int s0, int s1, int s2)
 
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...
 
build_vector_< Line > line_parser(const std::string &input)
Helper function for parsing particles.txt and decaymodes.txt.
 
std::string trim(const std::string &s)
Strip leading and trailing whitespaces.
 
Parity
Represent the parity of a particle type.
 
std::vector< DecayTypePtr > * all_decay_types
Global pointer to the decay types list.
 
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 ...