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

openmc-dev / openmc / 18538152141

15 Oct 2025 06:02PM UTC coverage: 81.97% (-3.2%) from 85.194%
18538152141

Pull #3417

github

web-flow
Merge 4604e1321 into e9077b137
Pull Request #3417: Addition of a collision tracking feature

16794 of 23357 branches covered (71.9%)

Branch coverage included in aggregate %.

480 of 522 new or added lines in 13 files covered. (91.95%)

457 existing lines in 53 files now uncovered.

54128 of 63165 relevant lines covered (85.69%)

42776927.64 hits per line

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

76.9
/src/endf.cpp
1
#include "openmc/endf.h"
2

3
#include <algorithm> // for copy
4
#include <cmath>     // for log, exp
5
#include <iterator>  // for back_inserter
6
#include <stdexcept> // for runtime_error
7

8
#include "xtensor/xarray.hpp"
9
#include "xtensor/xview.hpp"
10

11
#include "openmc/array.h"
12
#include "openmc/constants.h"
13
#include "openmc/hdf5_interface.h"
14
#include "openmc/search.h"
15

16
namespace openmc {
17

18
//==============================================================================
19
// Functions
20
//==============================================================================
21

22
Interpolation int2interp(int i)
58,101,995✔
23
{
24
  // TODO: We are ignoring specification of two-dimensional interpolation
25
  // schemes (method of corresponding points and unit base interpolation). Those
26
  // should be accounted for in the distribution classes somehow.
27

28
  switch (i) {
58,101,995!
29
  case 1:
11,077,411✔
30
  case 11:
31
  case 21:
32
    return Interpolation::histogram;
11,077,411✔
33
  case 2:
47,020,991✔
34
  case 12:
35
  case 22:
36
    return Interpolation::lin_lin;
47,020,991✔
37
  case 3:
×
38
  case 13:
39
  case 23:
40
    return Interpolation::lin_log;
×
41
  case 4:
×
42
  case 14:
43
  case 24:
44
    return Interpolation::log_lin;
×
45
  case 5:
3,593✔
46
  case 15:
47
  case 25:
48
    return Interpolation::log_log;
3,593✔
49
  default:
×
50
    throw std::runtime_error {"Invalid interpolation code."};
×
51
  }
52
}
53

54
bool is_fission(int mt)
2,147,483,647✔
55
{
56
  return mt == N_FISSION || mt == N_F || mt == N_NF || mt == N_2NF ||
2,147,483,647✔
57
         mt == N_3NF;
2,147,483,647✔
58
}
59

60
bool is_disappearance(int mt)
1,217,370✔
61
{
62
  if (mt >= N_DISAPPEAR && mt <= N_DA) {
1,217,370✔
63
    return true;
169,547✔
64
  } else if (mt >= N_P0 && mt <= N_AC) {
1,047,823!
65
    return true;
343,991✔
66
  } else if (mt == N_TA || mt == N_DT || mt == N_P3HE || mt == N_D3HE ||
703,832!
67
             mt == N_3HEA || mt == N_3P) {
703,832!
68
    return true;
×
69
  } else {
70
    return false;
703,832✔
71
  }
72
}
73

74
bool is_inelastic_scatter(int mt)
1,291,479✔
75
{
76
  if (mt < 100) {
1,291,479✔
77
    if (is_fission(mt)) {
721,872✔
78
      return false;
15,784✔
79
    } else {
80
      return mt >= MISC && mt != 27;
706,088!
81
    }
82
  } else if (mt <= 200) {
569,607✔
83
    return !is_disappearance(mt);
98,262✔
84
  } else if (mt >= N_2N0 && mt <= N_2NC) {
471,345!
85
    return true;
×
86
  } else {
87
    return false;
471,345✔
88
  }
89
}
90

91
unique_ptr<Function1D> read_function(hid_t group, const char* name)
3,363,405✔
92
{
93
  hid_t obj_id = open_object(group, name);
3,363,405✔
94
  std::string func_type;
3,363,405✔
95
  read_attribute(obj_id, "type", func_type);
3,363,405✔
96
  unique_ptr<Function1D> func;
3,363,405✔
97
  if (func_type == "Tabulated1D") {
3,363,405✔
98
    func = make_unique<Tabulated1D>(obj_id);
2,641,506✔
99
  } else if (func_type == "Polynomial") {
721,899✔
100
    func = make_unique<Polynomial>(obj_id);
721,715✔
101
  } else if (func_type == "CoherentElastic") {
184✔
102
    func = make_unique<CoherentElasticXS>(obj_id);
140✔
103
  } else if (func_type == "IncoherentElastic") {
44!
104
    func = make_unique<IncoherentElasticXS>(obj_id);
×
105
  } else if (func_type == "Sum") {
44!
106
    func = make_unique<Sum1D>(obj_id);
44✔
107
  } else {
108
    throw std::runtime_error {"Unknown function type " + func_type +
×
109
                              " for dataset " + object_name(obj_id)};
×
110
  }
111
  close_object(obj_id);
3,363,405✔
112
  return func;
6,726,810✔
113
}
3,363,405✔
114

115
//==============================================================================
116
// Polynomial implementation
117
//==============================================================================
118

119
Polynomial::Polynomial(hid_t dset)
721,715✔
120
{
121
  // Read coefficients into a vector
122
  read_dataset(dset, coef_);
721,715✔
123
}
721,715✔
124

125
double Polynomial::operator()(double x) const
1,275,247,599✔
126
{
127
  // Use Horner's rule to evaluate polynomial. Note that coefficients are
128
  // ordered in increasing powers of x.
129
  double y = 0.0;
1,275,247,599✔
130
  for (auto c = coef_.crbegin(); c != coef_.crend(); ++c) {
2,147,483,647✔
131
    y = y * x + *c;
2,147,483,647✔
132
  }
133
  return y;
1,275,247,599✔
134
}
135

136
//==============================================================================
137
// Tabulated1D implementation
138
//==============================================================================
139

140
Tabulated1D::Tabulated1D(hid_t dset)
2,652,516✔
141
{
142
  read_attribute(dset, "breakpoints", nbt_);
2,652,516✔
143
  n_regions_ = nbt_.size();
2,652,516✔
144

145
  // Change 1-indexing to 0-indexing
146
  for (auto& b : nbt_)
5,307,567✔
147
    --b;
2,655,051✔
148

149
  vector<int> int_temp;
2,652,516✔
150
  read_attribute(dset, "interpolation", int_temp);
2,652,516✔
151

152
  // Convert vector of ints into Interpolation
153
  for (const auto i : int_temp)
5,307,567✔
154
    int_.push_back(int2interp(i));
2,655,051✔
155

156
  xt::xarray<double> arr;
2,652,516✔
157
  read_dataset(dset, arr);
2,652,516✔
158

159
  auto xs = xt::view(arr, 0);
2,652,516✔
160
  auto ys = xt::view(arr, 1);
2,652,516✔
161

162
  std::copy(xs.begin(), xs.end(), std::back_inserter(x_));
2,652,516✔
163
  std::copy(ys.begin(), ys.end(), std::back_inserter(y_));
2,652,516✔
164
  n_pairs_ = x_.size();
2,652,516✔
165
}
2,652,516✔
166

167
double Tabulated1D::operator()(double x) const
2,147,483,647✔
168
{
169
  // find which bin the abscissa is in -- if the abscissa is outside the
170
  // tabulated range, the first or last point is chosen, i.e. no interpolation
171
  // is done outside the energy range
172
  int i;
173
  if (x < x_[0]) {
2,147,483,647✔
174
    return y_[0];
1,830,780,448✔
175
  } else if (x > x_[n_pairs_ - 1]) {
2,147,483,647✔
176
    return y_[n_pairs_ - 1];
40,407,530✔
177
  } else {
178
    i = lower_bound_index(x_.begin(), x_.end(), x);
2,147,483,647✔
179
  }
180

181
  // determine interpolation scheme
182
  Interpolation interp;
183
  if (n_regions_ == 0) {
2,147,483,647!
184
    interp = Interpolation::lin_lin;
×
185
  } else {
186
    interp = int_[0];
2,147,483,647✔
187
    for (int j = 0; j < n_regions_; ++j) {
2,147,483,647!
188
      if (i < nbt_[j]) {
2,147,483,647✔
189
        interp = int_[j];
2,147,483,647✔
190
        break;
2,147,483,647✔
191
      }
192
    }
193
  }
194

195
  // handle special case of histogram interpolation
196
  if (interp == Interpolation::histogram)
2,147,483,647✔
197
    return y_[i];
2,147,483,647✔
198

199
  // determine bounding values
200
  double x0 = x_[i];
2,147,483,647✔
201
  double x1 = x_[i + 1];
2,147,483,647✔
202
  double y0 = y_[i];
2,147,483,647✔
203
  double y1 = y_[i + 1];
2,147,483,647✔
204

205
  // determine interpolation factor and interpolated value
206
  double r;
207
  switch (interp) {
2,147,483,647!
208
  case Interpolation::lin_lin:
2,147,483,647✔
209
    r = (x - x0) / (x1 - x0);
2,147,483,647✔
210
    return y0 + r * (y1 - y0);
2,147,483,647✔
211
  case Interpolation::lin_log:
×
212
    r = log(x / x0) / log(x1 / x0);
×
213
    return y0 + r * (y1 - y0);
×
214
  case Interpolation::log_lin:
×
215
    r = (x - x0) / (x1 - x0);
×
216
    return y0 * exp(r * log(y1 / y0));
×
217
  case Interpolation::log_log:
21,414,749✔
218
    r = log(x / x0) / log(x1 / x0);
21,414,749✔
219
    return y0 * exp(r * log(y1 / y0));
21,414,749✔
220
  default:
×
221
    throw std::runtime_error {"Invalid interpolation scheme."};
×
222
  }
223
}
224

225
//==============================================================================
226
// CoherentElasticXS implementation
227
//==============================================================================
228

229
CoherentElasticXS::CoherentElasticXS(hid_t dset)
140✔
230
{
231
  // Read 2D array from dataset
232
  xt::xarray<double> arr;
140✔
233
  read_dataset(dset, arr);
140✔
234

235
  // Get views for Bragg edges and structure factors
236
  auto E = xt::view(arr, 0);
140✔
237
  auto s = xt::view(arr, 1);
140✔
238

239
  // Copy Bragg edges and partial sums of structure factors
240
  std::copy(E.begin(), E.end(), std::back_inserter(bragg_edges_));
140✔
241
  std::copy(s.begin(), s.end(), std::back_inserter(factors_));
140✔
242
}
140✔
243

244
double CoherentElasticXS::operator()(double E) const
4,939,957✔
245
{
246
  if (E < bragg_edges_[0]) {
4,939,957✔
247
    // If energy is below that of the lowest Bragg peak, the elastic cross
248
    // section will be zero
249
    return 0.0;
3,102✔
250
  } else {
251
    auto i_grid =
252
      lower_bound_index(bragg_edges_.begin(), bragg_edges_.end(), E);
4,936,855✔
253
    return factors_[i_grid] / E;
4,936,855✔
254
  }
255
}
256

257
//==============================================================================
258
// IncoherentElasticXS implementation
259
//==============================================================================
260

261
IncoherentElasticXS::IncoherentElasticXS(hid_t dset)
×
262
{
263
  array<double, 2> tmp;
264
  read_dataset(dset, nullptr, tmp);
×
265
  bound_xs_ = tmp[0];
×
266
  debye_waller_ = tmp[1];
×
UNCOV
267
}
×
268

269
double IncoherentElasticXS::operator()(double E) const
×
270
{
271
  // Determine cross section using ENDF-102, Eq. (7.5)
272
  double W = debye_waller_;
×
273
  return bound_xs_ / 2.0 * ((1 - std::exp(-4.0 * E * W)) / (2.0 * E * W));
×
274
}
275

276
//==============================================================================
277
// Sum1D implementation
278
//==============================================================================
279

280
Sum1D::Sum1D(hid_t group)
44✔
281
{
282
  // Get number of functions
283
  int n;
284
  read_attribute(group, "n", n);
44✔
285

286
  // Get each function
287
  for (int i = 0; i < n; ++i) {
132✔
288
    auto dset_name = fmt::format("func_{}", i + 1);
160✔
289
    functions_.push_back(read_function(group, dset_name.c_str()));
88✔
290
  }
88✔
291
}
44✔
292

293
double Sum1D::operator()(double x) const
4,049,320✔
294
{
295
  double result = 0.0;
4,049,320✔
296
  for (auto& func : functions_) {
12,147,960✔
297
    result += (*func)(x);
8,098,640✔
298
  }
299
  return result;
4,049,320✔
300
}
301

302
} // 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

© 2025 Coveralls, Inc