Tue, 12 May 2026 20:44:45 -0500
README arXiv link
// The main documentation is in README.md #![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))] #![feature(maybe_uninit_array_assume_init)] #![feature(iterator_try_collect)] #![feature(once_cell_try)] // We use unicode. We would like to use much more of it than Rust allows. // Live with it. Embrace it. #![allow(uncommon_codepoints)] #![allow(mixed_script_confusables)] #![allow(confusable_idents)] use alg_tools::error::DynResult; use log::debug; use measures::python::pymod as pymod_measures; use pointsource_algs::common_main; use pyo3::append_to_inittab; use pyo3::ffi::c_str; use pyo3::prelude::*; use std::ffi::CStr; mod dolfinx_access; mod experiments; mod python_access; use experiments::Experiments; use python_access::pymod_pointsource_pde; /// Helper for construct the list Python modules that we include as strings from `.py` files. macro_rules! pymods { [$($modname:expr),*] => {&[$( (c_str!(concat!("pointsource_pde.", $modname)), c_str!(concat!("src/", $modname, ".py")), c_str!(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/", $modname, ".py")))), )*]}; } /// List of Python modules that we include as strings from `.py` files. const PY_MODULES: &[(&CStr, &CStr, &CStr)] = pymods![ "dolfinx_extras", "compose", "measure", "quadratic_dataterm", "convection_diffusion", "laser_sampling", "full_sampling" ]; /// The entry point for the program. pub fn main() -> DynResult<()> { unsafe { // "#(/€"#€/("#€(/ OpenMPI and Fenics junk, don't do your obsolete “single-program multiple-data, with no controller at all” threading. std::env::set_var("OMP_NUM_THREADS", "1"); } // Initialise logging colog::init(); debug!("Appending Rust-side Python modules to inittab"); // Register the C++ module in Pythong. CURRENTLY NOT USED. // Can't use DynResult above and ? here to get traces from Python. dolfinx_access::register_python_ffi().unwrap(); append_to_inittab!(pymod_measures); append_to_inittab!(pymod_pointsource_pde); debug!("Initialising python"); // Initialise Python. Python::initialize(); debug!("Loading Python modules from embedded source files"); // Load modules Python::attach(|py| { // Verify that there's no attempt to use MPI. py.run( c_str!( r#" import mpi4py mpi4py.rc.initialize = False # do not initialize MPI automatically mpi4py.rc.thread_level = "serialized" mpi4py.rc.threads = False from mpi4py import MPI MPI.Init() size = MPI.COMM_SELF.Get_size() if size != 1: raise RuntimeError("MPI_COMM_SELF size must be 1, but is %d" % size) size = MPI.COMM_WORLD.Get_size() if size != 1: raise RuntimeError("MPI_COMM_WORLD size must be 1, but is %d" % size) "# ), None, None, )?; // FIXME: this is weird, besides registering in [`dolfinx_access::register_python_ffí`], // we need to import our module into Python, once we have the GIL or otherwise // nanobind::type<Function_f64>() will SIGSEGV. let _dolfinx_access = PyModule::import(py, "dolfinx_access")?; //let _pointsource_pde = python_access::register_module(py); for &(modname, filename, filecontents) in PY_MODULES { debug!("… Loading {}", modname.to_string_lossy()); PyModule::from_code(py, filecontents, filename, modname)?; } Ok::<_, PyErr>(()) })?; debug!("Entering pointsource_algs::common_main"); common_main::<Experiments>() } /* fn py_main<'py>(py: Python<'py>, access_points: &PythonAccessPoints) -> PyResult<()> { let main = PyModule::import(py, "__main__")?; //let fp = u_py.getattr("_V")?; let mut u: DolfinxPyFunction_f64<2, 2, 1> = main.getattr("u")?.extract()?; let res = u.minimise(0.0, 0); println!("min : {res:?}"); let resx = u.maximise(0.0, 0); println!("max : {resx:?}"); let res2 = u.apply(Loc([0.5, 0.5])); println!("apply : {res2:?}"); let res3 = u.differential(Loc([0.5, 0.5])); println!("diff : {res3:?}"); // let dolfinx_fem = PyModule::import(py, "dolfinx.fem")?; // let d_function = dolfinx_fem.getattr("Function")?; // let d_function_new = d_function.getattr("__new__")?; // let f = d_function_new.call1((d_function, fp))?; let mut u10 = &u * 10.0; let obj = u10.into_pyobject(py)?; let locals = PyDict::new(py); locals.set_item("obj", obj)?; py.run( c_str!( "\ import numpy as np print(\"10 * min array \", np.min(obj.x.array)) print(\"10 * max array \", np.max(obj.x.array))" ), None, Some(&locals), )?; Ok(()) } */ // fn get_dolfinx_function_type_object(py: Python<'_>) -> PyResult<*mut pyo3::ffi::PyTypeObject> { // // Import the module and get the class // let fem = py.import("dolfinx.fem.function")?; // let func_class: Bound<'_, pyo3::types::PyType> = fem.getattr("Function")?.downcast_into()?; // // Convert to raw pointer // Ok(func_class.as_type_ptr() as *mut pyo3::ffi::PyTypeObject) // }