27#include <pybind11/functional.h>
28#include <pybind11/numpy.h>
32 template<
class Tvec,
class Tgr
idVec>
33 void add_instance(py::module &m, std::string name_config, std::string name_model) {
35 using Tscal = shambase::VecComponent<Tvec>;
36 using Tgridscal = shambase::VecComponent<TgridVec>;
39 using TConfig =
typename T::Solver::Config;
40 using TAnalysisSodTube = shammodels::basegodunov::modules::AnalysisSodTube<Tvec, TgridVec>;
42 shamlog_debug_ln(
"[Py]",
"registering class :", name_config,
typeid(T).name());
43 shamlog_debug_ln(
"[Py]",
"registering class :", name_model,
typeid(T).name());
45 py::class_<TConfig> config_cls(m, name_config.c_str());
47 shammodels::common::add_json_defs<TConfig>(config_cls);
52 [](TConfig &self, Tscal scale_factor) {
53 self.grid_coord_to_pos_fact = scale_factor;
57 [](TConfig &self, Tscal Csafe) {
62 [](TConfig &self, Tscal eos_gamma) {
63 self.set_eos_gamma(eos_gamma);
66 "set_riemann_solver_hll",
68 self.riemann_config = HLL;
71 "set_riemann_solver_hllc",
73 self.riemann_config = HLLC;
76 "set_riemann_solver_rusanov",
78 self.riemann_config = Rusanov;
83 self.slope_config = None;
86 "set_slope_lim_vanleer_f",
88 self.slope_config = VanLeer_f;
91 "set_slope_lim_vanleer_std",
93 self.slope_config = VanLeer_std;
96 "set_slope_lim_vanleer_sym",
98 self.slope_config = VanLeer_sym;
101 "set_slope_lim_minmod",
103 self.slope_config = Minmod;
106 "set_scheduler_config",
107 [](TConfig &self,
u64 split_crit,
u64 merge_crit) {
108 self.scheduler_conf.split_load_value = split_crit;
109 self.scheduler_conf.merge_load_value = merge_crit;
112 py::arg(
"split_load_value"),
113 py::arg(
"merge_load_value"))
115 "set_face_time_interpolation",
116 [](TConfig &self,
bool face_time_interpolate) {
117 self.face_half_time_interpolation = face_time_interpolate;
120 "set_boundary_condition",
121 [](TConfig &self,
const std::string &axis,
const std::string &bc_type) {
122 BCConfig::GhostType ghost_type;
123 if (bc_type ==
"periodic") {
124 ghost_type = BCConfig::GhostType::Periodic;
125 }
else if (bc_type ==
"reflective") {
126 ghost_type = BCConfig::GhostType::Reflective;
127 }
else if (bc_type ==
"outflow") {
128 ghost_type = BCConfig::GhostType::Outflow;
130 throw std::invalid_argument(
131 "Unsupported boundary condition type: " + bc_type);
135 self.bc_config.set_x(ghost_type);
136 }
else if (axis ==
"y") {
137 self.bc_config.set_y(ghost_type);
138 }
else if (axis ==
"z") {
139 self.bc_config.set_z(ghost_type);
141 throw std::invalid_argument(
"Unsupported axis: " + axis);
147 "set_dust_mode_dhll",
148 [](TConfig &self,
u32 ndust) {
149 self.dust_config = {
DHLL, ndust};
153 [](TConfig &self,
u32 ndust) {
154 self.dust_config = {
HB, ndust};
157 "set_dust_mode_none",
159 self.dust_config = {
NoDust, 0};
163 [](TConfig &self,
f32 alpha_values) {
164 return self.set_alphas_static(alpha_values);
167 "set_drag_mode_no_drag",
169 self.drag_config.drag_solver_config = NoDrag;
170 self.drag_config.enable_frictional_heating =
false;
173 "set_drag_mode_irk1",
174 [](TConfig &self,
bool frictional_status) {
175 self.drag_config.drag_solver_config = IRK1;
176 self.drag_config.enable_frictional_heating = frictional_status;
179 "set_drag_mode_irk2",
180 [](TConfig &self,
bool frictional_status) {
181 self.drag_config.drag_solver_config = IRK2;
182 self.drag_config.enable_frictional_heating = frictional_status;
185 "set_drag_mode_expo",
186 [](TConfig &self,
bool frictional_status) {
187 self.drag_config.drag_solver_config = EXPO;
188 self.drag_config.enable_frictional_heating = frictional_status;
193 self.amr_mode.set_refine_none();
196 "set_amr_mode_density_based",
197 [](TConfig &self, Tscal crit_mass) {
198 self.amr_mode.set_refine_density_based(crit_mass);
201 py::arg(
"crit_mass"))
203 "set_amr_mode_pseudo_gradient_based",
204 [](TConfig &self, Tscal error_min, Tscal error_max) {
205 self.amr_mode.set_refine_pseudo_gradient_based(error_min, error_max);
208 py::arg(
"error_min"),
209 py::arg(
"error_max"))
211 "set_amr_mode_jeans_length_based",
212 [](TConfig &self,
u32 N_jeans, Tscal T_init) {
213 self.amr_mode.set_refine_jeans_length_based(N_jeans, T_init);
219 "set_amr_mode_shear_based",
220 [](TConfig &self, Tscal threshold) {
221 self.amr_mode.set_refine_shear_based(threshold);
224 py::arg(
"Threshold"))
227 [](TConfig &self,
bool use_old_amr) {
228 self.amr_mode.old_amr = use_old_amr;
231 "set_gravity_mode_no_gravity",
233 self.gravity_config.gravity_mode = NoGravity;
236 "set_gravity_mode_cg",
238 self.gravity_config.gravity_mode = CG;
241 "set_gravity_mode_pcg",
243 self.gravity_config.gravity_mode = PCG;
246 "set_gravity_mode_bicgstab",
248 self.gravity_config.gravity_mode = BICGSTAB;
250 .def(
"set_npscal_gas", [](TConfig &self,
u32 npscal_gas) {
251 self.npscal_gas_config.npscal_gas = npscal_gas;
254 std::string sod_tube_analysis_name = name_model +
"_AnalysisSodTube";
255 py::class_<TAnalysisSodTube>(m, sod_tube_analysis_name.c_str())
256 .def(
"compute_L2_dist", [](TAnalysisSodTube &self) -> std::tuple<Tscal, Tvec, Tscal> {
257 auto ret = self.compute_L2_dist();
258 return {ret.rho, ret.v, ret.P};
261 py::class_<T>(m, name_model.c_str())
262 .def(
"init", &T::init)
263 .def(
"init_scheduler", &T::init_scheduler)
264 .def(
"make_base_grid", &T::make_base_grid)
265 .def(
"dump_vtk", &T::dump_vtk)
266 .def(
"dump", &T::dump)
267 .def(
"load_from_dump", &T::load_from_dump)
268 .def(
"evolve_once_override_time", &T::evolve_once_time_expl)
269 .def(
"evolve_once", &T::evolve_once)
272 [](T &self,
f64 target_time,
i32 niter_max) {
273 return self.evolve_until(target_time, niter_max);
275 py::arg(
"target_time"),
277 py::arg(
"niter_max") = -1)
278 .def(
"timestep", &T::timestep)
280 "set_field_value_lambda_f64",
282 std::string field_name,
283 const std::function<
f64(Tvec, Tvec)> pos_to_val,
285 return self.template set_field_value_lambda<f64>(
286 field_name, pos_to_val, offset);
288 py::arg(
"field_name"),
289 py::arg(
"pos_to_val"),
290 py::arg(
"offset") = 0)
292 "set_field_value_lambda_f64_3",
294 std::string field_name,
295 const std::function<f64_3(Tvec, Tvec)> pos_to_val,
297 return self.template set_field_value_lambda<f64_3>(
298 field_name, pos_to_val, offset);
300 py::arg(
"field_name"),
301 py::arg(
"pos_to_val"),
302 py::arg(
"offset") = 0)
304 "gen_default_config",
305 [](T &self) -> TConfig {
310 [](T &self, TConfig cfg) {
311 if (self.ctx.is_scheduler_initialized()) {
313 "Cannot change solver config after scheduler is initialized");
316 self.solver.solver_config = cfg;
320 [](T &self, std::pair<TgridVec, TgridVec> block_coord,
u32 cell_local_id) {
321 return self.get_cell_coords(block_coord, cell_local_id);
324 "make_analysis_sodtube",
326 shamphys::SodTube sod,
332 return std::make_unique<TAnalysisSodTube>(
334 self.solver.solver_config,
349 "get_solver_dot_graph",
356 [](T &self, std::string name, std::string field_type, std::vector<Tvec> positions)
357 -> std::variant<std::vector<f64>, std::vector<f64_3>> {
358 if (field_type ==
"f64") {
359 ramses::modules::GridRender<Tvec, TgridVec, f64> render(
360 self.ctx, self.solver.solver_config, self.solver.storage);
361 return render.compute_slice(name, positions).copy_to_stdvec();
364 if (field_type ==
"f64_3") {
365 ramses::modules::GridRender<Tvec, TgridVec, f64_3> render(
366 self.ctx, self.solver.solver_config, self.solver.storage);
367 return render.compute_slice(name, positions).copy_to_stdvec();
375 return self.solver.get_time();
380 return self.solver.get_dt();
384 [](T &self, Tscal t) {
385 return self.solver.set_time(t);
387 .def(
"set_next_dt", [](T &self, Tscal dt) {
388 return self.solver.set_next_dt(dt);
394 auto &m = root_module;
396 py::module mramses = m.def_submodule(
"model_ramses",
"Shamrock Ramses solver");
398 std::string base_name =
"RamsesModel";
401 add_instance<f64_3, i64_3>(
402 mramses, base_name +
"_f64_3_i64_3_SolverConfig", base_name +
"_f64_3_i64_3_Model");
404 using VariantAMRGodunovBind = std::variant<std::unique_ptr<Model<f64_3, i64_3>>>;
409 std::string vector_type,
410 std::string grid_repr) -> VariantAMRGodunovBind {
411 VariantAMRGodunovBind ret;
413 if (vector_type ==
"f64_3" && grid_repr ==
"i64_3") {
414 ret = std::make_unique<Model<f64_3, i64_3>>(ctx);
417 "unknown combination of representation and grid_repr");
424 py::arg(
"vector_type"),
425 py::arg(
"grid_repr"));
double f64
Alias for double.
float f32
Alias for float.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
std::int32_t i32
32 bit integer
void throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.
T & get_check_ref(const std::unique_ptr< T > &ptr, SourceLocation loc=SourceLocation())
Takes a std::unique_ptr and returns a reference to the object it holds. It throws a std::runtime_erro...
ExcptTypes make_except_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Create an exception with a message and a location.
namespace for the basegodunov model
@ HB
Huang and Bai. Pressureless Riemann solver by Huang and Bai (2022) in Athena++.
@ DHLL
Dust HLL. This is merely the HLL solver for dust. It's then a Rusanov like.
@ NoDust
No dust, so no Riemann solver is used.
Pybind11 include and definitions.
#define ON_PYTHON_INIT
Register a Python module init function using static initialization.
Utilities to convert JSON objects to Python objects and vice versa. TODO: try to convert directly wit...