diff --git a/include/openmc/reaction.h b/include/openmc/reaction.h index dd6de245f..2bf6d6e96 100644 --- a/include/openmc/reaction.h +++ b/include/openmc/reaction.h @@ -44,8 +44,18 @@ public: // Non-member functions //============================================================================== +//! Return reaction name given an ENDF MT value +// +//! \param[in] mt ENDF MT value +//! \return Name of the corresponding reaction std::string reaction_name(int mt); +//! Return reaction type (MT value) given a reaction name +// +//! \param[in] name Reaction name +//! \return Corresponding reaction type (MT value) +int reaction_type(std::string name); + } // namespace openmc #endif // OPENMC_REACTION_H diff --git a/src/reaction.cpp b/src/reaction.cpp index 3b80aa10d..1543517e8 100644 --- a/src/reaction.cpp +++ b/src/reaction.cpp @@ -87,7 +87,7 @@ Reaction::Reaction(hid_t group, const std::vector& temperatures) // Non-member functions //============================================================================== -const std::unordered_map REACTION_NAME_MAP { +std::unordered_map REACTION_NAME_MAP { {SCORE_FLUX, "flux"}, {SCORE_TOTAL, "total"}, {SCORE_SCATTER, "scatter"}, @@ -150,6 +150,55 @@ const std::unordered_map REACTION_NAME_MAP { {N_PD, "(n,pd)"}, {N_PT, "(n,pt)"}, {N_DA, "(n,da)"}, + {N_5N, "(n,5n)"}, + {N_6N, "(n,6n)"}, + {N_2NT, "(n,2nt)"}, + {N_TA, "(n,ta)"}, + {N_4NP, "(n,4np)"}, + {N_3ND, "(n,3nd)"}, + {N_NDA, "(n,nda)"}, + {N_2NPA, "(n,2npa)"}, + {N_7N, "(n,7n)"}, + {N_8N, "(n,8n)"}, + {N_5NP, "(n,5np)"}, + {N_6NP, "(n,6np)"}, + {N_7NP, "(n,7np)"}, + {N_4NA, "(n,4na)"}, + {N_5NA, "(n,5na)"}, + {N_6NA, "(n,6na)"}, + {N_7NA, "(n,7na)"}, + {N_4ND, "(n,4nd)"}, + {N_5ND, "(n,5nd)"}, + {N_6ND, "(n,6nd)"}, + {N_3NT, "(n,3nt)"}, + {N_4NT, "(n,4nt)"}, + {N_5NT, "(n,5nt)"}, + {N_6NT, "(n,6nt)"}, + {N_2N3HE, "(n,2n3He)"}, + {N_3N3HE, "(n,3n3He)"}, + {N_4N3HE, "(n,4n3He)"}, + {N_3N2P, "(n,3n2p)"}, + {N_3N3A, "(n,3n3a)"}, + {N_3NPA, "(n,3npa)"}, + {N_DT, "(n,dt)"}, + {N_NPD, "(n,npd)"}, + {N_NPT, "(n,npt)"}, + {N_NDT, "(n,ndt)"}, + {N_NP3HE, "(n,np3He)"}, + {N_ND3HE, "(n,nd3He)"}, + {N_NT3HE, "(n,nt3He)"}, + {N_NTA, "(n,nta)"}, + {N_2N2P, "(n,2n2p)"}, + {N_P3HE, "(n,p3He)"}, + {N_D3HE, "(n,d3He)"}, + {N_3HEA, "(n,3Hea)"}, + {N_4N2P, "(n,4n2p)"}, + {N_4N2A, "(n,4n2a)"}, + {N_4NPA, "(n,4npa)"}, + {N_3P, "(n,3p)"}, + {N_N3P, "(n,n3p)"}, + {N_3N2PA, "(n,3n2pa)"}, + {N_5N2P, "(n,5n2p)"}, {201, "(n,Xn)"}, {202, "(n,Xgamma)"}, {N_XP, "(n,Xp)"}, @@ -174,32 +223,98 @@ const std::unordered_map REACTION_NAME_MAP { {HEATING_LOCAL, "heating-local"}, }; -std::string reaction_name(int mt) +std::unordered_map REACTION_TYPE_MAP; + +void initialize_maps() { - if (N_N1 <= mt && mt <= N_N40) { - return fmt::format("(n,n{})", mt - 50); - } else if (534 <= mt && mt <= 572) { - return fmt::format("photoelectric, {} subshell", SUBSHELLS[mt - 534]); - } else if (N_P0 <= mt && mt < N_PC) { - return fmt::format("(n,p{})", mt - N_P0); - } else if (N_D0 <= mt && mt < N_DC) { - return fmt::format("(n,d{})", mt - N_D0); - } else if (N_T0 <= mt && mt < N_TC) { - return fmt::format("(n,t{})", mt - N_T0); - } else if (N_3HE0 <= mt && mt < N_3HEC) { - return fmt::format("(n,3He{})", mt - N_3HE0); - } else if (N_A0 <= mt && mt < N_AC) { - return fmt::format("(n,a{})", mt - N_A0); - } else if (N_2N0 <= mt && mt < N_2NC) { - return fmt::format("(n,2n{})", mt - N_2N0); - } else { - auto it = REACTION_NAME_MAP.find(mt); - if (it != REACTION_NAME_MAP.end()) { - return it->second; - } else { - return fmt::format("MT={}", mt); + // Add level reactions to name map + for (int level = 0; level <= 48; ++level) { + if (level >= 1 && level <= 40) { + REACTION_NAME_MAP[50 + level] = fmt::format("(n,n{})", level); } + REACTION_NAME_MAP[600 + level] = fmt::format("(n,p{})", level); + REACTION_NAME_MAP[650 + level] = fmt::format("(n,d{})", level); + REACTION_NAME_MAP[700 + level] = fmt::format("(n,t{})", level); + REACTION_NAME_MAP[750 + level] = fmt::format("(n,3He{})", level); + REACTION_NAME_MAP[800 + level] = fmt::format("(n,a{})", level); + if (level <= 15) { + REACTION_NAME_MAP[875 + level] = fmt::format("(n,a{})", level); + } + } + + // Create photoelectric subshells + for (int mt = 534; mt <= 572; ++mt) { + REACTION_NAME_MAP[mt] = fmt::format("photoelectric, {} subshell", + SUBSHELLS[mt - 534]); + } + + // Invert name map to create type map + for (const auto& kv : REACTION_NAME_MAP) { + REACTION_TYPE_MAP[kv.second] = kv.first; } } +std::string reaction_name(int mt) +{ + // Initialize remainder of name map and all of type map + if (REACTION_TYPE_MAP.empty()) initialize_maps(); + + // Get reaction name from map + auto it = REACTION_NAME_MAP.find(mt); + if (it != REACTION_NAME_MAP.end()) { + return it->second; + } else { + return fmt::format("MT={}", mt); + } +} + +int reaction_type(std::string name) +{ + // Initialize remainder of name map and all of type map + if (REACTION_TYPE_MAP.empty()) initialize_maps(); + + // Check if type map has an entry for this reaction name + auto it = REACTION_TYPE_MAP.find(name); + if (it != REACTION_TYPE_MAP.end()) { + return it->second; + } + + // Alternate names for several reactions + if (name == "(n,total)") { + return SCORE_TOTAL; + } else if (name == "elastic") { + return ELASTIC; + } else if (name == "n2n") { + return N_2N; + } else if (name == "n3n") { + return N_3N; + } else if (name == "n4n") { + return N_4N; + } else if (name == "H1-production") { + return N_XP; + } else if (name == "H2-production") { + return N_XD; + } else if (name == "H3-production") { + return N_XT; + } else if (name == "He3-production") { + return N_X3HE; + } else if (name == "He4-production") { + return N_XA; + } + + // Assume the given string is a reaction MT number. Make sure it's a natural + // number then return. + int MT = 0; + try { + MT = std::stoi(name); + } catch (const std::invalid_argument& ex) { + throw std::invalid_argument("Invalid tally score \"" + name + "\". See the docs " + "for details: https://docs.openmc.org/en/stable/usersguide/tallies.html#scores"); + } + if (MT < 1) + throw std::invalid_argument("Invalid tally score \"" + name + "\". See the docs " + "for details: https://docs.openmc.org/en/stable/usersguide/tallies.html#scores"); + return MT; +} + } // namespace openmc diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 5619c669c..0131592f8 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -65,190 +65,6 @@ double global_tally_collision; double global_tally_tracklength; double global_tally_leakage; -int -score_str_to_int(std::string score_str) -{ - if (score_str == "flux") - return SCORE_FLUX; - - if (score_str == "total" || score_str == "(n,total)") - return SCORE_TOTAL; - - if (score_str == "scatter") - return SCORE_SCATTER; - - if (score_str == "nu-scatter") - return SCORE_NU_SCATTER; - - if (score_str == "absorption") - return SCORE_ABSORPTION; - - if (score_str == "fission" || score_str == "18") - return SCORE_FISSION; - - if (score_str == "nu-fission") - return SCORE_NU_FISSION; - - if (score_str == "decay-rate") - return SCORE_DECAY_RATE; - - if (score_str == "delayed-nu-fission") - return SCORE_DELAYED_NU_FISSION; - - if (score_str == "prompt-nu-fission") - return SCORE_PROMPT_NU_FISSION; - - if (score_str == "kappa-fission") - return SCORE_KAPPA_FISSION; - - if (score_str == "inverse-velocity") - return SCORE_INVERSE_VELOCITY; - - if (score_str == "fission-q-prompt") - return SCORE_FISS_Q_PROMPT; - - if (score_str == "fission-q-recoverable") - return SCORE_FISS_Q_RECOV; - - if (score_str == "heating") - return HEATING; - - if (score_str == "heating-local") - return HEATING_LOCAL; - - if (score_str == "current") - return SCORE_CURRENT; - - if (score_str == "events") - return SCORE_EVENTS; - - if (score_str == "elastic" || score_str == "(n,elastic)") - return ELASTIC; - - if (score_str == "n2n" || score_str == "(n,2n)") - return N_2N; - - if (score_str == "n3n" || score_str == "(n,3n)") - return N_3N; - - if (score_str == "n4n" || score_str == "(n,4n)") - return N_4N; - - if (score_str == "(n,2nd)") - return N_2ND; - if (score_str == "(n,na)") - return N_2NA; - if (score_str == "(n,n3a)") - return N_N3A; - if (score_str == "(n,2na)") - return N_2NA; - if (score_str == "(n,3na)") - return N_3NA; - if (score_str == "(n,np)") - return N_NP; - if (score_str == "(n,n2a)") - return N_N2A; - if (score_str == "(n,2n2a)") - return N_2N2A; - if (score_str == "(n,nd)") - return N_ND; - if (score_str == "(n,nt)") - return N_NT; - if (score_str == "(n,n3He)") - return N_N3HE; - if (score_str == "(n,nd2a)") - return N_ND2A; - if (score_str == "(n,nt2a)") - return N_NT2A; - if (score_str == "(n,3nf)") - return N_3NF; - if (score_str == "(n,2np)") - return N_2NP; - if (score_str == "(n,3np)") - return N_3NP; - if (score_str == "(n,n2p)") - return N_N2P; - if (score_str == "(n,npa)") - return N_NPA; - if (score_str == "(n,n1)") - return N_N1; - if (score_str == "(n,nc)") - return N_NC; - if (score_str == "(n,gamma)") - return N_GAMMA; - if (score_str == "(n,p)") - return N_P; - if (score_str == "(n,d)") - return N_D; - if (score_str == "(n,t)") - return N_T; - if (score_str == "(n,3He)") - return N_3HE; - if (score_str == "(n,a)") - return N_A; - if (score_str == "(n,2a)") - return N_2A; - if (score_str == "(n,3a)") - return N_3A; - if (score_str == "(n,2p)") - return N_2P; - if (score_str == "(n,pa)") - return N_PA; - if (score_str == "(n,t2a)") - return N_T2A; - if (score_str == "(n,d2a)") - return N_D2A; - if (score_str == "(n,pd)") - return N_PD; - if (score_str == "(n,pt)") - return N_PT; - if (score_str == "(n,da)") - return N_DA; - if (score_str == "(n,Xp)" || score_str == "H1-production") - return N_XP; - if (score_str == "(n,Xd)" || score_str == "H2-production") - return N_XD; - if (score_str == "(n,Xt)" || score_str == "H3-production") - return N_XT; - if (score_str == "(n,X3He)" || score_str == "He3-production") - return N_X3HE; - if (score_str == "(n,Xa)" || score_str == "He4-production") - return N_XA; - if (score_str == "damage-energy") - return DAMAGE_ENERGY; - if (score_str == "coherent-scatter") - return COHERENT; - if (score_str == "incoherent-scatter") - return INCOHERENT; - if (score_str == "pair-production") - return PAIR_PROD; - if (score_str == "photoelectric") - return PHOTOELECTRIC; - - // So far we have not identified this score string. Check to see if it is a - // deprecated score. - if (score_str.rfind("scatter-", 0) == 0 - || score_str.rfind("nu-scatter-", 0) == 0 - || score_str.rfind("total-y", 0) == 0 - || score_str.rfind("flux-y", 0) == 0) - fatal_error(score_str + " is no longer an available score"); - - - // Assume the given string is a reaction MT number. Make sure it's a natural - // number then return. - int MT; - try { - MT = std::stoi(score_str); - } catch (const std::invalid_argument& ex) { - throw std::invalid_argument("Invalid tally score \"" + score_str + "\". See the docs " - "for details: https://docs.openmc.org/en/stable/usersguide/tallies.html#scores"); - } - if (MT < 1) - throw std::invalid_argument("Invalid tally score \"" + score_str + "\". See the docs " - "for details: https://docs.openmc.org/en/stable/usersguide/tallies.html#scores"); - return MT; -} - //============================================================================== // Tally object implementation //============================================================================== @@ -594,7 +410,8 @@ Tally::set_scores(const std::vector& scores) fatal_error("Cannot tally " + score_str + "with a delayedgroup filter"); } - auto score = score_str_to_int(score_str); + // Determine integer code for score + int score = reaction_type(score_str); switch (score) { case SCORE_FLUX: