Fri, 16 Jan 2026 19:41:32 -0500
pointsource_algs step length estimation support
/*! Conversions between [`DolfinxPyFunction_f64`] and `dolfinx.fem.Function` in Python. */ use crate::dolfinx_access::ffi; use crate::dolfinx_access::DolfinxPyFunction_f64; use pyo3::conversion::FromPyObject; use pyo3::exceptions::PyException; use pyo3::prelude::*; macro_rules! py_bail { ($msg:literal $(,)?) => { return Err(PyException::new_err(format!($msg))) }; ($err:expr $(,)?) => { return Err(PyException::new_err(format!($err))) }; ($fmt:expr, $($arg:tt)*) => { return Err(PyException::new_err(format!($fmt, $($arg)*))) }; } impl<'a, 'py, const N: u32, const O: u32, const D: u32> FromPyObject<'a, 'py> for DolfinxPyFunction_f64<'py, N, O, D> { type Error = PyErr; fn extract(u_: Borrowed<'a, 'py, PyAny>) -> PyResult<Self> { // We maintain our reference-counted copy let u = u_.to_owned(); // The "_cpp_object" attribute of a Python Dolfinx Function points to the C++ instance let u_cpp = u.getattr("_cpp_object")?; let cxx = unsafe { ffi::cast_mut_Function_f64(u_cpp.as_ptr() as *mut ffi::PyObject) } .or_else(|err| py_bail!("CXX cast error: {}", err))?; let info = unsafe { ffi::info_Function_f64(cxx) }; if !info.triangular_mesh { py_bail!("Triangular mesh required") } if info.order < O { py_bail!("Insufficient order") } if info.codomain_dim != D { py_bail!("Codomain of invalid size") } if info.domain_dim != N { py_bail!("Domain of invalid size") } DolfinxPyFunction_f64::new_prechecked(u, cxx) } } // TODO: should probably use internal mutability to avoid just supporting mut references. impl<'a, 'py, const N: u32, const O: u32, const D: u32> IntoPyObject<'py> for &'a mut DolfinxPyFunction_f64<'py, N, O, D> where 'py: 'a, { type Target = PyAny; type Error = PyErr; type Output = pyo3::Borrowed<'a, 'py, Self::Target>; fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> { self._into_py_ref(py) } } impl<'py, const N: u32, const O: u32, const D: u32> IntoPyObject<'py> for DolfinxPyFunction_f64<'py, N, O, D> { type Target = PyAny; type Error = PyErr; type Output = pyo3::Bound<'py, Self::Target>; fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> { self._into_py(py) } }