31 ParticleTypePtrList particle_types) {
35 if (type == &mode->type()) {
36 mode->set_weight(mode->weight() + ratio);
41 decay_modes_.push_back(make_unique<DecayBranch>(*type, ratio));
45 ParticleTypePtrList particle_types,
51 if (type->has_mother(mother) && type->has_particles(particle_types) &&
52 type->angular_momentum() == L) {
58 switch (particle_types.size()) {
61 particle_types[1]->pdgcode())) {
63 make_unique<TwoBodyDecayDilepton>(particle_types, L));
64 }
else if (particle_types[0]->is_stable() &&
65 particle_types[1]->is_stable()) {
67 make_unique<TwoBodyDecayStable>(particle_types, L));
68 }
else if (particle_types[0]->is_stable() ||
69 particle_types[1]->is_stable()) {
71 make_unique<TwoBodyDecaySemistable>(particle_types, L));
74 make_unique<TwoBodyDecayUnstable>(particle_types, L));
79 particle_types[1]->pdgcode(),
80 particle_types[2]->pdgcode())) {
82 make_unique<ThreeBodyDecayDilepton>(mother, particle_types, L));
85 make_unique<ThreeBodyDecay>(particle_types, L));
90 "DecayModes::get_decay_type was instructed to add a decay mode "
92 std::to_string(particle_types.size()) +
93 " particles. This is an invalid input.");
101 bool is_large_renormalization =
false;
103 sum += mode->weight();
107 ": Extremely small renormalization constant: ", sum,
108 "\n=> Skipping the renormalization.");
110 is_large_renormalization = (std::abs(sum - 1.) > 0.01);
112 ": Renormalizing decay modes with ", sum);
113 double new_sum = 0.0;
115 mode->set_weight(mode->weight() / sum);
116 new_sum += mode->weight();
118 logg[
LDecayModes].debug(
"After renormalization sum of ratios is ", new_sum);
120 return is_large_renormalization;
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");
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");
167 static std::vector<DecayTypePtr> decaytypes;
173 static std::vector<DecayModes> decaymodes;
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()) {
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]);
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();
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);
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();
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()) {
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();
328 " decay mode is forbidden by isospin: \"" +
329 line.text +
"\"" + s.str());
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 :
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;
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);
426 " decay mode violates charge conservation " +
427 "(line " + std::to_string(linenumber) +
": \"" +
436 if (parity != mother_states[0]->parity()) {
438 " decay mode violates parity conservation " +
439 "(line " + std::to_string(linenumber) +
": \"" +
443 if (L < min_L || L > max_L) {
445 mother_states[0]->name() +
446 " decay mode violates angular momentum conservation: " +
447 std::to_string(L) +
" not in [" + std::to_string(min_L) +
", " +
448 std::to_string(max_L) +
"] (line " + std::to_string(linenumber) +
449 ": \"" + trimmed +
"\")");
459 for (
const auto &mother : particles) {
460 if (mother.is_stable()) {
463 const auto &decays = mother.decay_modes().decay_mode_list();
464 for (
const auto &decay : decays) {
465 if (mother.mass() <= decay->threshold()) {
467 s << mother.name() <<
" → ";
468 for (
const auto p : decay->particle_types()) {
471 s <<
" with " << mother.mass() <<
" ≤ " << decay->threshold();
473 "For all decays, the minimum mass of daughters"
474 "must be smaller\nthan the mother's pole mass "
475 "(Manley-Saleski Ansatz)\n"
476 "Violated by the following decay: " +
481 if (total_large_renormalized > 0) {
483 "Branching ratios of ", total_large_renormalized,
484 " hadrons were renormalized by more than 1% to have sum 1.");