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

Open-Sn / opensn / 17874334706

19 Sep 2025 06:40PM UTC coverage: 74.578% (-0.2%) from 74.728%
17874334706

push

github

web-flow
Merge pull request #763 from andrsd/cmake-lib-names

cmake: correcting file names for the opensn library files

17734 of 23779 relevant lines covered (74.58%)

44077127.1 hits per line

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

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

4
#pragma once
5

6
#include "framework/parameters/parameter_block.h"
7
#include "framework/data_types/vector.h"
8
#include <pybind11/pybind11.h>
9
#include <unordered_set>
10
#include <unordered_map>
11
#include <vector>
12

13
namespace py = pybind11;
14

15
namespace opensn
16
{
17

18
// Converter
19

20
/// Convert a C++ vector to a Python memoryview.
21
template <typename T>
22
py::memoryview
23
convert_vector(const std::vector<T>& vec)
24
{
25
  return py::memoryview::from_buffer(const_cast<T*>(vec.data()), {vec.size()}, {sizeof(T)}, true);
26
}
27

28
/// Convert an OpenSn vector to a Python memoryview.
29
template <typename T>
30
py::memoryview
31
convert_vector(const Vector<T>& vec)
32
{
33
  return py::memoryview::from_buffer(const_cast<T*>(vec.data()), {vec.size()}, {sizeof(T)}, true);
34
}
35

36
// Cast kwargs to ParameterBlock
37

38
/// Translate a Python object into a ParameterBlock.
39
ParameterBlock pyobj_to_param_block(const std::string& key, const py::object& obj);
40

41
/// Translate a Python dictionary into a ParameterBlock.
42
ParameterBlock kwargs_to_param_block(const py::kwargs& params);
43

44
// Retrieve arguments from the Python interface
45

46
/// Pop an object from kwargs with default value
47
inline py::object
48
pop_cast(py::kwargs& kwargs, const std::string& key, const py::object& default_value)
265✔
49
{
50
  if (kwargs.contains(key.c_str()))
265✔
51
  {
52
    return kwargs.attr("pop")(key);
×
53
  }
54
  return default_value;
265✔
55
}
56

57
/// Pop an object from kwargs and raise error if the key is not found
58
inline py::object
59
pop_cast(py::kwargs& kwargs, const std::string& key)
768✔
60
{
61
  if (!kwargs.contains(key.c_str()))
768✔
62
  {
63
    throw std::runtime_error("Key \"" + key + "\" must be provided.\n");
×
64
  }
65
  return kwargs.attr("pop")(key);
1,536✔
66
}
67

68
/// Extract tuple of arguments
69
template <typename... Args>
70
std::tuple<Args...>
71
extract_args_tuple(py::kwargs& kwargs,
269✔
72
                   const std::vector<std::string>& required_keys,
73
                   const std::vector<std::pair<std::string, py::object>>& optional_keys =
74
                     std::vector<std::pair<std::string, py::object>>())
75
{
76
  // check size
77
  if (required_keys.size() + optional_keys.size() != sizeof...(Args))
269✔
78
  {
79
    throw std::runtime_error(
×
80
      "Mismatch number of arguments. "
81
      "This is a dev bug, please contact OpenSn developpers for this issue!");
82
  }
83
  // initialize retriever
84
  std::size_t index = 0;
269✔
85
  auto retriever = [&](auto& arg)
2,335✔
86
  {
87
    using ArgType = std::decay_t<decltype(arg)>;
88
    if (index < required_keys.size())
89
    {
90
      const std::string& key = required_keys[index];
91
      arg = pop_cast(kwargs, key).cast<ArgType>();
92
    }
93
    else
94
    {
95
      const auto& [key, default_val] = optional_keys[index - required_keys.size()];
96
      arg = pop_cast(kwargs, key, default_val).cast<ArgType>();
97
    }
98
    ++index;
99
  };
100
  // retrieve keys
101
  std::tuple<Args...> args;
269✔
102
  std::apply([&](auto&... args) { (retriever(args), ...); }, args);
538✔
103
  // check for orphan keys
104
  if (!kwargs.empty())
269✔
105
  {
106
    std::ostringstream err_log;
×
107
    err_log << "Unknown arguments(s):";
×
108
    for (const auto& item : kwargs)
×
109
    {
110
      std::string key = py::str(item.first);
×
111
      err_log << " \"" << key << "\"";
×
112
    }
113
    err_log << ".";
×
114
    throw std::runtime_error(err_log.str());
×
115
  }
×
116
  return args;
269✔
117
}
1,033✔
118

768✔
119
/**
768✔
120
 *  @brief Construct an object from kwargs
265✔
121
 *  @details This function template allows construction of a C++ object from Python keyword
265✔
122
 *  arguments (`py::kwargs`), with enforcement of required and optional arguments.
1,033✔
123
 *  @tparam T The target class type to construct.
124
 *  @tparam Args The constructor argument types of T.
125
 *  @param kwargs Python keyword arguments provided from a Pybind11 binding.
126
 *  @param required_keys List of required argument names (must appear in ``kwargs``).
127
 *  @param optional_keys List of optional arguments with default values (used if not found in
128
 *  ``kwargs``).
129
 *  @note This function is meant to replace the functionality of ``InputParameters``.
130
 *  @example
131
 *  // C++ class
132
 *  class Foo {
133
 *    public:
134
 *      Foo(int a, double b, const std::string& name, bool verbose = false);
135
 *  };
136
 *
137
 *  // Pybind11 constructor wrapper
138
 *  foo.def(
139
 *    py::init(
140
 *      [](py::kwargs& params) {
141
 *        const std::vector<std::string> required_keys = {"a", "b", "name"};
142
 *        const std::vector<std::pair<std::string, py::object>> optional_keys = {
143
 *          {"verbose", py::bool_(false)}
144
 *        };
145
 *        return construct_from_kwargs<Foo, int, double, std::string, bool>(params, required_keys,
146
 *                                                                          optional_keys);
147
 *      }
148
 *    ),
149
 *    R"(
150
 *    Construct ...
151
 *
152
 *    Parameters
153
 *    ----------
154
 *    a: int
155
 *        ...
156
 *    b: float
157
 *        ...
158
 *    name: str
159
 *        ...
160
 *    verbose: bool, default=False
161
 *        ...
162
 *    )"
163
 *  );
164
 */
165
template <class T, typename... Args>
166
std::shared_ptr<T>
167
construct_from_kwargs(py::kwargs& kwargs,
265✔
168
                      const std::vector<std::string>& required_keys,
169
                      const std::vector<std::pair<std::string, py::object>>& optional_keys =
170
                        std::vector<std::pair<std::string, py::object>>())
171
{
172
  std::tuple<Args...> args = extract_args_tuple<Args...>(kwargs, required_keys, optional_keys);
265✔
173
  return std::apply(
174
    [](auto&&... unpacked_args)
497✔
175
    { return std::make_shared<T>(std::forward<decltype(unpacked_args)>(unpacked_args)...); },
265✔
176
    args);
265✔
177
}
17✔
178

34✔
179
// Module wrappers
180

181
/// Wrap the context components of OpenSn.
182
void py_context(py::module& pyopensn);
183

184
/// Wrap the angular quadrature components of OpenSn.
185
void py_aquad(py::module& pyopensn);
186
void WrapQuadraturePointPhiTheta(py::module& aquad);
187
void WrapQuadrature(py::module& aquad);
188
void WrapProductQuadrature(py::module& aquad);
189
void WrapCurvilinearProductQuadrature(py::module& aquad);
190
void WrapSLDFESQuadrature(py::module& aquad);
191
void WrapLebedevQuadrature(py::module& aquad);
192

193
/// Wrap the field function components of OpenSn.
194
void py_ffunc(py::module& pyopensn);
195
void WrapFieldFunction(py::module& ffunc);
196
void WrapFieldFunctionGridBased(py::module& ffunc);
197
void WrapFieldFunctionInterpolation(py::module& ffunc);
198

199
/// Wrap the logical volume components of OpenSn.
200
void py_logvol(py::module& pyopensn);
201
void WrapLogicalVolume(py::module& logvol);
202

203
// Wrap the math components of OpenSn
204
void py_math(py::module& pyopensn);
205
void WrapYlm(py::module& math);
206
void WrapVector3(py::module& math);
207
void WrapFunctors(py::module& math);
208

209
/// Wrap the mesh components of OpenSn.
210
void py_mesh(py::module& pyopensn);
211
void WrapMesh(py::module& mesh);
212
void WrapMeshGenerator(py::module& mesh);
213
void WrapGraphPartitioner(py::module& mesh);
214

215
/// Wrap the response components of OpenSn.
216
void py_response(py::module& pyopensn);
217
void WrapResEval(py::module& response);
218

219
/// Wrap the settings components of OpenSn
220
void py_settings(py::module& pyopensn);
221

222
/// Wrap the solver components of OpenSn (unfinshed).
223
void py_solver(py::module& pyopensn);
224
void WrapProblem(py::module& slv);
225
void WrapSolver(py::module& slv);
226
void WrapLBS(py::module& slv);
227
void WrapSteadyState(py::module& slv);
228
void WrapNLKEigen(py::module& slv);
229
void WrapPIteration(py::module& slv);
230
void WrapDiscreteOrdinatesKEigenAcceleration(py::module& slv);
231

232
/// Wrap the source components of OpenSn.
233
void py_source(py::module& pyopensn);
234
void WrapPointSource(py::module& src);
235
void WrapVolumetricSource(py::module& src);
236

237
/// Wrap the cross section components of OpenSn.
238
void py_xs(py::module& pyopensn);
239
void WrapMultiGroupXS(py::module& xs);
240

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