• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openmc-dev / openmc / 25631610076

10 May 2026 02:44PM UTC coverage: 81.026% (-0.4%) from 81.388%
25631610076

Pull #3757

github

web-flow
Merge debc5a921 into d56cda254
Pull Request #3757: Testing point detectors

17769 of 25812 branches covered (68.84%)

Branch coverage included in aggregate %.

51 of 373 new or added lines in 25 files covered. (13.67%)

3 existing lines in 2 files now uncovered.

58805 of 68694 relevant lines covered (85.6%)

40257430.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.43
/src/chain.cpp
1
//! \file chain.cpp
2
//! \brief Depletion chain and associated information
3

4
#include "openmc/chain.h"
5

6
#include <cstdlib> // for getenv
7
#include <memory>  // for make_unique
8
#include <string>  // for stod
9

10
#include <fmt/core.h>
11
#include <pugixml.hpp>
12

13
#include "openmc/distribution.h" // for distribution_from_xml
14
#include "openmc/error.h"
15
#include "openmc/reaction.h"
16
#include "openmc/xml_interface.h" // for get_node_value
17

18
namespace openmc {
19

20
//==============================================================================
21
// ChainNuclide implementation
22
//==============================================================================
23

24
ChainNuclide::ChainNuclide(pugi::xml_node node)
53,608✔
25
{
26
  name_ = get_node_value(node, "name");
53,608✔
27
  if (check_for_node(node, "half_life")) {
53,608✔
28
    half_life_ = std::stod(get_node_value(node, "half_life"));
25,376✔
29
  }
30
  if (check_for_node(node, "decay_energy")) {
53,608✔
31
    decay_energy_ = std::stod(get_node_value(node, "decay_energy"));
25,344✔
32
  }
33

34
  // Read reactions to store MT -> product map
35
  for (pugi::xml_node reaction_node : node.children("reaction")) {
141,272✔
36
    std::string rx_name = get_node_value(reaction_node, "type");
43,832✔
37
    if (!reaction_node.attribute("target"))
43,832✔
38
      continue;
18,280✔
39
    std::string rx_target = get_node_value(reaction_node, "target");
25,552✔
40
    double branching_ratio = 1.0;
25,552✔
41
    if (reaction_node.attribute("branching_ratio")) {
25,552!
42
      branching_ratio =
×
43
        std::stod(get_node_value(reaction_node, "branching_ratio"));
×
44
    }
45
    int mt = reaction_mt(rx_name);
25,552✔
46
    reaction_products_[mt].push_back({rx_target, branching_ratio});
25,552✔
47
  }
43,832✔
48

49
  for (pugi::xml_node source_node : node.children("source")) {
53,920✔
50
    auto particle = get_node_value(source_node, "particle");
24,320✔
51
    if (particle == "photon") {
24,320✔
52
      photon_energy_ = distribution_from_xml(source_node);
24,008✔
53
      break;
24,008✔
54
    }
55
  }
24,320✔
56

57
  // Set entry in mapping
58
  data::chain_nuclide_map[name_] = data::chain_nuclides.size();
53,608✔
59
}
53,608✔
60

61
ChainNuclide::~ChainNuclide()
53,608✔
62
{
63
  data::chain_nuclide_map.erase(name_);
53,608✔
64
}
107,216✔
65

66
//==============================================================================
67
// DecayPhotonAngleEnergy implementation
68
//==============================================================================
69

70
void DecayPhotonAngleEnergy::sample(
39,800✔
71
  double E_in, double& E_out, double& mu, uint64_t* seed) const
72
{
73
  E_out = photon_energy_->sample(seed).first;
39,800✔
74
  mu = Uniform(-1., 1.).sample(seed).first;
39,800✔
75
}
39,800✔
76

NEW
77
double DecayPhotonAngleEnergy::sample_energy_and_pdf(double E_in, double mu,
×
78
  double& E_out, uint64_t* seed, bool is_com, double awr) const
79
{
NEW
80
  if (is_com)
×
NEW
81
    fatal_error(
×
82
      "DecayPhotonAngleEnergy distribution must be in lab coordinates");
83

84
  E_out = photon_energy_->sample(seed).first;
×
85
  return 0.5;
×
86
}
87

88
//==============================================================================
89
// Global variables
90
//==============================================================================
91

92
namespace data {
93

94
std::unordered_map<std::string, int> chain_nuclide_map;
95
vector<unique_ptr<ChainNuclide>> chain_nuclides;
96

97
} // namespace data
98

99
//==============================================================================
100
// Non-member functions
101
//==============================================================================
102

103
void read_chain_file_xml()
6,146✔
104
{
105
  free_memory_chain();
6,146✔
106

107
  char* chain_file_path = std::getenv("OPENMC_CHAIN_FILE");
6,146✔
108
  if (!chain_file_path) {
6,146✔
109
    return;
322✔
110
  }
111

112
  write_message(5, "Reading chain file: {}...", chain_file_path);
5,824✔
113

114
  pugi::xml_document doc;
5,824✔
115
  auto result = doc.load_file(chain_file_path);
5,824✔
116
  if (!result) {
5,824!
117
    fatal_error(
×
118
      fmt::format("Error processing chain file: {}", chain_file_path));
×
119
  }
120

121
  // Get root element
122
  pugi::xml_node root = doc.document_element();
5,824✔
123

124
  for (auto node : root.children("nuclide")) {
59,432✔
125
    data::chain_nuclides.push_back(std::make_unique<ChainNuclide>(node));
107,216✔
126
  }
127
}
5,824✔
128

129
void free_memory_chain()
12,350✔
130
{
131
  data::chain_nuclides.clear();
12,350✔
132
  data::chain_nuclide_map.clear();
12,350✔
133
}
12,350✔
134

135
} // namespace openmc
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc