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

openmc-dev / openmc / 15371300071

01 Jun 2025 05:04AM UTC coverage: 85.143% (+0.3%) from 84.827%
15371300071

Pull #3176

github

web-flow
Merge 4f739184a into cb95c784b
Pull Request #3176: MeshFilter rotation - solution to issue #3166

86 of 99 new or added lines in 4 files covered. (86.87%)

3707 existing lines in 117 files now uncovered.

52212 of 61323 relevant lines covered (85.14%)

42831974.38 hits per line

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

85.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_meshsurface.h"
29
#include "openmc/tallies/filter_mu.h"
30
#include "openmc/tallies/filter_musurface.h"
31
#include "openmc/tallies/filter_parent_nuclide.h"
32
#include "openmc/tallies/filter_particle.h"
33
#include "openmc/tallies/filter_polar.h"
34
#include "openmc/tallies/filter_sph_harm.h"
35
#include "openmc/tallies/filter_sptl_legendre.h"
36
#include "openmc/tallies/filter_surface.h"
37
#include "openmc/tallies/filter_time.h"
38
#include "openmc/tallies/filter_universe.h"
39
#include "openmc/tallies/filter_weight.h"
40
#include "openmc/tallies/filter_zernike.h"
41
#include "openmc/xml_interface.h"
42

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

46
namespace openmc {
47

48
//==============================================================================
49
// Global variables
50
//==============================================================================
51

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

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

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

66
//==============================================================================
67
// Filter implementation
68
//==============================================================================
69

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

75
Filter::~Filter()
12,559✔
76
{
77
  model::filter_map.erase(id_);
12,559✔
78
}
12,559✔
UNCOV
79

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

88
  // Convert filter type to lower case
10,540✔
89
  std::string s;
90
  if (check_for_node(node, "type")) {
91
    s = get_node_value(node, "type", true);
10,540✔
UNCOV
92
  }
×
93

94
  // Allocate according to the filter type
10,540✔
95
  auto f = Filter::create(s, filter_id);
96

97
  // Read filter data from XML
10,540✔
98
  f->from_xml(node);
10,540✔
99
  return f;
10,540✔
100
}
101

102
Filter* Filter::create(const std::string& type, int32_t id)
103
{
10,540✔
104
  if (type == "azimuthal") {
105
    return Filter::create<AzimuthalFilter>(id);
106
  } else if (type == "cell") {
10,540✔
107
    return Filter::create<CellFilter>(id);
10,540✔
108
  } else if (type == "cellborn") {
10,540✔
109
    return Filter::create<CellBornFilter>(id);
110
  } else if (type == "cellfrom") {
12,537✔
111
    return Filter::create<CellFromFilter>(id);
112
  } else if (type == "cellinstance") {
12,537✔
113
    return Filter::create<CellInstanceFilter>(id);
44✔
114
  } else if (type == "distribcell") {
12,493✔
115
    return Filter::create<DistribcellFilter>(id);
1,007✔
116
  } else if (type == "delayedgroup") {
11,486✔
117
    return Filter::create<DelayedGroupFilter>(id);
22✔
118
  } else if (type == "energyfunction") {
11,464✔
119
    return Filter::create<EnergyFunctionFilter>(id);
132✔
120
  } else if (type == "energy") {
11,332✔
121
    return Filter::create<EnergyFilter>(id);
46✔
122
  } else if (type == "collision") {
11,286✔
123
    return Filter::create<CollisionFilter>(id);
243✔
124
  } else if (type == "energyout") {
11,043✔
125
    return Filter::create<EnergyoutFilter>(id);
132✔
126
  } else if (type == "legendre") {
10,911✔
127
    return Filter::create<LegendreFilter>(id);
281✔
128
  } else if (type == "material") {
10,630✔
129
    return Filter::create<MaterialFilter>(id);
1,790✔
130
  } else if (type == "materialfrom") {
8,840✔
131
    return Filter::create<MaterialFromFilter>(id);
22✔
132
  } else if (type == "mesh") {
8,818✔
133
    return Filter::create<MeshFilter>(id);
565✔
134
  } else if (type == "meshborn") {
8,253✔
135
    return Filter::create<MeshBornFilter>(id);
793✔
136
  } else if (type == "meshsurface") {
7,460✔
137
    return Filter::create<MeshSurfaceFilter>(id);
2,736✔
138
  } else if (type == "mu") {
4,724✔
139
    return Filter::create<MuFilter>(id);
22✔
140
  } else if (type == "musurface") {
4,702✔
141
    return Filter::create<MuSurfaceFilter>(id);
3,010✔
142
  } else if (type == "parentnuclide") {
1,692✔
143
    return Filter::create<ParentNuclideFilter>(id);
37✔
144
  } else if (type == "particle") {
1,655✔
145
    return Filter::create<ParticleFilter>(id);
535✔
146
  } else if (type == "polar") {
1,120✔
147
    return Filter::create<PolarFilter>(id);
44✔
148
  } else if (type == "surface") {
1,076✔
149
    return Filter::create<SurfaceFilter>(id);
37✔
150
  } else if (type == "spatiallegendre") {
1,039✔
151
    return Filter::create<SpatialLegendreFilter>(id);
15✔
152
  } else if (type == "sphericalharmonics") {
1,024✔
153
    return Filter::create<SphericalHarmonicsFilter>(id);
498✔
154
  } else if (type == "time") {
526✔
155
    return Filter::create<TimeFilter>(id);
66✔
156
  } else if (type == "universe") {
460✔
157
    return Filter::create<UniverseFilter>(id);
199✔
158
  } else if (type == "weight") {
261✔
159
    return Filter::create<WeightFilter>(id);
15✔
160
  } else if (type == "zernike") {
246✔
161
    return Filter::create<ZernikeFilter>(id);
52✔
162
  } else if (type == "zernikeradial") {
194✔
163
    return Filter::create<ZernikeRadialFilter>(id);
97✔
164
  } else {
97✔
165
    throw std::runtime_error {fmt::format("Unknown filter type: {}", type)};
22✔
166
  }
75✔
167
  return nullptr;
15✔
168
}
60✔
169

60✔
UNCOV
170
void Filter::set_id(int32_t id)
×
UNCOV
171
{
×
172
  assert(id >= 0 || id == C_NONE);
UNCOV
173

×
174
  // Clear entry in filter map if an ID was already assigned before
175
  if (id_ != C_NONE) {
176
    model::filter_map.erase(id_);
177
    id_ = C_NONE;
178
  }
14,207✔
179

180
  // Make sure no other filter has same ID
12,308✔
181
  if (model::filter_map.find(id) != model::filter_map.end()) {
182
    throw std::runtime_error {
183
      "Two filters have the same ID: " + std::to_string(id)};
14,207✔
184
  }
1,648✔
185

1,648✔
186
  // If no ID specified, auto-assign next ID in sequence
187
  if (id == C_NONE) {
188
    id = 0;
189
    for (const auto& f : model::tally_filters) {
14,207✔
UNCOV
190
      id = std::max(id, f->id_);
×
UNCOV
191
    }
×
192
    ++id;
193
  }
194

195
  // Update ID and entry in filter map
14,207✔
196
  id_ = id;
2,019✔
197
  model::filter_map[id] = index_;
10,312✔
198
}
8,293✔
199

200
//==============================================================================
2,019✔
201
// C API functions
202
//==============================================================================
203

204
int verify_filter(int32_t index)
14,207✔
205
{
14,207✔
206
  if (index < 0 || index >= model::tally_filters.size()) {
14,207✔
207
    set_errmsg("Filter index is out of bounds.");
208
    return OPENMC_E_OUT_OF_BOUNDS;
209
  }
210
  return 0;
211
}
212

28,959✔
213
extern "C" int openmc_filter_get_id(int32_t index, int32_t* id)
214
{
28,959✔
UNCOV
215
  if (int err = verify_filter(index))
×
UNCOV
216
    return err;
×
217

218
  *id = model::tally_filters[index]->id();
28,959✔
219
  return 0;
220
}
221

14,965✔
222
extern "C" int openmc_filter_set_id(int32_t index, int32_t id)
223
{
14,965✔
UNCOV
224
  if (int err = verify_filter(index))
×
225
    return err;
226

14,965✔
227
  model::tally_filters[index]->set_id(id);
14,965✔
228
  return 0;
229
}
230

1,648✔
231
extern "C" int openmc_filter_get_type(int32_t index, char* type)
232
{
1,648✔
UNCOV
233
  if (int err = verify_filter(index))
×
234
    return err;
235

1,648✔
236
  std::strcpy(type, model::tally_filters[index]->type_str().c_str());
1,648✔
237
  return 0;
238
}
239

8,106✔
240
extern "C" int openmc_filter_get_num_bins(int32_t index, int* n_bins)
241
{
8,106✔
UNCOV
242
  if (int err = verify_filter(index))
×
243
    return err;
244

8,106✔
245
  *n_bins = model::tally_filters[index]->n_bins();
8,106✔
246
  return 0;
247
}
248

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

257
  *index = it->second;
15✔
258
  return 0;
259
}
15✔
260

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

×
270
extern "C" int openmc_new_filter(const char* type, int32_t* index)
UNCOV
271
{
×
UNCOV
272
  *index = model::tally_filters.size();
×
UNCOV
273
  Filter::create(type);
×
274
  return 0;
UNCOV
275
}
×
276

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