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