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

openmc-dev / openmc / 18299973882

07 Oct 2025 02:14AM UTC coverage: 81.92% (-3.3%) from 85.194%
18299973882

push

github

web-flow
Switch to using coveralls github action for reporting (#3594)

16586 of 23090 branches covered (71.83%)

Branch coverage included in aggregate %.

53703 of 62712 relevant lines covered (85.63%)

43428488.21 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)
60,419,111✔
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) {
60,419,111!
29
  case 1:
11,306,100✔
30
  case 11:
31
  case 21:
32
    return Interpolation::histogram;
11,306,100✔
33
  case 2:
49,109,777✔
34
  case 12:
35
  case 22:
36
    return Interpolation::lin_lin;
49,109,777✔
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,234✔
46
  case 15:
47
  case 25:
48
    return Interpolation::log_log;
3,234✔
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,250,470✔
61
{
62
  if (mt >= N_DISAPPEAR && mt <= N_DA) {
1,250,470✔
63
    return true;
176,022✔
64
  } else if (mt >= N_P0 && mt <= N_AC) {
1,074,448!
65
    return true;
355,471✔
66
  } else if (mt == N_TA || mt == N_DT || mt == N_P3HE || mt == N_D3HE ||
718,977!
67
             mt == N_3HEA || mt == N_3P) {
718,977!
68
    return true;
×
69
  } else {
70
    return false;
718,977✔
71
  }
72
}
73

74
bool is_inelastic_scatter(int mt)
1,326,161✔
75
{
76
  if (mt < 100) {
1,326,161✔
77
    if (is_fission(mt)) {
737,022✔
78
      return false;
15,176✔
79
    } else {
80
      return mt >= MISC && mt != 27;
721,846!
81
    }
82
  } else if (mt <= 200) {
589,139✔
83
    return !is_disappearance(mt);
101,895✔
84
  } else if (mt >= N_2N0 && mt <= N_2NC) {
487,244!
85
    return true;
×
86
  } else {
87
    return false;
487,244✔
88
  }
89
}
90

91
unique_ptr<Function1D> read_function(hid_t group, const char* name)
3,491,798✔
92
{
93
  hid_t obj_id = open_object(group, name);
3,491,798✔
94
  std::string func_type;
3,491,798✔
95
  read_attribute(obj_id, "type", func_type);
3,491,798✔
96
  unique_ptr<Function1D> func;
3,491,798✔
97
  if (func_type == "Tabulated1D") {
3,491,798✔
98
    func = make_unique<Tabulated1D>(obj_id);
2,754,525✔
99
  } else if (func_type == "Polynomial") {
737,273✔
100
    func = make_unique<Polynomial>(obj_id);
737,089✔
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,491,798✔
112
  return func;
6,983,596✔
113
}
3,491,798✔
114

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

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

125
double Polynomial::operator()(double x) const
1,291,709,713✔
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,291,709,713✔
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,291,709,713✔
134
}
135

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

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

145
  // Change 1-indexing to 0-indexing
146
  for (auto& b : nbt_)
5,533,885✔
147
    --b;
2,768,241✔
148

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

152
  // Convert vector of ints into Interpolation
153
  for (const auto i : int_temp)
5,533,885✔
154
    int_.push_back(int2interp(i));
2,768,241✔
155

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

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

162
  std::copy(xs.begin(), xs.end(), std::back_inserter(x_));
2,765,644✔
163
  std::copy(ys.begin(), ys.end(), std::back_inserter(y_));
2,765,644✔
164
  n_pairs_ = x_.size();
2,765,644✔
165
}
2,765,644✔
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,850,481,765✔
175
  } else if (x > x_[n_pairs_ - 1]) {
2,147,483,647✔
176
    return y_[n_pairs_ - 1];
40,559,735✔
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,416,750✔
218
    r = log(x / x0) / log(x1 / x0);
21,416,750✔
219
    return y0 * exp(r * log(y1 / y0));
21,416,750✔
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];
×
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