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

Open-Sn / opensn / 21933416870

12 Feb 2026 03:12AM UTC coverage: 74.409% (-0.4%) from 74.806%
21933416870

push

github

web-flow
Merge pull request #922 from wdhawkins/named_xs

Adding ability to load user-specifed OpenMC cross sections

28 of 52 new or added lines in 4 files covered. (53.85%)

418 existing lines in 9 files now uncovered.

19839 of 26662 relevant lines covered (74.41%)

67886044.11 hits per line

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

77.36
/python/lib/fieldfunc.cc
1
// SPDX-FileCopyrightText: 2025 The OpenSn Authors <https://open-sn.github.io/opensn/>
2
// SPDX-License-Identifier: MIT
3

4
#include "python/lib/py_wrappers.h"
5
#include "framework/runtime.h"
6
#include "framework/field_functions/field_function.h"
7
#include "framework/field_functions/field_function_grid_based.h"
8
#include "framework/field_functions/interpolation/ffinterpolation.h"
9
#include "framework/field_functions/interpolation/ffinter_point.h"
10
#include "framework/field_functions/interpolation/ffinter_line.h"
11
#include "framework/field_functions/interpolation/ffinter_volume.h"
12
#include <pybind11/functional.h>
13
#include <algorithm>
14
#include <map>
15
#include <memory>
16
#include <sstream>
17
#include <string>
18
#include <vector>
19

20
namespace opensn
21
{
22

23
// dictionary to field function interpolation operation type
24
static std::map<std::string, FieldFunctionInterpolationOperation> ff_op_type_map{
25
  {"sum", FieldFunctionInterpolationOperation::OP_SUM},
26
  {"avg", FieldFunctionInterpolationOperation::OP_AVG},
27
  {"max", FieldFunctionInterpolationOperation::OP_MAX},
28
  {"min", FieldFunctionInterpolationOperation::OP_MIN},
29
  {"sum_func", FieldFunctionInterpolationOperation::OP_SUM_FUNC},
30
  {"avg_func", FieldFunctionInterpolationOperation::OP_AVG_FUNC},
31
  {"max_func", FieldFunctionInterpolationOperation::OP_MAX_FUNC},
32
  {"min_func", FieldFunctionInterpolationOperation::OP_MIN_FUNC}};
33

34
static std::string
UNCOV
35
OpToString()
×
36
{
UNCOV
37
  std::vector<std::string> keys;
×
UNCOV
38
  keys.reserve(ff_op_type_map.size());
×
UNCOV
39
  for (const auto& [key, _] : ff_op_type_map)
×
UNCOV
40
    keys.push_back(key);
×
UNCOV
41
  std::sort(keys.begin(), keys.end());
×
UNCOV
42
  std::ostringstream oss;
×
UNCOV
43
  for (size_t i = 0; i < keys.size(); ++i)
×
44
  {
UNCOV
45
    if (i > 0)
×
UNCOV
46
      oss << ", ";
×
UNCOV
47
    oss << keys[i];
×
48
  }
UNCOV
49
  return oss.str();
×
UNCOV
50
}
×
51

52
// Wrap field functions
53
void
54
WrapFieldFunction(py::module& ffunc)
668✔
55
{
56
  // clang-format off
57
  // field function
58
  auto field_func = py::class_<FieldFunction, std::shared_ptr<FieldFunction>>(
668✔
59
    ffunc,
60
    "FieldFunction",
61
    R"(
62
    Field function.
63

64
    Wrapper of :cpp:class:`opensn::FieldFunction`.
65
    )"
66
  );
668✔
67
  // clang-format on
68
}
668✔
69

70
// Wrap field functions grid based
71
void
72
WrapFieldFunctionGridBased(py::module& ffunc)
668✔
73
{
74
  // clang-format off
75
  // field function grid based
76
  auto field_func_grid_based = py::class_<FieldFunctionGridBased,
668✔
77
                                          std::shared_ptr<FieldFunctionGridBased>,
78
                                          FieldFunction>(
79
    ffunc,
80
    "FieldFunctionGridBased",
81
    R"(
82
    Field function grid based.
83

84
    Wrapper of :cpp:class:`opensn::FieldFunctionGridBased`.
85
    )"
86
  );
668✔
87
  field_func_grid_based.def_static(
668✔
88
    "ExportMultipleToPVTU",
89
    [](py::list& ff_list, const std::string& base_name)
725✔
90
    {
91
      std::vector<std::shared_ptr<const FieldFunctionGridBased>> cpp_ff_list;
57✔
92
      cpp_ff_list.reserve(ff_list.size());
57✔
93
      for (py::handle item : ff_list)
6,051✔
94
      {
95
        cpp_ff_list.push_back(item.cast<std::shared_ptr<const FieldFunctionGridBased>>());
11,874✔
96
      }
97
      FieldFunctionGridBased::ExportMultipleToPVTU(base_name, cpp_ff_list);
57✔
98
    },
57✔
99
    R"(
100
      Export a list of "field function grid based" to parallel VTU format.
101

102
      Parameters
103
      ----------
104
      ff_list: List[opensn.FieldFunctionGridBased]
105
          List of "field function grid based" to export.
106
      base_name: str
107
          Base name.
108
    )",
109
    py::arg("ff_list"), py::arg("base_name")
668✔
110
  );
111
  // clang-format on
112
}
668✔
113

114
// Wrap field function interpolation
115
void
116
WrapFieldFunctionInterpolation(py::module& ffunc)
668✔
117
{
118
  // clang-format off
119
  // field function interpolation
120
  auto field_func_interp = py::class_<FieldFunctionInterpolation,
668✔
121
                                      std::shared_ptr<FieldFunctionInterpolation>>(
122
    ffunc,
123
    "FieldFunctionInterpolation",
124
    R"(
125
    Base class for field-function interpolation objects.
126

127
    Wrapper of :cpp:class:`opensn::FieldFunctionInterpolation`.
128
    )"
129
  );
668✔
130
  field_func_interp.def(
668✔
131
    "AddFieldFunction",
132
    &FieldFunctionInterpolation::AddFieldFunction,
1,336✔
133
    R"(
134
    Add a field function to the list.
135
    )",
136
    py::arg("ff")
668✔
137
  );
138
  field_func_interp.def(
668✔
139
    "Initialize",
140
    &FieldFunctionInterpolation::Initialize,
668✔
141
    R"(
142
    Initialize field function interpolator.
143
    )"
144
  );
145
  field_func_interp.def(
668✔
146
    "Execute",
147
    &FieldFunctionInterpolation::Execute,
668✔
148
    R"(
149
    Execute field function interpolator.
150
    )"
151
  );
152
  field_func_interp.def(
668✔
153
    "ExportToCSV",
154
    &FieldFunctionInterpolation::ExportToCSV,
1,336✔
155
    R"(
156
    Export field function interpolation to CSV files.
157

158
    Parameters
159
    ----------
160
    base_name: str
161
        Base name of the exported CSVs.
162
    )",
163
    py::arg("base_name")
668✔
164
  );
165
  field_func_interp.def_static(
668✔
166
    "GetFieldFunctionByName",
167
    [](const std::string& ff_name)
668✔
168
    {
169
      // get list of suitable field functions
UNCOV
170
      py::list matched_ff;
×
UNCOV
171
      for (std::shared_ptr<FieldFunction>& ff_ptr : field_function_stack)
×
172
      {
UNCOV
173
        if (ff_ptr->GetName() == ff_name)
×
174
        {
UNCOV
175
          matched_ff.append(ff_ptr);
×
176
        }
177
      }
UNCOV
178
      return matched_ff;
×
UNCOV
179
    },
×
180
    R"(
181
    Get the list of field functions matching a given name.
182

183
    This function returns a list of field functions whose names match the given argument. The list
184
    may be empty or contain multiple elements.
185

186
    Parameters
187
    ----------
188
    ff_name: str
189
        Field function name
190
    )",
191
    py::arg("ff_name")
668✔
192
  );
193

194
  // field function interpolation point
195
  auto field_func_interp_point = py::class_<FieldFunctionInterpolationPoint,
668✔
196
                                            std::shared_ptr<FieldFunctionInterpolationPoint>,
197
                                            FieldFunctionInterpolation>(
198
    ffunc,
199
    "FieldFunctionInterpolationPoint",
200
    R"(
201
    Interpolate the field function at a point.
202

203
    Wrapper of :cpp:class:`opensn::FieldFunctionInterpolationPoint`.
204
    )"
205
  );
668✔
206
  field_func_interp_point.def(
1,336✔
207
    py::init(
668✔
UNCOV
208
      []()
×
209
      {
UNCOV
210
        return FieldFunctionInterpolationPoint::Create();
×
211
      }
212
    ),
213
    "Default constructor."
214
  );
215
  field_func_interp_point.def(
668✔
216
    "GetPointValue",
217
    &FieldFunctionInterpolationPoint::GetPointValue,
668✔
218
    R"(
219
    Get the value of the field function interpolation at the specified point.
220
    )"
221
  );
222

223
  // field function interpolation line
224
  auto field_func_interp_line = py::class_<FieldFunctionInterpolationLine,
668✔
225
                                           std::shared_ptr<FieldFunctionInterpolationLine>,
226
                                           FieldFunctionInterpolation>(
227
    ffunc,
228
    "FieldFunctionInterpolationLine",
229
    R"(
230
    Line based interpolation function.
231

232
    Wrapper of :cpp:class:`opensn::FieldFunctionInterpolationLine`.
233
    )"
234
  );
668✔
235
  field_func_interp_line.def(
1,336✔
236
    py::init(
668✔
237
      []()
570✔
238
      {
239
        return FieldFunctionInterpolationLine::Create();
570✔
240
      }
241
    ),
242
    "Default constructor."
243
  );
244
  field_func_interp_line.def(
668✔
245
    "SetInitialPoint",
246
    &FieldFunctionInterpolationLine::SetInitialPoint,
1,336✔
247
    R"(
248
    Set initial point.
249

250
    Parameters
251
    ----------
252
    point: pyopensn.math.Vector3
253
        Coordinates of the initial point.
254
    )",
255
    py::arg("point")
668✔
256
  );
257
  field_func_interp_line.def(
668✔
258
    "SetFinalPoint",
259
    &FieldFunctionInterpolationLine::SetFinalPoint,
1,336✔
260
    R"(
261
    Set final point.
262

263
    Parameters
264
    ----------
265
    point: pyopensn.math.Vector3
266
        Coordinates of the final point.
267
    )",
268
    py::arg("point")
668✔
269
  );
270
  field_func_interp_line.def(
668✔
271
    "SetNumberOfPoints",
272
    &FieldFunctionInterpolationLine::SetNumberOfPoints,
1,336✔
273
    R"(
274
    Set number of points.
275

276
    Parameters
277
    ----------
278
    number: int
279
        Number of points.
280
    )",
281
    py::arg("number")
668✔
282
  );
283

284
  // field function interpolation volume
285
  auto field_func_interp_volume = py::class_<FieldFunctionInterpolationVolume,
668✔
286
                                             std::shared_ptr<FieldFunctionInterpolationVolume>,
287
                                             FieldFunctionInterpolation>(
288
    ffunc,
289
    "FieldFunctionInterpolationVolume",
290
    R"(
291
    A line based interpolation function.
292

293
    Wrapper of :cpp:class:`opensn::FieldFunctionInterpolationVolume`.
294
    )"
295
  );
668✔
296
  field_func_interp_volume.def(
1,336✔
297
    py::init(
668✔
298
      []()
6,595✔
299
      {
300
        return FieldFunctionInterpolationVolume::Create();
6,595✔
301
      }
302
    ),
303
    "Default constructor."
304
  );
305
  field_func_interp_volume.def(
668✔
306
    "SetLogicalVolume",
307
    &FieldFunctionInterpolationVolume::SetLogicalVolume,
1,336✔
308
    "Set logical volume.",
309
    py::arg("lv")
668✔
310
  );
311
  field_func_interp_volume.def(
668✔
312
    "SetOperationType",
313
    [](FieldFunctionInterpolationVolume& self, const std::string& op_type)
7,275✔
314
    {
315
      const auto it = ff_op_type_map.find(op_type);
6,607✔
316
      if (it == ff_op_type_map.end())
6,607✔
UNCOV
317
        throw std::runtime_error("Unknown field-function operation '" + op_type +
×
UNCOV
318
                                 "'. Valid options are: " + OpToString());
×
319
      self.SetOperationType(it->second);
6,607✔
320
    },
6,607✔
321
    R"(
322
    Set operation type.
323

324
    Parameters
325
    ----------
326
    op_type: {'sum', 'avg', 'max', 'min', 'sum_func', 'avg_func', 'max_func', 'min_func'}
327
        Operation type.
328
    )",
329
    py::arg("op_type")
668✔
330
  );
331
  field_func_interp_volume.def(
668✔
332
    "SetOperationFunction",
333
    [](FieldFunctionInterpolationVolume& self, const ScalarMaterialFunction& function)
668✔
334
    {
UNCOV
335
      self.SetOperationFunction(function);
×
336
    },
337
    R"(
338
    Set the field function operation type to a custom scalar material function.
339

340
    Parameters
341
    ----------
342
    function: Callable[[float, int], float]
343
        A scalar material function that takes the field function value (float) and the
344
        block id (int) as parameters and returns a double.
345
    )",
346
    py::arg("function")
668✔
347
  );
348
  field_func_interp_volume.def(
668✔
349
    "GetValue",
350
    &FieldFunctionInterpolationVolume::GetValue,
668✔
351
    R"(
352
    Returns the value of the field function interpolation.
353
    )"
354
  );
355
  // clang-format on
356
}
668✔
357

358
// Wrap the field function components of OpenSn
359
void
360
py_ffunc(py::module& pyopensn)
63✔
361
{
362
  py::module ffunc = pyopensn.def_submodule("fieldfunc", "Field function module.");
63✔
363
  WrapFieldFunction(ffunc);
63✔
364
  WrapFieldFunctionGridBased(ffunc);
63✔
365
  WrapFieldFunctionInterpolation(ffunc);
63✔
366
}
63✔
367

368
} // namespace opensn
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