--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.rs Thu Feb 26 09:32:12 2026 -0500 @@ -0,0 +1,165 @@ +/*! +TODO: include README here. +*/ + +#![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; + +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")))), + )*]}; +} + +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<()> { + // 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 = "multiple" +mpi4py.rc.threads = True + +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) +// }