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>;
38 using T = Model<Tvec, TgridVec>;
39 using TConfig =
typename T::Solver::Config;
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_gravity_mode_no_gravity",
205 self.gravity_config.gravity_mode = NoGravity;
208 "set_gravity_mode_cg",
210 self.gravity_config.gravity_mode = CG;
213 "set_gravity_mode_pcg",
215 self.gravity_config.gravity_mode = PCG;
218 "set_gravity_mode_bicgstab",
220 self.gravity_config.gravity_mode = BICGSTAB;
222 .def(
"set_npscal_gas", [](TConfig &self,
u32 npscal_gas) {
223 self.npscal_gas_config.npscal_gas = npscal_gas;
226 std::string sod_tube_analysis_name = name_model +
"_AnalysisSodTube";
227 py::class_<TAnalysisSodTube>(m, sod_tube_analysis_name.c_str())
228 .def(
"compute_L2_dist", [](TAnalysisSodTube &self) -> std::tuple<Tscal, Tvec, Tscal> {
229 auto ret = self.compute_L2_dist();
230 return {ret.rho, ret.v, ret.P};
233 py::class_<T>(m, name_model.c_str())
234 .def(
"init", &T::init)
235 .def(
"init_scheduler", &T::init_scheduler)
236 .def(
"make_base_grid", &T::make_base_grid)
237 .def(
"dump_vtk", &T::dump_vtk)
238 .def(
"dump", &T::dump)
239 .def(
"load_from_dump", &T::load_from_dump)
240 .def(
"evolve_once_override_time", &T::evolve_once_time_expl)
241 .def(
"evolve_once", &T::evolve_once)
244 [](T &self,
f64 target_time,
i32 niter_max) {
245 return self.evolve_until(target_time, niter_max);
247 py::arg(
"target_time"),
249 py::arg(
"niter_max") = -1)
250 .def(
"timestep", &T::timestep)
254 "set_field_value_lambda_f64",
256 std::string field_name,
257 const std::function<
f64(Tvec, Tvec)> pos_to_val,
259 return self.template set_field_value_lambda<f64>(
260 field_name, pos_to_val, offset);
262 py::arg(
"field_name"),
263 py::arg(
"pos_to_val"),
264 py::arg(
"offset") = 0)
266 "set_field_value_lambda_f64_3",
268 std::string field_name,
269 const std::function<f64_3(Tvec, Tvec)> pos_to_val,
271 return self.template set_field_value_lambda<f64_3>(
272 field_name, pos_to_val, offset);
274 py::arg(
"field_name"),
275 py::arg(
"pos_to_val"),
276 py::arg(
"offset") = 0)
278 "gen_default_config",
279 [](T &self) -> TConfig {
284 [](T &self, TConfig cfg) {
285 if (self.ctx.is_scheduler_initialized()) {
287 "Cannot change solver config after scheduler is initialized");
290 self.solver.solver_config = cfg;
294 [](T &self, std::pair<TgridVec, TgridVec> block_coord,
u32 cell_local_id) {
295 return self.get_cell_coords(block_coord, cell_local_id);
298 "make_analysis_sodtube",
306 return std::make_unique<TAnalysisSodTube>(
308 self.solver.solver_config,
323 "get_solver_dot_graph",
330 [](T &self, std::string name, std::string field_type, std::vector<Tvec> positions)
331 -> std::variant<std::vector<f64>, std::vector<f64_3>> {
332 if (field_type ==
"f64") {
333 ramses::modules::GridRender<Tvec, TgridVec, f64> render(
334 self.ctx, self.solver.solver_config, self.solver.storage);
335 return render.compute_slice(name, positions).copy_to_stdvec();
338 if (field_type ==
"f64_3") {
339 ramses::modules::GridRender<Tvec, TgridVec, f64_3> render(
340 self.ctx, self.solver.solver_config, self.solver.storage);
341 return render.compute_slice(name, positions).copy_to_stdvec();
349 return self.solver.solver_config.get_time();
354 return self.solver.solver_config.get_dt();
358 [](T &self, Tscal t) {
359 return self.solver.solver_config.set_time(t);
361 .def(
"set_next_dt", [](T &self, Tscal dt) {
362 return self.solver.solver_config.set_next_dt(dt);
369 py::module mramses = m.def_submodule(
"model_ramses",
"Shamrock Ramses solver");
371 std::string base_name =
"RamsesModel";
374 add_instance<f64_3, i64_3>(
375 mramses, base_name +
"_f64_3_i64_3_SolverConfig", base_name +
"_f64_3_i64_3_Model");
377 using VariantAMRGodunovBind = std::variant<std::unique_ptr<Model<f64_3, i64_3>>>;
382 std::string vector_type,
383 std::string grid_repr) -> VariantAMRGodunovBind {
384 VariantAMRGodunovBind ret;
386 if (vector_type ==
"f64_3" && grid_repr ==
"i64_3") {
387 ret = std::make_unique<Model<f64_3, i64_3>>(ctx);
390 "unknown combination of representation and grid_repr");
397 py::arg(
"vector_type"),
398 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...
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 Register_pymod(placeholdername)
Register a python module init function using static initialisation.
Utilities to convert JSON objects to Python objects and vice versa. TODO: try to convert directly wit...