Loading [MathJax]/extensions/tex2jax.js
OGS
ogs_mpl.cpp
Go to the documentation of this file.
1
10#include <pybind11/eigen.h>
11#include <pybind11/pybind11.h>
12#include <pybind11/stl.h>
13
14#include <range/v3/range/conversion.hpp>
15#include <range/v3/view/transform.hpp>
16
17#include "BaseLib/Logging.h"
21#include "MathLib/Point3d.h"
23
24namespace py = pybind11;
25
26using namespace MaterialPropertyLib;
27using namespace ParameterLib;
28
29namespace
30{
31// Convert NumPy array to Point3d if not None. This function is there to avoid
32// pulling the MeshLib::Point3d object into python, but use std::array (which
33// has all automatic conversions in pybind11).
34std::optional<MathLib::Point3d> pythonToSpatialPositionCoords(
35 py::object const& coordinates)
36{
37 if (coordinates.is_none())
38 {
39 return std::nullopt;
40 }
41 return std::make_optional<MathLib::Point3d>(
42 py::cast<std::array<double, 3>>(coordinates));
43}
44
45// Convert SpatialPositon to python array if coordinates are set. This function
46// is there to avoid pulling the MeshLib::Point3d object into python, but use
47// python arrays.
49{
50 auto const& opt_coords = pos.getCoordinates();
51 if (opt_coords)
52 {
53 return py::array_t<double>(3, opt_coords->data());
54 }
55 return py::none();
56}
57
58void bindSpatialPosition(py::module_& m)
59{
60 py::class_<SpatialPosition>(m, "SpatialPosition",
61 R"pbdoc(
62 Describes a spatial position within a mesh or domain.
63
64 A SpatialPosition may refer to a node (via node ID), an element (via element ID),
65 or a physical point in space (via coordinates). It is typically used when evaluating
66 material properties that depend on the spatial context within a simulation.
67
68 The position may be partially specified. For example:
69 - Only coordinates for geometric evaluation
70 - Only node ID for nodal properties
71 - Only element ID for element-wise values
72 - Or any combination of the above
73
74 The class is used as a parameter to property evaluations in the OGS material properties library.
75)pbdoc")
76 .def(py::init(
77 [](std::optional<std::size_t> node_id,
78 std::optional<std::size_t>
79 element_id,
80 py::object const& coordinates)
81 {
82 return SpatialPosition(
83 node_id, element_id,
85 }),
86 py::arg("node_id") = std::nullopt,
87 py::arg("element_id") = std::nullopt,
88 py::arg("coords") = py::none(),
89 R"pbdoc(
90 SpatialPosition(node_id=None, element_id=None, coords=None)
91
92 Parameters:
93 node_id (int, optional): Node ID
94 element_id (int, optional): Element ID
95 coords (array-like of 3 floats, optional): Coordinates
96 )pbdoc")
97
98 .def_property(
99 "node_id",
100 [](SpatialPosition const& pos) { return pos.getNodeID(); },
101 [](SpatialPosition& pos, std::size_t const id)
102 { pos.setNodeID(id); },
103 R"pbdoc(
104 Node ID of the spatial position.
105
106 This property can be read and set from Python. Setting to None is not supported.
107 )pbdoc")
108
109 .def_property(
110 "element_id",
111 [](SpatialPosition const& pos) { return pos.getElementID(); },
112 [](SpatialPosition& pos, std::size_t const id)
113 { pos.setElementID(id); },
114 R"pbdoc(
115 Element ID of the spatial position.
116
117 This property can be read and set from Python. Setting to None is not supported.
118 )pbdoc")
119
120 .def_property(
121 "coordinates",
123 [](SpatialPosition& pos, py::object const& coordinates)
124 {
125 pos.setCoordinates(
126 pythonToSpatialPositionCoords(coordinates).value());
127 },
128 R"pbdoc(
129 Coordinates of the spatial position as a 3-element array.
130
131 This property can be read and set from Python. Use a 3-element list, tuple,
132 or NumPy array. Setting to None is not supported.
133 )pbdoc")
134
135 .def(
136 "__repr__",
137 [](SpatialPosition const& pos)
138 {
139 auto const node_id =
140 pos.getNodeID() ? std::to_string(*pos.getNodeID()) : "None";
141 auto const element_id =
142 pos.getElementID() ? std::to_string(*pos.getElementID())
143 : "None";
144 auto const coords = spatialPositionCoordsToPython(pos);
145
146 return "<SpatialPosition(" + node_id + ", " + element_id +
147 ", " + py::str(coords).cast<std::string>() + ")>";
148 },
149 R"pbdoc(
150 Return string representation of the SpatialPosition.
151 )pbdoc");
152}
153
154void bindVariableArray(py::module_& m)
155{
156 py::class_<VariableArray>(m, "VariableArray")
157 .def(py::init<>())
158 .def_readwrite("capillary_pressure", &VariableArray::capillary_pressure)
159 .def_readwrite("concentration", &VariableArray::concentration)
160 .def_readwrite("deformation_gradient",
162 .def_readwrite("density", &VariableArray::density)
163 .def_readwrite("effective_pore_pressure",
165 .def_readwrite("enthalpy", &VariableArray::enthalpy)
166 .def_readwrite("enthalpy_of_evaporation",
168 .def_readwrite("equivalent_plastic_strain",
170 .def_readwrite("fracture_aperture", &VariableArray::fracture_aperture)
171 .def_readwrite("grain_compressibility",
173 .def_readwrite("liquid_phase_pressure",
175 .def_readwrite("liquid_saturation", &VariableArray::liquid_saturation)
176 .def_readwrite("mechanical_strain", &VariableArray::mechanical_strain)
177 .def_readwrite("molar_mass", &VariableArray::molar_mass)
178 .def_readwrite("molar_mass_derivative",
180 .def_readwrite("molar_fraction", &VariableArray::molar_fraction)
181 .def_readwrite("gas_phase_pressure", &VariableArray::gas_phase_pressure)
182 .def_readwrite("porosity", &VariableArray::porosity)
183 .def_readwrite("solid_grain_pressure",
185 .def_readwrite("stress", &VariableArray::stress)
186 .def_readwrite("temperature", &VariableArray::temperature)
187 .def_readwrite("total_strain", &VariableArray::total_strain)
188 .def_readwrite("total_stress", &VariableArray::total_stress)
189 .def_readwrite("transport_porosity", &VariableArray::transport_porosity)
190 .def_readwrite("vapour_pressure", &VariableArray::vapour_pressure)
191 .def_readwrite("volumetric_strain", &VariableArray::volumetric_strain);
192}
193
194void bindVariableEnum(py::module_& m)
195{
196 py::enum_<Variable>(m, "Variable")
197 .value("capillary_pressure", Variable::capillary_pressure)
198 .value("concentration", Variable::concentration)
199 .value("deformation_gradient", Variable::deformation_gradient)
200 .value("density", Variable::density)
201 .value("effective_pore_pressure", Variable::effective_pore_pressure)
202 .value("enthalpy", Variable::enthalpy)
203 .value("enthalpy_of_evaporation", Variable::enthalpy_of_evaporation)
204 .value("equivalent_plastic_strain", Variable::equivalent_plastic_strain)
205 .value("fracture_aperture", Variable::fracture_aperture)
206 .value("grain_compressibility", Variable::grain_compressibility)
207 .value("liquid_phase_pressure", Variable::liquid_phase_pressure)
208 .value("liquid_saturation", Variable::liquid_saturation)
209 .value("mechanical_strain", Variable::mechanical_strain)
210 .value("molar_mass", Variable::molar_mass)
211 .value("molar_mass_derivative", Variable::molar_mass_derivative)
212 .value("molar_fraction", Variable::molar_fraction)
213 .value("gas_phase_pressure", Variable::gas_phase_pressure)
214 .value("porosity", Variable::porosity)
215 .value("solid_grain_pressure", Variable::solid_grain_pressure)
216 .value("stress", Variable::stress)
217 .value("temperature", Variable::temperature)
218 .value("total_strain", Variable::total_strain)
219 .value("total_stress", Variable::total_stress)
220 .value("transport_porosity", Variable::transport_porosity)
221 .value("vapour_pressure", Variable::vapour_pressure)
222 .value("volumetric_strain", Variable::volumetric_strain)
223 .export_values();
224}
225
226void bindProperty(py::module_& m)
227{
228 py::class_<Property>(m, "Property", R"pbdoc(
229 Base class for material properties.
230 )pbdoc")
231 .def(
232 "value",
233 [](const Property& p, const VariableArray& va,
234 const SpatialPosition& pos, double t, double dt)
235 { return p.value(va, pos, t, dt); },
236 py::arg("variable_array"),
237 py::arg("pos"),
238 py::arg("t"),
239 py::arg("dt"),
240 R"pbdoc(
241 Evaluate the property value.
242
243 Parameters:
244 variable_array: Current time step values.
245 pos: Spatial position.
246 t: Current time.
247 dt: Time step size.
248 )pbdoc")
249
250 .def(
251 "value",
252 [](const Property& p, const VariableArray& va,
253 const VariableArray& vap, const SpatialPosition& pos, double t,
254 double dt) { return p.value(va, vap, pos, t, dt); },
255 py::arg("variable_array"),
256 py::arg("variable_array_prev"),
257 py::arg("pos"),
258 py::arg("t"),
259 py::arg("dt"),
260 R"pbdoc(
261 Evaluate the property value with previous time step data.
262
263 Parameters:
264 variable_array: Current time step values.
265 variable_array_prev: Previous time step values.
266 pos: Spatial position.
267 t: Current time.
268 dt: Time step size.
269 )pbdoc")
270
271 .def(
272 "dValue",
273 [](const Property& p, const VariableArray& va,
274 const VariableArray& vap, Variable var,
275 const SpatialPosition& pos, double t, double dt)
276 { return p.dValue(va, vap, var, pos, t, dt); },
277 py::arg("variable_array"),
278 py::arg("variable_array_prev"),
279 py::arg("variable"),
280 py::arg("pos"),
281 py::arg("t"),
282 py::arg("dt"),
283 R"pbdoc(
284 Evaluate the derivative of the property with respect to a variable,
285 using previous time step data.
286
287 Parameters:
288 variable_array: Current time step values.
289 variable_array_prev: Previous time step values.
290 variable: Variable to differentiate with respect to.
291 pos: Spatial position.
292 t: Current time.
293 dt: Time step size.
294 )pbdoc")
295
296 .def(
297 "dValue",
298 [](const Property& p, const VariableArray& va, Variable var,
299 const SpatialPosition& pos, double t, double dt)
300 { return p.dValue(va, var, pos, t, dt); },
301 py::arg("variable_array"),
302 py::arg("variable"),
303 py::arg("pos"),
304 py::arg("t"),
305 py::arg("dt"),
306 R"pbdoc(
307 Evaluate the derivative of the property with respect to a variable.
308
309 Parameters:
310 variable_array: Current time step values.
311 variable: Variable to differentiate with respect to.
312 pos: Spatial position.
313 t: Current time.
314 dt: Time step size.
315 )pbdoc");
316}
317
318void bindConstant(py::module_& m)
319{
320 py::class_<Constant, Property>(m, "Constant", R"pbdoc(
321 Constant property with a fixed value.
322 )pbdoc")
323 .def(py::init<std::string, PropertyDataType>(),
324 py::arg("name"),
325 py::arg("value"),
326 R"pbdoc(
327 Construct a Constant property.
328
329 Parameters:
330 name: Name of the property.
331 value: Constant value.
332 )pbdoc");
333}
334
335void bindLinear(py::module_& m)
336{
337 py::class_<Linear, Property>(m, "Linear", R"pbdoc(
338 Linearly interpolated property dependent on independent variables.
339 )pbdoc")
340 .def(py::init(
341 [](std::string name, PropertyDataType reference_value,
342 std::vector<std::tuple<Variable, VariableType,
343 VariableType>> const& ivs)
344 {
345 auto makeIV = [](std::tuple<Variable, VariableType,
346 VariableType> const& iv)
347 { return std::make_from_tuple<IndependentVariable>(iv); };
348
349 auto independent_variables =
350 ivs | ranges::views::transform(makeIV) |
351 ranges::to<std::vector>();
352 return std::make_unique<Linear>(name, reference_value,
353 independent_variables);
354 }),
355 py::arg("name"),
356 py::arg("reference_value"),
357 py::arg("independent_variables"),
358 R"pbdoc(
359 Construct a Linear property.
360
361 Parameters:
362 name: Name of the property.
363 reference_value: Base property value.
364 independent_variables: List of tuples (variable, reference condition, slope), each defining a linear dependency on a variable.
365 )pbdoc");
366}
367} // namespace
368
370{
371 m.attr("__name__") = "ogs.mpl";
372 m.doc() = "pybind11 ogs MPL bindings";
373
377 bindProperty(m);
378 bindConstant(m);
379 bindLinear(m);
380}
Definition of the Point3d class.
DeformationGradient deformation_gradient
std::optional< std::size_t > getNodeID() const
void setNodeID(std::size_t node_id)
std::optional< std::size_t > getElementID() const
void setCoordinates(MathLib::Point3d const &coordinates)
void setElementID(std::size_t element_id)
std::optional< MathLib::Point3d > const getCoordinates() const
std::variant< std::monostate, double, Eigen::Vector< double, 4 >, Eigen::Vector< double, 5 >, Eigen::Vector< double, 6 >, Eigen::Vector< double, 9 > > VariableType
std::variant< double, Eigen::Matrix< double, 2, 1 >, Eigen::Matrix< double, 3, 1 >, Eigen::Matrix< double, 2, 2 >, Eigen::Matrix< double, 3, 3 >, Eigen::Matrix< double, 4, 1 >, Eigen::Matrix< double, 6, 1 >, Eigen::MatrixXd > PropertyDataType
Definition Property.h:31
void bindSpatialPosition(py::module_ &m)
Definition ogs_mpl.cpp:58
void bindConstant(py::module_ &m)
Definition ogs_mpl.cpp:245
void bindLinear(py::module_ &m)
Definition ogs_mpl.cpp:256
void bindVariableArray(py::module_ &m)
Definition ogs_mpl.cpp:118
void bindVariableEnum(py::module_ &m)
Definition ogs_mpl.cpp:158
std::optional< MathLib::Point3d > pythonToSpatialPositionCoords(py::object const &coordinates)
Definition ogs_mpl.cpp:34
py::object spatialPositionCoordsToPython(SpatialPosition const &pos)
Definition ogs_mpl.cpp:48
void bindProperty(py::module_ &m)
Definition ogs_mpl.cpp:190
PYBIND11_MODULE(mpl, m)
Definition ogs_mpl.cpp:369