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

openmc-dev / openmc / 19058781736

04 Nov 2025 05:26AM UTC coverage: 82.008% (-3.1%) from 85.155%
19058781736

Pull #3252

github

web-flow
Merge b8a72730f into bd76fc056
Pull Request #3252: Adding vtkhdf option to write vtk data

16714 of 23236 branches covered (71.93%)

Branch coverage included in aggregate %.

61 of 66 new or added lines in 1 file covered. (92.42%)

3175 existing lines in 103 files now uncovered.

54243 of 63288 relevant lines covered (85.71%)

43393337.77 hits per line

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

79.92
/src/tallies/filter.cpp
1
#include "openmc/tallies/filter.h"
2

3
#include <algorithm> // for max
4
#include <cassert>
5
#include <cstring> // for strcpy
6
#include <string>
7

8
#include <fmt/core.h>
9

10
#include "openmc/capi.h"
11
#include "openmc/constants.h" // for MAX_LINE_LEN;
12
#include "openmc/error.h"
13
#include "openmc/tallies/filter_azimuthal.h"
14
#include "openmc/tallies/filter_cell.h"
15
#include "openmc/tallies/filter_cell_instance.h"
16
#include "openmc/tallies/filter_cellborn.h"
17
#include "openmc/tallies/filter_cellfrom.h"
18
#include "openmc/tallies/filter_collision.h"
19
#include "openmc/tallies/filter_delayedgroup.h"
20
#include "openmc/tallies/filter_distribcell.h"
21
#include "openmc/tallies/filter_energy.h"
22
#include "openmc/tallies/filter_energyfunc.h"
23
#include "openmc/tallies/filter_legendre.h"
24
#include "openmc/tallies/filter_material.h"
25
#include "openmc/tallies/filter_materialfrom.h"
26
#include "openmc/tallies/filter_mesh.h"
27
#include "openmc/tallies/filter_meshborn.h"
28
#include "openmc/tallies/filter_meshmaterial.h"
29
#include "openmc/tallies/filter_meshsurface.h"
30
#include "openmc/tallies/filter_mu.h"
31
#include "openmc/tallies/filter_musurface.h"
32
#include "openmc/tallies/filter_parent_nuclide.h"
33
#include "openmc/tallies/filter_particle.h"
34
#include "openmc/tallies/filter_polar.h"
35
#include "openmc/tallies/filter_sph_harm.h"
36
#include "openmc/tallies/filter_sptl_legendre.h"
37
#include "openmc/tallies/filter_surface.h"
38
#include "openmc/tallies/filter_time.h"
39
#include "openmc/tallies/filter_universe.h"
40
#include "openmc/tallies/filter_weight.h"
41
#include "openmc/tallies/filter_zernike.h"
42
#include "openmc/xml_interface.h"
43

44
// explicit template instantiation definition
45
template class openmc::vector<openmc::FilterMatch>;
46

47
namespace openmc {
48

49
//==============================================================================
50
// Global variables
51
//==============================================================================
52

53
namespace model {
54
std::unordered_map<int, int> filter_map;
55
vector<unique_ptr<Filter>> tally_filters;
56
} // namespace model
57

58
//==============================================================================
59
// Non-member functions
60
//==============================================================================
61

62
extern "C" size_t tally_filters_size()
1,973✔
63
{
64
  return model::tally_filters.size();
1,973✔
65
}
66

67
//==============================================================================
68
// Filter implementation
69
//==============================================================================
70

71
Filter::Filter()
10,497✔
72
{
73
  index_ = model::tally_filters.size(); // Avoids warning about narrowing
10,497✔
74
}
10,497✔
75

76
Filter::~Filter()
10,497✔
77
{
78
  model::filter_map.erase(id_);
10,497✔
79
}
10,497✔
80

81
Filter* Filter::create(pugi::xml_node node)
8,250✔
82
{
83
  // Copy filter id
84
  if (!check_for_node(node, "id")) {
8,250!
UNCOV
85
    fatal_error("Must specify id for filter in tally XML file.");
×
86
  }
87
  int filter_id = std::stoi(get_node_value(node, "id"));
8,250✔
88

89
  // Convert filter type to lower case
90
  std::string s;
8,250✔
91
  if (check_for_node(node, "type")) {
8,250!
92
    s = get_node_value(node, "type", true);
8,250✔
93
  }
94

95
  // Allocate according to the filter type
96
  auto f = Filter::create(s, filter_id);
8,250✔
97

98
  // Read filter data from XML
99
  f->from_xml(node);
8,250✔
100
  return f;
8,250✔
101
}
8,250✔
102

103
Filter* Filter::create(const std::string& type, int32_t id)
10,481✔
104
{
105
  if (type == "azimuthal") {
10,481✔
106
    return Filter::create<AzimuthalFilter>(id);
32✔
107
  } else if (type == "cell") {
10,449✔
108
    return Filter::create<CellFilter>(id);
801✔
109
  } else if (type == "cellborn") {
9,648✔
110
    return Filter::create<CellBornFilter>(id);
16✔
111
  } else if (type == "cellfrom") {
9,632✔
112
    return Filter::create<CellFromFilter>(id);
96✔
113
  } else if (type == "cellinstance") {
9,536✔
114
    return Filter::create<CellInstanceFilter>(id);
34✔
115
  } else if (type == "distribcell") {
9,502✔
116
    return Filter::create<DistribcellFilter>(id);
233✔
117
  } else if (type == "delayedgroup") {
9,269✔
118
    return Filter::create<DelayedGroupFilter>(id);
134✔
119
  } else if (type == "energyfunction") {
9,135✔
120
    return Filter::create<EnergyFunctionFilter>(id);
299✔
121
  } else if (type == "energy") {
8,836✔
122
    return Filter::create<EnergyFilter>(id);
1,643✔
123
  } else if (type == "collision") {
7,193✔
124
    return Filter::create<CollisionFilter>(id);
16✔
125
  } else if (type == "energyout") {
7,177✔
126
    return Filter::create<EnergyoutFilter>(id);
412✔
127
  } else if (type == "legendre") {
6,765✔
128
    return Filter::create<LegendreFilter>(id);
573✔
129
  } else if (type == "material") {
6,192✔
130
    return Filter::create<MaterialFilter>(id);
2,508✔
131
  } else if (type == "materialfrom") {
3,684✔
132
    return Filter::create<MaterialFromFilter>(id);
16✔
133
  } else if (type == "mesh") {
3,668✔
134
    return Filter::create<MeshFilter>(id);
2,312✔
135
  } else if (type == "meshborn") {
1,356✔
136
    return Filter::create<MeshBornFilter>(id);
27✔
137
  } else if (type == "meshmaterial") {
1,329✔
138
    return Filter::create<MeshMaterialFilter>(id);
22✔
139
  } else if (type == "meshsurface") {
1,307✔
140
    return Filter::create<MeshSurfaceFilter>(id);
411✔
141
  } else if (type == "mu") {
896✔
142
    return Filter::create<MuFilter>(id);
32✔
143
  } else if (type == "musurface") {
864✔
144
    return Filter::create<MuSurfaceFilter>(id);
27✔
145
  } else if (type == "parentnuclide") {
837✔
146
    return Filter::create<ParentNuclideFilter>(id);
11✔
147
  } else if (type == "particle") {
826✔
148
    return Filter::create<ParticleFilter>(id);
387✔
149
  } else if (type == "polar") {
439✔
150
    return Filter::create<PolarFilter>(id);
48✔
151
  } else if (type == "surface") {
391✔
152
    return Filter::create<SurfaceFilter>(id);
177✔
153
  } else if (type == "spatiallegendre") {
214✔
154
    return Filter::create<SpatialLegendreFilter>(id);
11✔
155
  } else if (type == "sphericalharmonics") {
203✔
156
    return Filter::create<SphericalHarmonicsFilter>(id);
38✔
157
  } else if (type == "time") {
165✔
158
    return Filter::create<TimeFilter>(id);
82✔
159
  } else if (type == "universe") {
83✔
160
    return Filter::create<UniverseFilter>(id);
16✔
161
  } else if (type == "weight") {
67✔
162
    return Filter::create<WeightFilter>(id);
11✔
163
  } else if (type == "zernike") {
56!
164
    return Filter::create<ZernikeFilter>(id);
56✔
UNCOV
165
  } else if (type == "zernikeradial") {
×
UNCOV
166
    return Filter::create<ZernikeRadialFilter>(id);
×
167
  } else {
UNCOV
168
    throw std::runtime_error {fmt::format("Unknown filter type: {}", type)};
×
169
  }
170
  return nullptr;
171
}
172

173
void Filter::set_id(int32_t id)
12,470✔
174
{
175
  assert(id >= 0 || id == C_NONE);
10,226!
176

177
  // Clear entry in filter map if an ID was already assigned before
178
  if (id_ != C_NONE) {
12,470✔
179
    model::filter_map.erase(id_);
1,973✔
180
    id_ = C_NONE;
1,973✔
181
  }
182

183
  // Make sure no other filter has same ID
184
  if (model::filter_map.find(id) != model::filter_map.end()) {
12,470!
UNCOV
185
    throw std::runtime_error {
×
UNCOV
186
      "Two filters have the same ID: " + std::to_string(id)};
×
187
  }
188

189
  // If no ID specified, auto-assign next ID in sequence
190
  if (id == C_NONE) {
12,470✔
191
    id = 0;
2,247✔
192
    for (const auto& f : model::tally_filters) {
12,218✔
193
      id = std::max(id, f->id_);
9,971✔
194
    }
195
    ++id;
2,247✔
196
  }
197

198
  // Update ID and entry in filter map
199
  id_ = id;
12,470✔
200
  model::filter_map[id] = index_;
12,470✔
201
}
12,470✔
202

203
//==============================================================================
204
// C API functions
205
//==============================================================================
206

207
int verify_filter(int32_t index)
37,167✔
208
{
209
  if (index < 0 || index >= model::tally_filters.size()) {
37,167!
UNCOV
210
    set_errmsg("Filter index is out of bounds.");
×
UNCOV
211
    return OPENMC_E_OUT_OF_BOUNDS;
×
212
  }
213
  return 0;
37,167✔
214
}
215

216
extern "C" int openmc_filter_get_id(int32_t index, int32_t* id)
19,357✔
217
{
218
  if (int err = verify_filter(index))
19,357!
219
    return err;
×
220

221
  *id = model::tally_filters[index]->id();
19,357✔
222
  return 0;
19,357✔
223
}
224

225
extern "C" int openmc_filter_set_id(int32_t index, int32_t id)
1,973✔
226
{
227
  if (int err = verify_filter(index))
1,973!
UNCOV
228
    return err;
×
229

230
  model::tally_filters[index]->set_id(id);
1,973✔
231
  return 0;
1,973✔
232
}
233

234
extern "C" int openmc_filter_get_type(int32_t index, char* type)
10,438✔
235
{
236
  if (int err = verify_filter(index))
10,438!
UNCOV
237
    return err;
×
238

239
  std::strcpy(type, model::tally_filters[index]->type_str().c_str());
10,438✔
240
  return 0;
10,438✔
241
}
242

243
extern "C" int openmc_filter_get_num_bins(int32_t index, int* n_bins)
144✔
244
{
245
  if (int err = verify_filter(index))
144!
UNCOV
246
    return err;
×
247

248
  *n_bins = model::tally_filters[index]->n_bins();
144✔
249
  return 0;
144✔
250
}
251

252
extern "C" int openmc_get_filter_index(int32_t id, int32_t* index)
15✔
253
{
254
  auto it = model::filter_map.find(id);
15✔
255
  if (it == model::filter_map.end()) {
15!
UNCOV
256
    set_errmsg("No filter exists with ID=" + std::to_string(id) + ".");
×
UNCOV
257
    return OPENMC_E_INVALID_ID;
×
258
  }
259

260
  *index = it->second;
15✔
261
  return 0;
15✔
262
}
263

264
extern "C" void openmc_get_filter_next_id(int32_t* id)
×
265
{
UNCOV
266
  int32_t largest_filter_id = 0;
×
UNCOV
267
  for (const auto& t : model::tally_filters) {
×
UNCOV
268
    largest_filter_id = std::max(largest_filter_id, t->id());
×
269
  }
UNCOV
270
  *id = largest_filter_id + 1;
×
UNCOV
271
}
×
272

273
extern "C" int openmc_new_filter(const char* type, int32_t* index)
1,973✔
274
{
275
  *index = model::tally_filters.size();
1,973✔
276
  Filter::create(type);
1,973✔
277
  return 0;
1,973✔
278
}
279

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