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

openmc-dev / openmc / 22322317452

pending completion
22322317452

Pull #3808

github

web-flow
Merge 0e9eea39a into 83a30f686
Pull Request #3808: Add properties to settings w/ documentation, c++ loading of filename, and python round-trip test

16820 of 23482 branches covered (71.63%)

Branch coverage included in aggregate %.

76 of 92 new or added lines in 8 files covered. (82.61%)

724 existing lines in 14 files now uncovered.

56900 of 66807 relevant lines covered (85.17%)

43125827.06 hits per line

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

80.51
/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_particle_production.h"
35
#include "openmc/tallies/filter_polar.h"
36
#include "openmc/tallies/filter_reaction.h"
37
#include "openmc/tallies/filter_sph_harm.h"
38
#include "openmc/tallies/filter_sptl_legendre.h"
39
#include "openmc/tallies/filter_surface.h"
40
#include "openmc/tallies/filter_time.h"
41
#include "openmc/tallies/filter_universe.h"
42
#include "openmc/tallies/filter_weight.h"
43
#include "openmc/tallies/filter_zernike.h"
44
#include "openmc/xml_interface.h"
45

46
// explicit template instantiation definition
47
template class openmc::vector<openmc::FilterMatch>;
48

49
namespace openmc {
50

51
//==============================================================================
52
// Global variables
53
//==============================================================================
54

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

60
//==============================================================================
61
// Non-member functions
62
//==============================================================================
63

64
extern "C" size_t tally_filters_size()
942✔
65
{
66
  return model::tally_filters.size();
942✔
67
}
68

69
//==============================================================================
70
// Filter implementation
71
//==============================================================================
72

73
Filter::Filter()
8,664✔
74
{
75
  index_ = model::tally_filters.size(); // Avoids warning about narrowing
8,664✔
76
}
8,664✔
77

78
Filter::~Filter()
8,664✔
79
{
80
  model::filter_map.erase(id_);
8,664✔
81
}
8,664✔
82

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

91
  // Convert filter type to lower case
92
  std::string s;
7,512✔
93
  if (check_for_node(node, "type")) {
7,512!
94
    s = get_node_value(node, "type", true);
7,512✔
95
  }
96

97
  // Allocate according to the filter type
98
  auto f = Filter::create(s, filter_id);
7,512✔
99

100
  // Read filter data from XML
101
  f->from_xml(node);
7,512✔
102
  return f;
7,512✔
103
}
7,512✔
104

105
Filter* Filter::create(const std::string& type, int32_t id)
8,652✔
106
{
107
  if (type == "azimuthal") {
8,652✔
108
    return Filter::create<AzimuthalFilter>(id);
24✔
109
  } else if (type == "cell") {
8,628✔
110
    return Filter::create<CellFilter>(id);
597✔
111
  } else if (type == "cellborn") {
8,031✔
112
    return Filter::create<CellBornFilter>(id);
12✔
113
  } else if (type == "cellfrom") {
8,019✔
114
    return Filter::create<CellFromFilter>(id);
72✔
115
  } else if (type == "cellinstance") {
7,947✔
116
    return Filter::create<CellInstanceFilter>(id);
24✔
117
  } else if (type == "distribcell") {
7,923✔
118
    return Filter::create<DistribcellFilter>(id);
144✔
119
  } else if (type == "delayedgroup") {
7,779✔
120
    return Filter::create<DelayedGroupFilter>(id);
102✔
121
  } else if (type == "energyfunction") {
7,677✔
122
    return Filter::create<EnergyFunctionFilter>(id);
159✔
123
  } else if (type == "energy") {
7,518✔
124
    return Filter::create<EnergyFilter>(id);
1,527✔
125
  } else if (type == "collision") {
5,991✔
126
    return Filter::create<CollisionFilter>(id);
12✔
127
  } else if (type == "energyout") {
5,979✔
128
    return Filter::create<EnergyoutFilter>(id);
522✔
129
  } else if (type == "legendre") {
5,457✔
130
    return Filter::create<LegendreFilter>(id);
642✔
131
  } else if (type == "material") {
4,815✔
132
    return Filter::create<MaterialFilter>(id);
1,872✔
133
  } else if (type == "materialfrom") {
2,943✔
134
    return Filter::create<MaterialFromFilter>(id);
12✔
135
  } else if (type == "mesh") {
2,931✔
136
    return Filter::create<MeshFilter>(id);
1,848✔
137
  } else if (type == "meshborn") {
1,083✔
138
    return Filter::create<MeshBornFilter>(id);
21✔
139
  } else if (type == "meshmaterial") {
1,062✔
140
    return Filter::create<MeshMaterialFilter>(id);
18✔
141
  } else if (type == "meshsurface") {
1,044✔
142
    return Filter::create<MeshSurfaceFilter>(id);
300✔
143
  } else if (type == "mu") {
744✔
144
    return Filter::create<MuFilter>(id);
24✔
145
  } else if (type == "musurface") {
720✔
146
    return Filter::create<MuSurfaceFilter>(id);
21✔
147
  } else if (type == "parentnuclide") {
699✔
148
    return Filter::create<ParentNuclideFilter>(id);
9✔
149
  } else if (type == "particle") {
690✔
150
    return Filter::create<ParticleFilter>(id);
321✔
151
  } else if (type == "particleproduction") {
369✔
152
    return Filter::create<ParticleProductionFilter>(id);
24✔
153
  } else if (type == "polar") {
345✔
154
    return Filter::create<PolarFilter>(id);
36✔
155
  } else if (type == "reaction") {
309✔
156
    return Filter::create<ReactionFilter>(id);
12✔
157
  } else if (type == "surface") {
297✔
158
    return Filter::create<SurfaceFilter>(id);
135✔
159
  } else if (type == "spatiallegendre") {
162✔
160
    return Filter::create<SpatialLegendreFilter>(id);
9✔
161
  } else if (type == "sphericalharmonics") {
153✔
162
    return Filter::create<SphericalHarmonicsFilter>(id);
30✔
163
  } else if (type == "time") {
123✔
164
    return Filter::create<TimeFilter>(id);
66✔
165
  } else if (type == "universe") {
57✔
166
    return Filter::create<UniverseFilter>(id);
12✔
167
  } else if (type == "weight") {
45✔
168
    return Filter::create<WeightFilter>(id);
9✔
169
  } else if (type == "zernike") {
36!
170
    return Filter::create<ZernikeFilter>(id);
36✔
171
  } else if (type == "zernikeradial") {
×
UNCOV
172
    return Filter::create<ZernikeRadialFilter>(id);
×
173
  } else {
UNCOV
174
    throw std::runtime_error {fmt::format("Unknown filter type: {}", type)};
×
175
  }
176
  return nullptr;
177
}
178

179
void Filter::set_id(int32_t id)
9,606✔
180
{
181
  assert(id >= 0 || id == C_NONE);
7,337!
182

183
  // Clear entry in filter map if an ID was already assigned before
184
  if (id_ != C_NONE) {
9,606✔
185
    model::filter_map.erase(id_);
942✔
186
    id_ = C_NONE;
942✔
187
  }
188

189
  // Make sure no other filter has same ID
190
  if (model::filter_map.find(id) != model::filter_map.end()) {
9,606!
UNCOV
191
    throw std::runtime_error {
×
UNCOV
192
      "Two filters have the same ID: " + std::to_string(id)};
×
193
  }
194

195
  // If no ID specified, auto-assign next ID in sequence
196
  if (id == C_NONE) {
9,606✔
197
    id = 0;
1,152✔
198
    for (const auto& f : model::tally_filters) {
5,895✔
199
      id = std::max(id, f->id_);
4,743✔
200
    }
201
    ++id;
1,152✔
202
  }
203

204
  // Update ID and entry in filter map
205
  id_ = id;
9,606✔
206
  model::filter_map[id] = index_;
9,606✔
207
}
9,606✔
208

209
//==============================================================================
210
// C API functions
211
//==============================================================================
212

213
int verify_filter(int32_t index)
16,929✔
214
{
215
  if (index < 0 || index >= model::tally_filters.size()) {
16,929!
UNCOV
216
    set_errmsg("Filter index is out of bounds.");
×
UNCOV
217
    return OPENMC_E_OUT_OF_BOUNDS;
×
218
  }
219
  return 0;
16,929✔
220
}
221

222
extern "C" int openmc_filter_get_id(int32_t index, int32_t* id)
8,709✔
223
{
224
  if (int err = verify_filter(index))
8,709!
UNCOV
225
    return err;
×
226

227
  *id = model::tally_filters[index]->id();
8,709✔
228
  return 0;
8,709✔
229
}
230

231
extern "C" int openmc_filter_set_id(int32_t index, int32_t id)
942✔
232
{
233
  if (int err = verify_filter(index))
942!
UNCOV
234
    return err;
×
235

236
  model::tally_filters[index]->set_id(id);
942✔
237
  return 0;
942✔
238
}
239

240
extern "C" int openmc_filter_get_type(int32_t index, char* type)
4,770✔
241
{
242
  if (int err = verify_filter(index))
4,770!
UNCOV
243
    return err;
×
244

245
  std::strcpy(type, model::tally_filters[index]->type_str().c_str());
4,770✔
246
  return 0;
4,770✔
247
}
248

249
extern "C" int openmc_filter_get_num_bins(int32_t index, int* n_bins)
108✔
250
{
251
  if (int err = verify_filter(index))
108!
UNCOV
252
    return err;
×
253

254
  *n_bins = model::tally_filters[index]->n_bins();
108✔
255
  return 0;
108✔
256
}
257

258
extern "C" int openmc_get_filter_index(int32_t id, int32_t* index)
9✔
259
{
260
  auto it = model::filter_map.find(id);
9✔
261
  if (it == model::filter_map.end()) {
9!
UNCOV
262
    set_errmsg("No filter exists with ID=" + std::to_string(id) + ".");
×
UNCOV
263
    return OPENMC_E_INVALID_ID;
×
264
  }
265

266
  *index = it->second;
9✔
267
  return 0;
9✔
268
}
269

270
extern "C" void openmc_get_filter_next_id(int32_t* id)
×
271
{
UNCOV
272
  int32_t largest_filter_id = 0;
×
273
  for (const auto& t : model::tally_filters) {
×
274
    largest_filter_id = std::max(largest_filter_id, t->id());
×
275
  }
UNCOV
276
  *id = largest_filter_id + 1;
×
UNCOV
277
}
×
278

279
extern "C" int openmc_new_filter(const char* type, int32_t* index)
942✔
280
{
281
  *index = model::tally_filters.size();
942✔
282
  Filter::create(type);
942✔
283
  return 0;
942✔
284
}
285

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