//! \file chain.cpp //! \brief Depletion chain and associated information #include "openmc/chain.h" #include // for getenv #include // for make_unique #include // for stod #include #include #include "openmc/distribution.h" // for distribution_from_xml #include "openmc/error.h" #include "openmc/reaction.h" #include "openmc/xml_interface.h" // for get_node_value namespace openmc { //============================================================================== // ChainNuclide implementation //============================================================================== ChainNuclide::ChainNuclide(pugi::xml_node node) { name_ = get_node_value(node, "name"); if (check_for_node(node, "half_life")) { half_life_ = std::stod(get_node_value(node, "half_life")); } if (check_for_node(node, "decay_energy")) { decay_energy_ = std::stod(get_node_value(node, "decay_energy")); } // Read reactions to store MT -> product map for (pugi::xml_node reaction_node : node.children("reaction")) { std::string rx_name = get_node_value(reaction_node, "type"); if (!reaction_node.attribute("target")) continue; std::string rx_target = get_node_value(reaction_node, "target"); double branching_ratio = 1.0; if (reaction_node.attribute("branching_ratio")) { branching_ratio = std::stod(get_node_value(reaction_node, "branching_ratio")); } int mt = reaction_mt(rx_name); reaction_products_[mt].push_back({rx_target, branching_ratio}); } for (pugi::xml_node source_node : node.children("source")) { auto particle = get_node_value(source_node, "particle"); if (particle == "photon") { photon_energy_ = distribution_from_xml(source_node); break; } } // Set entry in mapping data::chain_nuclide_map[name_] = data::chain_nuclides.size(); } ChainNuclide::~ChainNuclide() { data::chain_nuclide_map.erase(name_); } //============================================================================== // DecayPhotonAngleEnergy implementation //============================================================================== void DecayPhotonAngleEnergy::sample( double E_in, double& E_out, double& mu, uint64_t* seed) const { E_out = photon_energy_->sample(seed).first; mu = Uniform(-1., 1.).sample(seed).first; } double DecayPhotonAngleEnergy::sample_energy_and_pdf( double E_in, double mu, double& E_out, uint64_t* seed) const { E_out = photon_energy_->sample(seed).first; return 0.5; } //============================================================================== // Global variables //============================================================================== namespace data { std::unordered_map chain_nuclide_map; vector> chain_nuclides; } // namespace data //============================================================================== // Non-member functions //============================================================================== void read_chain_file_xml() { free_memory_chain(); char* chain_file_path = std::getenv("OPENMC_CHAIN_FILE"); if (!chain_file_path) { return; } write_message(5, "Reading chain file: {}...", chain_file_path); pugi::xml_document doc; auto result = doc.load_file(chain_file_path); if (!result) { fatal_error( fmt::format("Error processing chain file: {}", chain_file_path)); } // Get root element pugi::xml_node root = doc.document_element(); for (auto node : root.children("nuclide")) { data::chain_nuclides.push_back(std::make_unique(node)); } } void free_memory_chain() { data::chain_nuclides.clear(); data::chain_nuclide_map.clear(); } } // namespace openmc