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

Open-Sn / opensn / #2

23 Mar 2026 03:31AM UTC coverage: 73.898% (+0.002%) from 73.896%
#2

push

web-flow
Merge pull request #994 from wdhawkins/boundary_error_names

Print boundary names in error messages

0 of 1 new or added line in 1 file covered. (0.0%)

22 existing lines in 3 files now uncovered.

20477 of 27710 relevant lines covered (73.9%)

67310933.32 hits per line

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

96.34
/python/lib/xs.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/materials/multi_group_xs/multi_group_xs.h"
7
#include "framework/materials/multi_group_xs/xsfile.h"
8
#include <pybind11/stl.h>
9
#include <memory>
10
#include <string>
11
#include <vector>
12

13
#define XS_GETTER(method_name) [](MultiGroupXS& self) { return convert_vector(self.method_name()); }
14

15
namespace opensn
16
{
17

18
// Wrap multi-group cross section
19
void
20
WrapMultiGroupXS(py::module& xs)
681✔
21
{
22
  // clang-format off
23
  // multi-group cross section
24
  auto multigroup_xs = py::class_<MultiGroupXS, std::shared_ptr<MultiGroupXS>>(
681✔
25
    xs,
26
    "MultiGroupXS",
27
    R"(
28
    Multi-group cross section.
29

30
    Wrapper of :cpp:class:`opensn::MultiGroupXS`.
31

32
    The Python API currently has two types of methods:
33

34
    - Creation/loading methods such as ``CreateSimpleOneGroup``,
35
      ``LoadFromOpenSn``, and ``LoadFromOpenMC`` populate an existing object.
36
    - Transformation methods such as ``Scale`` and ``Combine`` return new
37
      cross-section objects and do not mutate their inputs.
38
    )"
39
  );
681✔
40
  multigroup_xs.def(
1,362✔
41
    py::init(
681✔
42
      []()
905✔
43
      {
44
        std::shared_ptr<MultiGroupXS> xs = std::make_shared<MultiGroupXS>();
905✔
45
        multigroup_xs_stack.push_back(xs);
905✔
46
        return xs;
905✔
47
      }),
×
48
    "Create an empty multi-group cross section."
49
  );
50
  multigroup_xs.def(
1,362✔
51
    "CreateSimpleOneGroup",
52
    [](MultiGroupXS& self, double sigma_t, double c, double velocity) {
869✔
53
      self = MultiGroupXS::CreateSimpleOneGroup(sigma_t, c, velocity);
188✔
54
    },
188✔
55
    R"(
56
    Populate this object with a one-group cross section.
57

58
    Parameters
59
    ----------
60
    sigma_t: float
61
        Total cross section.
62
    c: float
63
        Scattering ratio.
64
    velocity: float, optional
65
        Group velocity. If provided and positive, inverse velocity
66
        is populated with 1.0/velocity.
67

68
    Notes
69
    -----
70
    This method mutates ``self`` by replacing its current contents.
71
    )",
72
    py::arg("sigma_t"),
1,362✔
73
    py::arg("c"),
681✔
74
    py::arg("velocity") = 0.0
681✔
75
  );
76
  multigroup_xs.def(
681✔
77
    "LoadFromOpenSn",
78
    [](MultiGroupXS& self, const std::string& file_name)
1,325✔
79
    {
80
      self = MultiGroupXS::LoadFromOpenSn(file_name);
644✔
81
    },
644✔
82
    py::arg("file_name"),
681✔
83
    R"(
84
    Load multi-group cross sections from an OpenSn cross section input file
85
    into this object.
86

87
    Format is as follows (for transfers, gprime denotes the departing group and g is the arrival
88
    group).
89

90
    .. code-block:: none
91

92
       # Add comment lines, as needed
93
       NUM_GROUPS ng
94
       NUM_MOMENTS nmom
95

96
       SIGMA_T_BEGIN
97
       0 value
98
       .
99
       .
100
       ng-1 value
101
       SIGMA_T_END
102

103
       SIGMA_A_BEGIN
104
       0 value
105
       .
106
       .
107
       ng-1 value
108
       SIGMA_A_END
109

110
       TRANSFER_MOMENTS_BEGIN
111
       M_GFROM_GTO_VAL 0 0 0 value
112
       .
113
       M_GFROM_GTO_VAL moment gfrom gto value
114
       .
115
       M_GFROM_GTO_VAL nmom-1 ng-1 ng-1 value
116
       TRANSFER_MOMENTS_END
117

118
    Notes
119
    -----
120
    This method mutates ``self`` by replacing its current contents.
121
    )"
122
  );
123
  multigroup_xs.def_static(
681✔
124
    "Combine",
125
    &MultiGroupXS::Combine,
1,362✔
126
    R"(
127
    Return a new combined cross-section.
128

129
    Parameters
130
    ----------
131

132
    combinations: List[Tuple[pyopensn.xs.MultiGroupXS, float]]
133
        List of ``(cross_section, density)`` pairs.
134
        The density values are linear weights used to combine raw cross sections.
135

136
    Returns
137
    -------
138
    pyopensn.xs.MultiGroupXS
139
        A new combined cross-section object. The input cross sections are not
140
        modified.
141

142
    Notes
143
    -----
144
    Let :math:`d_i` be the supplied density for cross section :math:`i`.
145

146
    - Raw XS terms are density-weighted sums:
147
      :math:`\sigma = \sum_i d_i \sigma_i`
148
      (e.g. total, absorption, fission, transfer, production).
149
    - Fission spectra and precursor yields are weighted by fissile density
150
      fraction so their sums remain normalized.
151
    - All inputs must have the same number of groups.
152
    - If inverse velocity is present, all inputs must have identical values.
153

154
    Examples
155
    --------
156

157
    >>> xs_1 = MultiGroupXS()
158
    >>> xs_1.CreateSimpleOneGroup(sigma_t=1, c=0.5)
159
    >>> xs_2 = MultiGroupXS()
160
    >>> xs_2.CreateSimpleOneGroup(sigma_t=2, c=1./3.)
161
    >>> combo = [
162
    ...     ( xs_1, 0.5 ),
163
    ...     ( xs_2, 3.0 )
164
    ... ]
165
    >>> xs_combined = MultiGroupXS.Combine(combo)
166
    )",
167
    py::arg("combinations")
681✔
168
  );
169
  multigroup_xs.def(
1,362✔
170
    "LoadFromOpenMC",
171
    [](MultiGroupXS& self,
754✔
172
       const std::string& file_name,
173
       const std::string& dataset_name,
174
       double temperature,
175
       const std::vector<std::string>& extra_xs_names)
176
    {
177
      self = MultiGroupXS::LoadFromOpenMC(file_name, dataset_name, temperature, extra_xs_names);
73✔
178
    },
73✔
179
    R"(
180
    Load multi-group cross sections from an OpenMC cross-section file into this
181
    object.
182

183
    Notes
184
    -----
185
    This method mutates ``self`` by replacing its current contents.
186
    )",
187
    py::arg("file_name"),
1,362✔
188
    py::arg("dataset_name"),
1,362✔
189
    py::arg("temperature"),
681✔
190
    py::arg("extra_xs_names") = std::vector<std::string>()
1,362✔
191
  );
192
  multigroup_xs.def(
681✔
193
    "Scale",
194
    &MultiGroupXS::Scale,
1,362✔
195
    R"(
196
    Return a scaled copy of the cross sections.
197

198
    Parameters
199
    ----------
200
    factor: float
201
        Multiplicative factor applied to scalable cross-section data.
202

203
    Returns
204
    -------
205
    pyopensn.xs.MultiGroupXS
206
        A new scaled cross-section object. ``self`` is not modified.
207
    )",
208
    py::arg("factor")
681✔
209
  );
210
  multigroup_xs.def_property_readonly(
681✔
211
    "num_groups",
212
    &MultiGroupXS::GetNumGroups,
681✔
213
    "Get number of energy groups."
214
  );
215
  multigroup_xs.def_property_readonly(
681✔
216
    "scattering_order",
217
    &MultiGroupXS::GetScatteringOrder,
681✔
218
    "Get Legendre scattering order."
219
  );
220
  multigroup_xs.def_property_readonly(
681✔
221
    "num_precursors",
222
    &MultiGroupXS::GetNumPrecursors,
681✔
223
    "Get number of precursors."
224
  );
225
  multigroup_xs.def_property_readonly(
681✔
226
    "is_fissionable",
227
    &MultiGroupXS::IsFissionable,
681✔
228
    "Check if the material is fissile."
229
  );
230
  multigroup_xs.def_property_readonly(
681✔
231
    "sigma_t",
232
    XS_GETTER(GetSigmaTotal),
19✔
233
    "Get total cross section.",
234
    py::keep_alive<0, 1>()
681✔
235
  );
236
  multigroup_xs.def_property_readonly(
681✔
237
    "sigma_a",
238
    XS_GETTER(GetSigmaAbsorption),
2,512✔
239
    "Get absorption cross section.",
240
    py::keep_alive<0, 1>()
681✔
241
  );
242
  multigroup_xs.def_property_readonly(
681✔
243
    "sigma_f",
244
    XS_GETTER(GetSigmaFission),
4✔
245
    "Get fission cross section.",
246
    py::keep_alive<0, 1>()
681✔
247
  );
248
  multigroup_xs.def_property_readonly(
681✔
249
    "chi",
250
    XS_GETTER(GetChi),
2✔
251
    "Get neutron fission spectrum.",
252
    py::keep_alive<0, 1>()
681✔
253
  );
254
  multigroup_xs.def_property_readonly(
681✔
255
    "nu_sigma_f",
256
    XS_GETTER(GetNuSigmaF),
28✔
257
    "Get neutron production due to fission.",
258
    py::keep_alive<0, 1>()
681✔
259
  );
260
  multigroup_xs.def_property_readonly(
681✔
261
    "nu_prompt_sigma_f",
UNCOV
262
    XS_GETTER(GetNuPromptSigmaF),
×
263
    "Get prompt neutron production due to fission.",
264
    py::keep_alive<0, 1>()
681✔
265
  );
266
  multigroup_xs.def_property_readonly(
681✔
267
    "nu_delayed_sigma_f",
UNCOV
268
    XS_GETTER(GetNuDelayedSigmaF),
×
269
    "Get delayed neutron production due to fission.",
270
    py::keep_alive<0, 1>()
681✔
271
  );
272
  multigroup_xs.def(
681✔
273
    "has_custom_xs",
274
    &MultiGroupXS::HasCustomXS,
1,362✔
275
    "Check if a custom XS is available.",
276
    py::arg("name")
681✔
277
  );
278
  multigroup_xs.def(
681✔
279
    "get_custom_xs",
280
    [](MultiGroupXS& self, const std::string& name)
682✔
281
    { return convert_vector(self.GetCustomXS(name)); },
1✔
282
    "Get a custom XS vector.",
283
    py::arg("name")
681✔
284
  );
285
  multigroup_xs.def(
681✔
286
    "custom_xs_names",
287
    &MultiGroupXS::GetCustomXSNames,
681✔
288
    "Get a list of custom XS entries."
289
  );
290
  multigroup_xs.def_property_readonly(
681✔
291
    "inv_velocity",
292
    XS_GETTER(GetInverseVelocity),
25✔
293
    "Get inverse velocity.",
294
    py::keep_alive<0, 1>()
681✔
295
  );
296
  // clang-format on
297
}
681✔
298

299
// Wrap the cross section components of OpenSn
300
void
301
py_xs(py::module& pyopensn)
72✔
302
{
303
  py::module xs = pyopensn.def_submodule("xs", "Cross section module.");
72✔
304
  WrapMultiGroupXS(xs);
72✔
305
}
72✔
306

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