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

Open-Sn / opensn / #5

02 Apr 2026 01:04PM UTC coverage: 74.858% (-1.2%) from 76.085%
#5

push

web-flow
Merge pull request #1009 from andrsd/unit-tests

Removing `opensn-test`

20988 of 28037 relevant lines covered (74.86%)

65922489.9 hits per line

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

96.43
/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)
661✔
21
{
22
  // clang-format off
23
  // multi-group cross section
24
  auto multigroup_xs = py::class_<MultiGroupXS, std::shared_ptr<MultiGroupXS>>(
661✔
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
    - ``Scale`` mutates the current object.
37
    - ``Combine`` returns a new cross-section object and does not mutate inputs.
38
    )"
39
  );
661✔
40
  multigroup_xs.def(
1,322✔
41
    py::init(
661✔
42
      []()
959✔
43
      {
44
        std::shared_ptr<MultiGroupXS> xs = std::make_shared<MultiGroupXS>();
959✔
45
        multigroup_xs_stack.push_back(xs);
959✔
46
        return xs;
959✔
47
      }),
×
48
    "Create an empty multi-group cross section."
49
  );
50
  multigroup_xs.def(
1,322✔
51
    "CreateSimpleOneGroup",
52
    [](MultiGroupXS& self, double sigma_t, double c, double velocity) {
848✔
53
      self = MultiGroupXS::CreateSimpleOneGroup(sigma_t, c, velocity);
187✔
54
    },
187✔
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,322✔
73
    py::arg("c"),
661✔
74
    py::arg("velocity") = 0.0
661✔
75
  );
76
  multigroup_xs.def(
661✔
77
    "LoadFromOpenSn",
78
    [](MultiGroupXS& self, const std::string& file_name)
1,349✔
79
    {
80
      self = MultiGroupXS::LoadFromOpenSn(file_name);
688✔
81
    },
688✔
82
    py::arg("file_name"),
661✔
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(
661✔
124
    "Combine",
125
    &MultiGroupXS::Combine,
1,322✔
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
    - Named custom 1D XS are preserved and combined with the same density weighting.
150
    - Fission spectra and precursor yields are weighted by fissile density
151
      fraction so their sums remain normalized.
152
    - All inputs must have the same number of groups.
153
    - If inverse velocity is present, all inputs must have identical values.
154

155
    Examples
156
    --------
157

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

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

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

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

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