src/python_access/function.rs

changeset 1
a4137aedcb3a
equal deleted inserted replaced
0:7ec1cfe19a24 1:a4137aedcb3a
1 /*!
2 Conversions between [`DolfinxPyFunction_f64`] and `dolfinx.fem.Function` in Python.
3 */
4
5 use crate::dolfinx_access::ffi;
6 use crate::dolfinx_access::DolfinxPyFunction_f64;
7 use pyo3::conversion::FromPyObject;
8 use pyo3::exceptions::PyException;
9 use pyo3::prelude::*;
10
11 macro_rules! py_bail {
12 ($msg:literal $(,)?) => {
13 return Err(PyException::new_err(format!($msg)))
14 };
15 ($err:expr $(,)?) => {
16 return Err(PyException::new_err(format!($err)))
17 };
18 ($fmt:expr, $($arg:tt)*) => {
19 return Err(PyException::new_err(format!($fmt, $($arg)*)))
20 };
21 }
22
23 impl<'a, 'py, const N: u32, const O: u32, const D: u32> FromPyObject<'a, 'py>
24 for DolfinxPyFunction_f64<'py, N, O, D>
25 {
26 type Error = PyErr;
27
28 fn extract(u_: Borrowed<'a, 'py, PyAny>) -> PyResult<Self> {
29 // We maintain our reference-counted copy
30 let u = u_.to_owned();
31 // The "_cpp_object" attribute of a Python Dolfinx Function points to the C++ instance
32 let u_cpp = u.getattr("_cpp_object")?;
33 let cxx = unsafe { ffi::cast_mut_Function_f64(u_cpp.as_ptr() as *mut ffi::PyObject) }
34 .or_else(|err| py_bail!("CXX cast error: {}", err))?;
35 let info = unsafe { ffi::info_Function_f64(cxx) };
36 if !info.triangular_mesh {
37 py_bail!("Triangular mesh required")
38 }
39 if info.order < O {
40 py_bail!("Insufficient order")
41 }
42 if info.codomain_dim != D {
43 py_bail!("Codomain of invalid size")
44 }
45 if info.domain_dim != N {
46 py_bail!("Domain of invalid size")
47 }
48 DolfinxPyFunction_f64::new_prechecked(u, cxx)
49 }
50 }
51
52 // TODO: should probably use internal mutability to avoid just supporting mut references.
53 impl<'a, 'py, const N: u32, const O: u32, const D: u32> IntoPyObject<'py>
54 for &'a mut DolfinxPyFunction_f64<'py, N, O, D>
55 where
56 'py: 'a,
57 {
58 type Target = PyAny;
59 type Error = PyErr;
60 type Output = pyo3::Borrowed<'a, 'py, Self::Target>;
61
62 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
63 self._into_py_ref(py)
64 }
65 }
66
67 impl<'py, const N: u32, const O: u32, const D: u32> IntoPyObject<'py>
68 for DolfinxPyFunction_f64<'py, N, O, D>
69 {
70 type Target = PyAny;
71 type Error = PyErr;
72 type Output = pyo3::Bound<'py, Self::Target>;
73
74 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
75 self._into_py(py)
76 }
77 }

mercurial