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

openmc-dev / openmc / 13114782272

03 Feb 2025 01:38PM UTC coverage: 82.603% (-2.3%) from 84.867%
13114782272

Pull #3087

github

web-flow
Merge 258841139 into 59c398be8
Pull Request #3087: wheel building with scikit build core

107121 of 129682 relevant lines covered (82.6%)

12608592.69 hits per line

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

47.58
/src/tallies/filter_energyfunc.cpp
1
#include "openmc/tallies/filter_energyfunc.h"
2

3
#include <fmt/core.h>
4

5
#include "openmc/error.h"
6
#include "openmc/interpolate.h"
7
#include "openmc/search.h"
8
#include "openmc/settings.h"
9
#include "openmc/xml_interface.h"
10

11
namespace openmc {
12

13
void EnergyFunctionFilter::from_xml(pugi::xml_node node)
136✔
14
{
15
  if (!settings::run_CE)
136✔
16
    fatal_error("EnergyFunction filters are only supported for "
×
17
                "continuous-energy transport calculations");
18

19
  if (!check_for_node(node, "energy"))
136✔
20
    fatal_error("Energy grid not specified for EnergyFunction filter.");
×
21

22
  auto energy = get_node_array<double>(node, "energy");
136✔
23

24
  if (!check_for_node(node, "y"))
136✔
25
    fatal_error("y values not specified for EnergyFunction filter.");
×
26

27
  auto y = get_node_array<double>(node, "y");
136✔
28
  this->set_data(energy, y);
136✔
29

30
  // default to linear-linear interpolation
31
  interpolation_ = Interpolation::lin_lin;
136✔
32
  if (check_for_node(node, "interpolation")) {
136✔
33
    std::string interpolation = get_node_value(node, "interpolation");
136✔
34
    this->set_interpolation(interpolation);
136✔
35
  }
136✔
36
}
136✔
37

38
void EnergyFunctionFilter::set_data(
136✔
39
  gsl::span<const double> energy, gsl::span<const double> y)
40
{
41
  // Check for consistent sizes with new data
42
  if (energy.size() != y.size()) {
136✔
43
    fatal_error("Energy grid and y values are not consistent");
×
44
  }
45
  energy_.clear();
136✔
46
  energy_.reserve(energy.size());
136✔
47
  y_.clear();
136✔
48
  y_.reserve(y.size());
136✔
49

50
  // Copy over energy values, ensuring they are valid
51
  for (gsl::index i = 0; i < energy.size(); ++i) {
1,020✔
52
    if (i > 0 && energy[i] <= energy[i - 1]) {
884✔
53
      throw std::runtime_error {
×
54
        "Energy bins must be monotonically increasing."};
×
55
    }
56
    energy_.push_back(energy[i]);
884✔
57
    y_.push_back(y[i]);
884✔
58
  }
59
}
136✔
60

61
void EnergyFunctionFilter::set_interpolation(const std::string& interpolation)
136✔
62
{
63
  if (interpolation == "histogram") {
136✔
64
    interpolation_ = Interpolation::histogram;
17✔
65
  } else if (interpolation == "linear-linear") {
119✔
66
    interpolation_ = Interpolation::lin_lin;
34✔
67
  } else if (interpolation == "linear-log") {
85✔
68
    interpolation_ = Interpolation::lin_log;
17✔
69
  } else if (interpolation == "log-linear") {
68✔
70
    interpolation_ = Interpolation::log_lin;
17✔
71
  } else if (interpolation == "log-log") {
51✔
72
    interpolation_ = Interpolation::log_log;
17✔
73
  } else if (interpolation == "quadratic") {
34✔
74
    if (energy_.size() < 3)
17✔
75
      fatal_error(
×
76
        fmt::format("Quadratic interpolation on EnergyFunctionFilter {} "
×
77
                    "requires at least 3 data points.",
78
          this->id()));
×
79
    interpolation_ = Interpolation::quadratic;
17✔
80
  } else if (interpolation == "cubic") {
17✔
81
    if (energy_.size() < 4)
17✔
82
      fatal_error(fmt::format("Cubic interpolation on EnergyFunctionFilter "
×
83
                              "{} requires at least 4 data points.",
84
        this->id()));
×
85
    interpolation_ = Interpolation::cubic;
17✔
86
  } else {
87
    fatal_error(fmt::format(
×
88
      "Found invalid interpolation type '{}' on EnergyFunctionFilter {}.",
89
      interpolation, this->id()));
×
90
  }
91
}
136✔
92

93
void EnergyFunctionFilter::get_all_bins(
3,061,248✔
94
  const Particle& p, TallyEstimator estimator, FilterMatch& match) const
95
{
96
  if (p.E_last() >= energy_.front() && p.E_last() <= energy_.back()) {
3,061,248✔
97

98
    double w = interpolate(energy_, y_, p.E_last(), interpolation_);
3,061,248✔
99

100
    // Interpolate on the lin-lin grid.
101
    match.bins_.push_back(0);
3,061,248✔
102
    match.weights_.push_back(w);
3,061,248✔
103
  }
104
}
3,061,248✔
105

106
void EnergyFunctionFilter::to_statepoint(hid_t filter_group) const
96✔
107
{
108
  Filter::to_statepoint(filter_group);
96✔
109
  write_dataset(filter_group, "energy", energy_);
96✔
110
  write_dataset(filter_group, "y", y_);
96✔
111
  hid_t y_dataset = open_dataset(filter_group, "y");
96✔
112
  write_attribute<int>(
96✔
113
    y_dataset, "interpolation", static_cast<int>(interpolation_));
96✔
114
  close_dataset(y_dataset);
96✔
115
}
96✔
116

117
std::string EnergyFunctionFilter::text_label(int bin) const
96✔
118
{
119
  return fmt::format(
120
    "Energy Function f([{:.1e}, ..., {:.1e}]) = [{:.1e}, ..., {:.1e}]",
121
    energy_.front(), energy_.back(), y_.front(), y_.back());
192✔
122
}
123

124
//==============================================================================
125
// C-API functions
126
//==============================================================================
127

128
extern "C" int openmc_energyfunc_filter_set_data(
×
129
  int32_t index, size_t n, const double* energy, const double* y)
130
{
131
  // Ensure this is a valid index to allocated filter
132
  if (int err = verify_filter(index))
×
133
    return err;
×
134

135
  // Get a pointer to the filter
136
  const auto& filt_base = model::tally_filters[index].get();
×
137
  // Downcast to EnergyFunctionFilter
138
  auto* filt = dynamic_cast<EnergyFunctionFilter*>(filt_base);
×
139

140
  // Check if a valid filter was produced
141
  if (!filt) {
×
142
    set_errmsg(
×
143
      "Tried to set interpolation data for non-energy function filter.");
144
    return OPENMC_E_INVALID_TYPE;
×
145
  }
146

147
  filt->set_data({energy, n}, {y, n});
×
148
  return 0;
×
149
}
150

151
extern "C" int openmc_energyfunc_filter_get_energy(
×
152
  int32_t index, size_t* n, const double** energy)
153
{
154
  // ensure this is a valid index to allocated filter
155
  if (int err = verify_filter(index))
×
156
    return err;
×
157

158
  // get a pointer to the filter
159
  const auto& filt_base = model::tally_filters[index].get();
×
160
  // downcast to EnergyFunctionFilter
161
  auto* filt = dynamic_cast<EnergyFunctionFilter*>(filt_base);
×
162

163
  // check if a valid filter was produced
164
  if (!filt) {
×
165
    set_errmsg(
×
166
      "Tried to set interpolation data for non-energy function filter.");
167
    return OPENMC_E_INVALID_TYPE;
×
168
  }
169
  *energy = filt->energy().data();
×
170
  *n = filt->energy().size();
×
171
  return 0;
×
172
}
173

174
extern "C" int openmc_energyfunc_filter_get_y(
×
175
  int32_t index, size_t* n, const double** y)
176
{
177
  // ensure this is a valid index to allocated filter
178
  if (int err = verify_filter(index))
×
179
    return err;
×
180

181
  // get a pointer to the filter
182
  const auto& filt_base = model::tally_filters[index].get();
×
183
  // downcast to EnergyFunctionFilter
184
  auto* filt = dynamic_cast<EnergyFunctionFilter*>(filt_base);
×
185

186
  // check if a valid filter was produced
187
  if (!filt) {
×
188
    set_errmsg(
×
189
      "Tried to set interpolation data for non-energy function filter.");
190
    return OPENMC_E_INVALID_TYPE;
×
191
  }
192
  *y = filt->y().data();
×
193
  *n = filt->y().size();
×
194
  return 0;
×
195
}
196

197
extern "C" int openmc_energyfunc_filter_set_interpolation(
×
198
  int32_t index, const char* interp)
199
{
200
  // ensure this is a valid index to allocated filter
201
  if (int err = verify_filter(index))
×
202
    return err;
×
203

204
  // get a pointer to the filter
205
  const auto& filt_base = model::tally_filters[index].get();
×
206
  // downcast to EnergyFunctionFilter
207
  auto* filt = dynamic_cast<EnergyFunctionFilter*>(filt_base);
×
208

209
  // check if a valid filter was produced
210
  if (!filt) {
×
211
    set_errmsg(
×
212
      "Tried to set interpolation data for non-energy function filter.");
213
    return OPENMC_E_INVALID_TYPE;
×
214
  }
215

216
  // Set interpolation
217
  filt->set_interpolation(interp);
×
218
  return 0;
×
219
}
220

221
extern "C" int openmc_energyfunc_filter_get_interpolation(
×
222
  int32_t index, int* interp)
223
{
224
  // ensure this is a valid index to allocated filter
225
  if (int err = verify_filter(index))
×
226
    return err;
×
227

228
  // get a pointer to the filter
229
  const auto& filt_base = model::tally_filters[index].get();
×
230
  // downcast to EnergyFunctionFilter
231
  auto* filt = dynamic_cast<EnergyFunctionFilter*>(filt_base);
×
232

233
  // check if a valid filter was produced
234
  if (!filt) {
×
235
    set_errmsg(
×
236
      "Tried to set interpolation data for non-energy function filter.");
237
    return OPENMC_E_INVALID_TYPE;
×
238
  }
239

240
  *interp = static_cast<int>(filt->interpolation());
×
241
  return 0;
×
242
}
243

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