src/main.rs

changeset 1
a4137aedcb3a
child 3
c3a4f4bb87f7
--- /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)
+// }

mercurial