| |
1 /*! |
| |
2 TODO: include README here. |
| |
3 */ |
| |
4 |
| |
5 #![feature(maybe_uninit_array_assume_init)] |
| |
6 #![feature(iterator_try_collect)] |
| |
7 #![feature(once_cell_try)] |
| |
8 // We use unicode. We would like to use much more of it than Rust allows. |
| |
9 // Live with it. Embrace it. |
| |
10 #![allow(uncommon_codepoints)] |
| |
11 #![allow(mixed_script_confusables)] |
| |
12 #![allow(confusable_idents)] |
| |
13 |
| |
14 use alg_tools::error::DynResult; |
| |
15 use log::debug; |
| |
16 use measures::python::pymod as pymod_measures; |
| |
17 use pointsource_algs::common_main; |
| |
18 use pyo3::append_to_inittab; |
| |
19 use pyo3::ffi::c_str; |
| |
20 use pyo3::prelude::*; |
| |
21 use std::ffi::CStr; |
| |
22 |
| |
23 mod dolfinx_access; |
| |
24 mod experiments; |
| |
25 mod python_access; |
| |
26 |
| |
27 use experiments::Experiments; |
| |
28 use python_access::pymod_pointsource_pde; |
| |
29 |
| |
30 macro_rules! pymods { |
| |
31 [$($modname:expr),*] => {&[$( |
| |
32 (c_str!(concat!("pointsource_pde.", $modname)), |
| |
33 c_str!(concat!("src/", $modname, ".py")), |
| |
34 c_str!(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/", $modname, ".py")))), |
| |
35 )*]}; |
| |
36 } |
| |
37 |
| |
38 const PY_MODULES: &[(&CStr, &CStr, &CStr)] = pymods![ |
| |
39 "dolfinx_extras", |
| |
40 "compose", |
| |
41 "measure", |
| |
42 "quadratic_dataterm", |
| |
43 "convection_diffusion", |
| |
44 "laser_sampling", |
| |
45 "full_sampling" |
| |
46 ]; |
| |
47 |
| |
48 /// The entry point for the program. |
| |
49 pub fn main() -> DynResult<()> { |
| |
50 // Initialise logging |
| |
51 colog::init(); |
| |
52 |
| |
53 debug!("Appending Rust-side Python modules to inittab"); |
| |
54 |
| |
55 // Register the C++ module in Pythong. CURRENTLY NOT USED. |
| |
56 // Can't use DynResult above and ? here to get traces from Python. |
| |
57 dolfinx_access::register_python_ffi().unwrap(); |
| |
58 append_to_inittab!(pymod_measures); |
| |
59 append_to_inittab!(pymod_pointsource_pde); |
| |
60 |
| |
61 debug!("Initialising python"); |
| |
62 |
| |
63 // Initialise Python. |
| |
64 Python::initialize(); |
| |
65 |
| |
66 debug!("Loading Python modules from embedded source files"); |
| |
67 |
| |
68 // Load modules |
| |
69 Python::attach(|py| { |
| |
70 // Verify that there's no attempt to use MPI. |
| |
71 py.run( |
| |
72 c_str!( |
| |
73 r#" |
| |
74 import mpi4py |
| |
75 |
| |
76 mpi4py.rc.initialize = False # do not initialize MPI automatically |
| |
77 mpi4py.rc.thread_level = "multiple" |
| |
78 mpi4py.rc.threads = True |
| |
79 |
| |
80 from mpi4py import MPI |
| |
81 |
| |
82 MPI.Init() |
| |
83 size = MPI.COMM_SELF.Get_size() |
| |
84 if size != 1: |
| |
85 raise RuntimeError("MPI_COMM_SELF size must be 1, but is %d" % size) |
| |
86 size = MPI.COMM_WORLD.Get_size() |
| |
87 if size != 1: |
| |
88 raise RuntimeError("MPI_COMM_WORLD size must be 1, but is %d" % size) |
| |
89 "# |
| |
90 ), |
| |
91 None, |
| |
92 None, |
| |
93 )?; |
| |
94 |
| |
95 // FIXME: this is weird, besides registering in [`dolfinx_access::register_python_ffí`], |
| |
96 // we need to import our module into Python, once we have the GIL or otherwise |
| |
97 // nanobind::type<Function_f64>() will SIGSEGV. |
| |
98 let _dolfinx_access = PyModule::import(py, "dolfinx_access")?; |
| |
99 |
| |
100 //let _pointsource_pde = python_access::register_module(py); |
| |
101 |
| |
102 for &(modname, filename, filecontents) in PY_MODULES { |
| |
103 debug!("… Loading {}", modname.to_string_lossy()); |
| |
104 PyModule::from_code(py, filecontents, filename, modname)?; |
| |
105 } |
| |
106 |
| |
107 Ok::<_, PyErr>(()) |
| |
108 })?; |
| |
109 |
| |
110 debug!("Entering pointsource_algs::common_main"); |
| |
111 |
| |
112 common_main::<Experiments>() |
| |
113 } |
| |
114 |
| |
115 /* |
| |
116 fn py_main<'py>(py: Python<'py>, access_points: &PythonAccessPoints) -> PyResult<()> { |
| |
117 let main = PyModule::import(py, "__main__")?; |
| |
118 |
| |
119 //let fp = u_py.getattr("_V")?; |
| |
120 let mut u: DolfinxPyFunction_f64<2, 2, 1> = main.getattr("u")?.extract()?; |
| |
121 |
| |
122 let res = u.minimise(0.0, 0); |
| |
123 println!("min : {res:?}"); |
| |
124 |
| |
125 let resx = u.maximise(0.0, 0); |
| |
126 println!("max : {resx:?}"); |
| |
127 |
| |
128 let res2 = u.apply(Loc([0.5, 0.5])); |
| |
129 println!("apply : {res2:?}"); |
| |
130 |
| |
131 let res3 = u.differential(Loc([0.5, 0.5])); |
| |
132 println!("diff : {res3:?}"); |
| |
133 |
| |
134 // let dolfinx_fem = PyModule::import(py, "dolfinx.fem")?; |
| |
135 // let d_function = dolfinx_fem.getattr("Function")?; |
| |
136 // let d_function_new = d_function.getattr("__new__")?; |
| |
137 // let f = d_function_new.call1((d_function, fp))?; |
| |
138 |
| |
139 let mut u10 = &u * 10.0; |
| |
140 let obj = u10.into_pyobject(py)?; |
| |
141 |
| |
142 let locals = PyDict::new(py); |
| |
143 locals.set_item("obj", obj)?; |
| |
144 py.run( |
| |
145 c_str!( |
| |
146 "\ |
| |
147 import numpy as np |
| |
148 print(\"10 * min array \", np.min(obj.x.array)) |
| |
149 print(\"10 * max array \", np.max(obj.x.array))" |
| |
150 ), |
| |
151 None, |
| |
152 Some(&locals), |
| |
153 )?; |
| |
154 |
| |
155 Ok(()) |
| |
156 } |
| |
157 */ |
| |
158 |
| |
159 // fn get_dolfinx_function_type_object(py: Python<'_>) -> PyResult<*mut pyo3::ffi::PyTypeObject> { |
| |
160 // // Import the module and get the class |
| |
161 // let fem = py.import("dolfinx.fem.function")?; |
| |
162 // let func_class: Bound<'_, pyo3::types::PyType> = fem.getattr("Function")?.downcast_into()?; |
| |
163 // // Convert to raw pointer |
| |
164 // Ok(func_class.as_type_ptr() as *mut pyo3::ffi::PyTypeObject) |
| |
165 // } |