42#include <pybind11/cast.h>
43#include <pybind11/numpy.h>
44#include <pybind11/pytypes.h>
50template<
class Tvec,
template<
class>
class SPHKernel>
51void add_instance(py::module &m, std::string name_config, std::string name_model) {
54 using Tscal = shambase::VecComponent<Tvec>;
61 using TConfig =
typename T::Solver::Config;
63 using custom_getter_t = std::function<pybind11::array_t<f64>(
size_t, pybind11::dict &)>;
65 shamlog_debug_ln(
"[Py]",
"registering class :", name_config,
typeid(T).name());
66 shamlog_debug_ln(
"[Py]",
"registering class :", name_model,
typeid(T).name());
68 py::class_<TConfig> config_cls(m, name_config.c_str());
70 shammodels::common::add_json_defs<TConfig>(config_cls);
72 config_cls.def(
"print_status", &TConfig::print_status)
73 .def(
"set_particle_tracking", &TConfig::set_particle_tracking)
75 "set_scheduler_config",
76 [](TConfig &self,
u64 split_crit,
u64 merge_crit) {
77 self.scheduler_conf.split_load_value = split_crit;
78 self.scheduler_conf.merge_load_value = merge_crit;
81 py::arg(
"split_load_value"),
82 py::arg(
"merge_load_value"))
83 .def(
"set_tree_reduction_level", &TConfig::set_tree_reduction_level)
84 .def(
"set_two_stage_search", &TConfig::set_two_stage_search)
85 .def(
"set_show_neigh_stats", &TConfig::set_show_neigh_stats)
87 "set_max_neigh_cache_size",
88 [](TConfig &self,
const py::object &max_neigh_cache_size) {
91 ".set_max_neigh_cache_size() is deprecated,\n"
92 " -> calling this is a no-op,\n"
93 " -> you can remove the call to that function"););
95 .def(
"set_smoothing_length_density_based", &TConfig::set_smoothing_length_density_based)
97 "set_smoothing_length_density_based_neigh_lim",
98 &TConfig::set_smoothing_length_density_based_neigh_lim)
99 .def(
"set_enable_particle_reordering", &TConfig::set_enable_particle_reordering)
100 .def(
"set_particle_reordering_step_freq", &TConfig::set_particle_reordering_step_freq)
101 .def(
"set_show_ghost_zone_graph", &TConfig::set_show_ghost_zone_graph)
102 .def(
"use_luminosity", &TConfig::use_luminosity)
103 .def(
"set_save_dt_to_fields", &TConfig::set_save_dt_to_fields)
104 .def(
"should_save_dt_to_fields", &TConfig::should_save_dt_to_fields)
105 .def(
"set_eos_isothermal", &TConfig::set_eos_isothermal)
106 .def(
"set_eos_adiabatic", &TConfig::set_eos_adiabatic)
107 .def(
"set_eos_polytropic", &TConfig::set_eos_polytropic)
108 .def(
"set_eos_locally_isothermal", &TConfig::set_eos_locally_isothermal)
110 "set_eos_locally_isothermalLP07",
111 [](TConfig &self, Tscal cs0, Tscal q, Tscal r0) {
112 self.set_eos_locally_isothermalLP07(cs0, q, r0);
119 "set_eos_locally_isothermalFA2014",
120 [](TConfig &self, Tscal h_over_r) {
121 self.set_eos_locally_isothermalFA2014(h_over_r);
126 "set_eos_locally_isothermalFA2014_extended",
127 [](TConfig &self, Tscal cs0, Tscal q, Tscal r0,
u32 n_sinks) {
128 self.set_eos_locally_isothermalFA2014_extended(cs0, q, r0, n_sinks);
137 [](TConfig &self, Tscal mu_e) {
138 self.set_eos_fermi(mu_e);
142 .def(
"set_artif_viscosity_None", &TConfig::set_artif_viscosity_None)
144 "set_artif_viscosity_Constant",
145 [](TConfig &self, Tscal alpha_u, Tscal alpha_AV, Tscal beta_AV) {
146 self.set_artif_viscosity_Constant({alpha_u, alpha_AV, beta_AV});
153 "set_artif_viscosity_VaryingMM97",
160 self.set_artif_viscosity_VaryingMM97(
161 {alpha_min, alpha_max, sigma_decay, alpha_u, beta_AV});
164 py::arg(
"alpha_min"),
165 py::arg(
"alpha_max"),
166 py::arg(
"sigma_decay"),
170 "set_artif_viscosity_VaryingCD10",
177 self.set_artif_viscosity_VaryingCD10(
178 {alpha_min, alpha_max, sigma_decay, alpha_u, beta_AV});
181 py::arg(
"alpha_min"),
182 py::arg(
"alpha_max"),
183 py::arg(
"sigma_decay"),
187 "set_artif_viscosity_ConstantDisc",
188 [](TConfig &self, Tscal alpha_AV, Tscal alpha_u, Tscal beta_AV) {
189 self.set_artif_viscosity_ConstantDisc({alpha_AV, alpha_u, beta_AV});
197 [](TConfig &self, Tscal sigma_mhd, Tscal sigma_u) {
198 self.set_IdealMHD({sigma_mhd, sigma_u});
201 py::arg(
"sigma_mhd"),
204 "set_self_gravity_none",
206 self.self_grav_config.set_none();
209 "set_self_gravity_direct",
210 [](TConfig &self,
bool reference_mode =
false) {
211 self.self_grav_config.set_direct(reference_mode);
214 py::arg(
"reference_mode") =
false)
216 "set_self_gravity_mm",
217 [](TConfig &self,
u32 mm_order,
f64 opening_angle,
u32 reduction_level) {
218 self.self_grav_config.set_mm(mm_order, opening_angle, reduction_level);
222 py::arg(
"opening_angle"),
223 py::arg(
"reduction_level") = 3)
225 "set_self_gravity_fmm",
226 [](TConfig &self,
u32 order,
f64 opening_angle,
u32 reduction_level) {
227 self.self_grav_config.set_fmm(order, opening_angle, reduction_level);
231 py::arg(
"opening_angle"),
232 py::arg(
"reduction_level") = 3)
234 "set_self_gravity_sfmm",
239 u32 reduction_level) {
240 self.self_grav_config.set_sfmm(
241 sfmm_order, opening_angle, leaf_lowering, reduction_level);
245 py::arg(
"opening_angle"),
246 py::arg(
"leaf_lowering") =
true,
247 py::arg(
"reduction_level") = 3)
249 "set_softening_plummer",
250 [](TConfig &self,
f64 epsilon) {
251 self.self_grav_config.set_softening_plummer(epsilon);
256 "set_softening_none",
258 self.self_grav_config.set_softening_none();
260 .def(
"set_boundary_free", &TConfig::set_boundary_free)
261 .def(
"set_boundary_periodic", &TConfig::set_boundary_periodic)
262 .def(
"set_boundary_shearing_periodic", &TConfig::set_boundary_shearing_periodic)
264 "set_dust_mode_none",
266 self.dust_config.set_none();
269 "set_dust_mode_monofluid_tvi",
270 [](TConfig &self,
u32 nvar,
bool pure_diffusion_mode) {
271 self.dust_config.set_monofluid_tvi(nvar, pure_diffusion_mode);
275 py::arg(
"pure_diffusion_mode") =
false)
277 "set_dust_mode_monofluid_complete",
278 [](TConfig &self,
u32 ndust) {
279 self.dust_config.set_monofluid_complete(ndust);
284 "set_dust_drag_constant",
285 [](TConfig &self, std::vector<Tscal> ts) {
286 self.dust_config.set_drag_constant({.stopping_times = std::move(ts)});
289 "set_dust_drag_epstein",
292 std::vector<Tscal> grain_sizes,
293 std::vector<Tscal> grain_densities) {
294 self.dust_config.set_drag_epstein(
296 .grains_sizes = std::move(grain_sizes),
297 .grains_densities = std::move(grain_densities)});
300 py::arg(
"grain_sizes"),
301 py::arg(
"grain_densities"))
302 .def(
"add_ext_force_point_mass", &TConfig::add_ext_force_point_mass)
303 .def(
"add_ext_force_paczynski_wiita", &TConfig::add_ext_force_paczynski_wiita)
305 "add_ext_force_lense_thirring",
306 [](TConfig &self, Tscal central_mass, Tscal Racc, Tscal a_spin, Tvec dir_spin) {
307 self.add_ext_force_lense_thirring(central_mass, Racc, a_spin, dir_spin);
310 py::arg(
"central_mass"),
315 "add_ext_force_shearing_box",
316 [](TConfig &self, Tscal Omega_0, Tscal eta, Tscal q) {
317 self.add_ext_force_shearing_box(Omega_0, eta, q);
324 "add_ext_force_velocity_dissipation",
325 [](TConfig &self, Tscal eta) {
326 self.ext_force_config.add_velocity_dissipation(eta);
331 "add_ext_force_vertical_disc_potential",
332 [](TConfig &self, Tscal central_mass, Tscal R0) {
333 self.ext_force_config.add_vertical_disc_potential(central_mass, R0);
336 py::arg(
"central_mass"),
338 .def(
"set_units", &TConfig::set_units)
342 return self.unit_sys;
346 [](TConfig &self, Tscal cfl_cour) {
347 self.cfl_config.cfl_cour = cfl_cour;
351 [](TConfig &self, Tscal cfl_force) {
352 self.cfl_config.cfl_force = cfl_force;
356 [](TConfig &self, Tscal eta_sink) {
357 self.cfl_config.eta_sink = eta_sink;
359 .def(
"set_cfl_multipler", &TConfig::set_cfl_multipler)
360 .def(
"set_cfl_mult_stiffness", &TConfig::set_cfl_mult_stiffness)
362 "set_show_cfl_detail",
363 [](TConfig &self,
bool show_cfl_detail) {
364 self.show_cfl_detail = show_cfl_detail;
366 py::arg(
"show_cfl_detail"))
369 [](TConfig &self, Tscal gpart_mass) {
370 self.gpart_mass = gpart_mass;
374 [](TConfig &self,
const Tvec ¢er, Tscal radius) {
375 self.particle_killing.add_kill_sphere(center, radius);
381 std::string sod_tube_analysis_name = name_model +
"_AnalysisSodTube";
382 py::class_<TAnalysisSodTube>(m, sod_tube_analysis_name.c_str())
383 .def(
"compute_L2_dist", [](TAnalysisSodTube &self) -> std::tuple<Tscal, Tvec, Tscal> {
384 auto ret = self.compute_L2_dist();
385 return {ret.rho, ret.v, ret.P};
388 std::string disc_analysis_name = name_model +
"_AnalysisDisc";
389 py::class_<TAnalysisDisc>(m, disc_analysis_name.c_str())
392 [](TAnalysisDisc &self, Tscal Rmin, Tscal Rmax,
u32 Nbin,
ShamrockCtx &ctx) {
393 auto anal = self.compute_analysis(Rmin, Rmax, Nbin, ctx);
396 auto radius = anal.radius.copy_to_stdvec();
397 auto counter = anal.counter.copy_to_stdvec();
398 auto Sigma = anal.Sigma.copy_to_stdvec();
399 auto lx = anal.lx.copy_to_stdvec();
400 auto ly = anal.ly.copy_to_stdvec();
401 auto lz = anal.lz.copy_to_stdvec();
402 auto tilt = anal.tilt.copy_to_stdvec();
403 auto twist = anal.twist.copy_to_stdvec();
404 auto psi = anal.psi.copy_to_stdvec();
405 auto Hsq = anal.Hsq.copy_to_stdvec();
407 dic_out[
"radius"] = radius;
408 dic_out[
"counter"] = counter;
409 dic_out[
"Sigma"] = Sigma;
413 dic_out[
"tilt"] = tilt;
414 dic_out[
"twist"] = twist;
415 dic_out[
"psi"] = psi;
416 dic_out[
"Hsq"] = Hsq;
421 std::string setup_name = name_model +
"_SPHSetup";
422 py::class_<TSPHSetup>(m, setup_name.c_str())
424 "make_generator_lattice_hcp",
425 [](TSPHSetup &self, Tscal dr, Tvec box_min, Tvec box_max,
bool discontinuous) {
426 return self.make_generator_lattice_hcp(dr, {box_min, box_max}, discontinuous);
431 py::arg(
"discontinuous") =
true)
433 "make_generator_lattice_cubic",
434 [](TSPHSetup &self, Tscal dr, Tvec box_min, Tvec box_max) {
435 return self.make_generator_lattice_cubic(dr, {box_min, box_max});
438 "make_generator_disc_mc",
444 std::function<Tscal(Tscal)> sigma_profile,
445 std::function<Tscal(Tscal)> H_profile,
446 std::function<Tscal(Tscal)> rot_profile,
447 std::function<Tscal(Tscal)> cs_profile,
448 std::function<Tvec(Tvec)> velocity_field,
449 std::function<Tscal(Tvec)> cs_field,
451 Tscal init_h_factor) {
452 auto build_vel_lambda = [&]() -> std::function<Tvec(Tvec)> {
453 if (!velocity_field && !rot_profile) {
455 "make_generator_disc_mc: either velocity_field or rot_profile must be "
456 "provided, you must provide one of them");
459 if (velocity_field && rot_profile) {
461 "make_generator_disc_mc: either velocity_field or rot_profile must be "
462 "provided, you cannot provide both");
465 if (velocity_field) {
466 return std::move(velocity_field);
468 return [vth_r = std::move(rot_profile)](Tvec pos) {
470 Tscal r = sycl::length(pos);
472 auto etheta = sycl::vec<Tscal, 3>{-pos.y(), pos.x(), 0};
473 etheta /= sycl::length(etheta);
475 return vth_r(r) * etheta;
479 auto build_cs_lambda = [&]() -> std::function<Tscal(Tvec)> {
480 bool need_cs = self.solver_config.is_eos_locally_isothermal();
487 "make_generator_disc_mc: with the current EOS, cs_field is "
495 "make_generator_disc_mc: with the current EOS, cs_profile is "
499 return std::function<Tscal(Tvec)>{};
502 if (!cs_field && !cs_profile) {
504 "make_generator_disc_mc: either cs_field or cs_profile must be "
505 "provided, you must provide one of them");
508 if (cs_field && cs_profile) {
510 "make_generator_disc_mc: either cs_field or cs_profile must be "
511 "provided, you cannot provide both");
515 return std::move(cs_field);
518 return [cs_r = std::move(cs_profile)](Tvec pos) {
520 Tscal r = sycl::length(pos);
525 return self.make_generator_disc_mc(
530 std::move(sigma_profile),
531 std::move(H_profile),
534 std::mt19937_64(random_seed),
538 py::arg(
"part_mass"),
539 py::arg(
"disc_mass"),
542 py::arg(
"sigma_profile"),
543 py::arg(
"H_profile"),
544 py::arg(
"rot_profile") = std::function<Tscal(Tscal)>{},
545 py::arg(
"cs_profile") = std::function<Tscal(Tscal)>{},
546 py::arg(
"velocity_field") = std::function<Tvec(Tvec)>{},
547 py::arg(
"cs_field") = std::function<Tscal(Tvec)>{},
548 py::arg(
"random_seed"),
549 py::arg(
"init_h_factor") = 0.8,
551 Create a Monte Carlo disc particle generator.
553 Particles are sampled in cylindrical coordinates: the radius is drawn
554 with rejection sampling from ``sigma_profile``, the azimuth is uniform,
555 and the vertical coordinate follows a Gaussian with scale ``H_profile(r)``.
556 The initial density is extrapolated from the surface density profile, and
557 smoothing lengths are set from that density.
560 part_mass: Mass of each SPH particle.
561 disc_mass: Total disc mass. The particle count is ``disc_mass / part_mass``.
562 r_in: Inner disc radius.
563 r_out: Outer disc radius.
564 sigma_profile: Surface density profile ``sigma(r)``.
565 H_profile: Disc scale height profile ``H(r)``.
566 rot_profile: Azimuthal speed profile ``v_theta(r)``. The velocity is
567 projected along the cylindrical azimuthal direction at each
568 particle position. Mutually exclusive with ``velocity_field``.
569 cs_profile: Sound speed profile ``c_s(r)``. Evaluated at the cylindrical
570 radius of each particle. Required when the solver uses a locally
571 isothermal EOS. Mutually exclusive with ``cs_field``.
572 velocity_field: Velocity profile ``v(x, y, z)``. Mutually exclusive
573 with ``rot_profile``.
574 cs_field: Sound speed profile ``c_s(x, y, z)``. Required when the solver
575 uses a locally isothermal EOS. Mutually exclusive with ``cs_profile``.
576 random_seed: Seed for the Monte Carlo sampler.
577 init_h_factor: Multiplier applied to the smoothing length inferred from
578 the generated density. Defaults to ``0.8``.
581 Exactly one of ``velocity_field`` or ``rot_profile`` must be provided.
583 If the solver uses a locally isothermal EOS, exactly one of ``cs_field``
584 or ``cs_profile`` must be provided. Otherwise both sound-speed profiles
585 are ignored and a warning is emitted if either is supplied.
588 A setup node to pass to :py:meth:`apply_setup`.
591 "make_generator_from_context",
593 return self.make_generator_from_context(context_other);
600 return self.make_combiner_add(parent1, parent2);
603 "make_modifier_warp_disc",
610 return self.make_modifier_warp_disc(parent, Rwarp, Hwarp, inclination, posangle);
616 py::arg(
"inclination"),
617 py::arg(
"posangle") = 0.)
619 "make_modifier_custom_warp",
622 std::function<Tscal(Tscal)> inc_profile,
623 std::function<Tscal(Tscal)> psi_profile,
624 std::function<Tvec(Tscal)> k_profile) {
625 return self.make_modifier_custom_warp(parent, inc_profile, psi_profile, k_profile);
629 py::arg(
"inc_profile"),
630 py::arg(
"psi_profile"),
631 py::arg(
"k_profile"))
633 "make_modifier_offset",
637 Tvec offset_velocity) {
638 return self.make_modifier_add_offset(parent, offset_postion, offset_velocity);
642 py::arg(
"offset_position"),
643 py::arg(
"offset_velocity"))
645 "make_modifier_filter",
648 std::function<
bool(Tvec)> filter) {
649 return self.make_modifier_filter(parent, filter);
655 "make_modifier_split_part",
661 return self.make_modifier_split_part(parent, n_split, seed, h_scaling);
667 py::arg(
"h_scaling") = 0.6)
672 bool part_reordering,
673 std::optional<u32> gen_step,
674 std::optional<u32> insert_step,
675 std::optional<u64> msg_count_limit,
676 std::optional<u64> msg_size_limit,
677 std::optional<u64> max_msg_size,
680 bool speculative_balancing) {
682 return self.apply_setup_new(
691 speculative_balancing);
693 if (
bool(gen_step)) {
696 "SPHSetup",
"gen_step is ignored when using old setup"));
698 if (
bool(msg_count_limit)) {
701 "SPHSetup",
"msg_count_limit is ignored when using old setup"));
703 if (
bool(msg_size_limit)) {
706 "SPHSetup",
"msg_size_limit is ignored when using old setup"));
708 if (
bool(max_msg_size)) {
711 "SPHSetup",
"max_msg_size is ignored when using old setup"));
713 if (
bool(do_setup_log)) {
716 "SPHSetup",
"do_setup_log is ignored when using old setup"));
718 return self.apply_setup(setup, part_reordering, insert_step);
723 py::arg(
"part_reordering") =
true,
724 py::arg(
"gen_step") = std::nullopt,
725 py::arg(
"insert_step") = std::nullopt,
726 py::arg(
"msg_count_limit") = std::nullopt,
727 py::arg(
"rank_comm_size_limit") = std::nullopt,
728 py::arg(
"max_msg_size") = std::nullopt,
729 py::arg(
"do_setup_log") =
false,
730 py::arg(
"use_new_setup") =
true,
731 py::arg(
"speculative_balancing") =
false);
733 py::class_<T>(m, name_model.c_str())
735 return std::make_unique<T>(ctx);
737 .def(
"init", &T::init)
738 .def(
"init_scheduler", &T::init_scheduler)
741 "evolve_once_override_time",
742 &T::evolve_once_time_expl,
745 .def(
"evolve_once", &T::evolve_once)
748 [](T &self,
f64 target_time,
i32 niter_max,
f64 max_walltime) {
749 return self.evolve_until(target_time, niter_max, max_walltime);
751 py::arg(
"target_time"),
753 py::arg(
"niter_max") = -1,
754 py::arg(
"max_walltime") = -1)
757 [](T &self,
f64 dt) {
758 self.solver.solver_config.set_next_dt(dt);
760 .def(
"timestep", &T::timestep)
761 .def(
"set_cfl_cour", &T::set_cfl_cour, py::arg(
"cfl_cour"))
762 .def(
"set_cfl_force", &T::set_cfl_force, py::arg(
"cfl_force"))
763 .def(
"set_eta_sink", &T::set_eta_sink, py::arg(
"eta_sink"))
764 .def(
"set_particle_mass", &T::set_particle_mass, py::arg(
"gpart_mass"))
765 .def(
"get_particle_mass", &T::get_particle_mass)
766 .def(
"rho_h", &T::rho_h)
767 .def(
"get_hfact", &T::get_hfact)
774 "get_solver_dot_graph",
779 "get_box_dim_fcc_3d",
781 return self.get_box_dim_fcc_3d(dr, xcnt, ycnt, zcnt);
785 [](T &self,
f64 dr, f64_3 box_min, f64_3 box_max) {
789 "The python function get_ideal_fcc_box is deprecated in the SPH model and "
790 "will be removed at some point, replace it by "
791 "shamrock.math.get_ideal_hcp_box"));
792 return shammath::LatticeHCP<f64_3>::get_ideal_hcp_box(dr, {box_min, box_max});
796 [](T &self,
f64 dr, f64_3 box_min, f64_3 box_max) {
800 "The python function get_ideal_hcp_box is deprecated in the SPH model and "
801 "will be removed at some point, replace it by "
802 "shamrock.math.get_ideal_hcp_box"));
803 return shammath::LatticeHCP<f64_3>::get_ideal_hcp_box(dr, {box_min, box_max});
806 "resize_simulation_box",
807 [](T &self, f64_3 box_min, f64_3 box_max) {
808 return self.resize_simulation_box({box_min, box_max});
812 [](T &self, std::vector<f64_3> pos, std::vector<f64> hpart, std::vector<f64> upart) {
813 return self.push_particle(pos, hpart, upart);
818 std::vector<f64_3> pos,
819 std::vector<f64> hpart,
820 std::vector<f64> upart,
821 std::vector<f64_3> B_on_rho,
822 std::vector<f64> psi_on_ch) {
823 return self.push_particle_mhd(pos, hpart, upart, B_on_rho, psi_on_ch);
827 [](T &self,
f64 dr, f64_3 box_min, f64_3 box_max) {
828 return self.add_cube_fcc_3d(dr, {box_min, box_max});
832 [](T &self,
f64 dr, f64_3 box_min, f64_3 box_max) {
833 return self.add_cube_hcp_3d(dr, {box_min, box_max});
836 "add_cube_hcp_3d_v2",
837 [](T &self,
f64 dr, f64_3 box_min, f64_3 box_max) {
838 return self.add_cube_hcp_3d_v2(dr, {box_min, box_max});
841 "add_disc_3d_keplerian",
852 return self.add_cube_disc_3d(center, Npart, p, rho_0, m, r_in, r_out, q, cmass);
866 return self.add_disc_3d(
867 center, central_mass, Npart, r_in, r_out, disc_mass, p, H_r_in, q);
882 self.add_big_disc_3d(
893 return disc_mass / Npart;
895 .def(
"get_total_part_count", &T::get_total_part_count)
896 .def(
"total_mass_to_part_mass", &T::total_mass_to_part_mass)
898 "set_value_in_a_box",
900 const std::string &field_name,
901 const std::string &field_type,
902 const pybind11::object &value,
906 if (field_type ==
"f64") {
907 f64 val = value.cast<
f64>();
908 self.set_value_in_a_box(field_name, val, {box_min, box_max}, ivar);
909 }
else if (field_type ==
"f64_3") {
910 f64_3 val = value.cast<f64_3>();
911 self.set_value_in_a_box(field_name, val, {box_min, box_max}, ivar);
914 "unknown field type");
917 py::arg(
"field_name"),
918 py::arg(
"field_type"),
925 "set_value_in_sphere",
927 const std::string &field_name,
928 const std::string &field_type,
929 const pybind11::object &value,
932 if (field_type ==
"f64") {
933 f64 val = value.cast<
f64>();
934 self.set_value_in_sphere(field_name, val, center, radius);
935 }
else if (field_type ==
"f64_3") {
936 f64_3 val = value.cast<f64_3>();
937 self.set_value_in_sphere(field_name, val, center, radius);
940 "unknown field type");
944 "set_field_value_lambda_f64",
946 std::string field_name,
947 const std::function<
f64(Tvec)> pos_to_val,
949 return self.template set_field_value_lambda<f64>(
950 std::move(field_name), pos_to_val, offset);
952 py::arg(
"field_name"),
953 py::arg(
"pos_to_val"),
954 py::arg(
"offset") = 0)
956 "set_field_value_lambda_f64_3",
958 std::string field_name,
959 const std::function<f64_3(Tvec)> pos_to_val,
961 return self.template set_field_value_lambda<f64_3>(
962 std::move(field_name), pos_to_val, offset);
964 py::arg(
"field_name"),
965 py::arg(
"pos_to_val"),
966 py::arg(
"offset") = 0)
967 .def(
"overwrite_field_value_f64", &T::template overwrite_field_value<f64>)
968 .def(
"overwrite_field_value_f64_3", &T::template overwrite_field_value<f64_3>)
969 .def(
"remap_positions", &T::remap_positions)
979 const std::string &field_name,
980 const std::string &field_type,
981 const pybind11::object &value,
984 if (field_type ==
"f64") {
985 f64 val = value.cast<
f64>();
986 self.add_kernel_value(field_name, val, center, h_ker);
987 }
else if (field_type ==
"f64_3") {
988 f64_3 val = value.cast<f64_3>();
989 self.add_kernel_value(field_name, val, center, h_ker);
992 "unknown field type");
997 [](T &self,
const std::string &field_name,
const std::string &field_type) {
998 if (field_type ==
"f64") {
999 return py::cast(self.template get_sum<f64>(field_name));
1000 }
else if (field_type ==
"f64_3") {
1001 return py::cast(self.template get_sum<f64_3>(field_name));
1004 "unknown field type");
1008 "get_closest_part_to",
1009 [](T &self, f64_3 pos) -> f64_3 {
1010 return self.get_closest_part_to(pos);
1013 "gen_default_config",
1015 return typename T::Solver::Config{};
1018 "get_current_config",
1020 return self.solver.solver_config;
1022 .def(
"set_solver_config", &T::set_solver_config)
1023 .def(
"add_sink", &T::add_sink)
1029 if (!self.solver.storage.sinks.is_empty()) {
1030 for (
auto &sink : self.solver.storage.sinks.get()) {
1032 sink_dic[
"pos"] = sink.pos;
1033 sink_dic[
"velocity"] = sink.velocity;
1034 sink_dic[
"sph_acceleration"] = sink.sph_acceleration;
1035 sink_dic[
"ext_acceleration"] = sink.ext_acceleration;
1036 sink_dic[
"mass"] = sink.mass;
1037 sink_dic[
"angular_momentum"] = sink.angular_momentum;
1038 sink_dic[
"accretion_radius"] = sink.accretion_radius;
1039 list_out.append(sink_dic);
1048 return self.solver.solver_config.unit_sys;
1053 const std::string &name,
1054 const std::string &field_type,
1055 const std::vector<Tvec> &positions,
1056 const std::optional<custom_getter_t> &custom_getter)
1057 -> std::variant<std::vector<f64>, std::vector<f64_3>> {
1058 if (custom_getter.has_value()) {
1059 if (!(name ==
"custom" && field_type ==
"f64")) {
1061 "custom_getter only available for name=custom and field_type=f64");
1065 if (field_type ==
"f64") {
1067 self.ctx, self.solver.solver_config, self.solver.storage);
1068 return render.compute_slice(name, positions, custom_getter).copy_to_stdvec();
1071 if (field_type ==
"f64_3") {
1073 self.ctx, self.solver.solver_config, self.solver.storage);
1074 return render.compute_slice(name, positions, std::nullopt).copy_to_stdvec();
1080 py::arg(
"field_type"),
1081 py::arg(
"positions"),
1082 py::arg(
"custom_getter") = std::nullopt)
1084 "render_column_integ",
1086 const std::string &name,
1087 const std::string &field_type,
1089 const std::optional<custom_getter_t> &custom_getter)
1090 -> std::variant<std::vector<f64>, std::vector<f64_3>> {
1091 if (custom_getter.has_value()) {
1092 if (!(name ==
"custom" && field_type ==
"f64")) {
1094 "custom_getter only available for name=custom and field_type=f64");
1098 if (field_type ==
"f64") {
1100 self.ctx, self.solver.solver_config, self.solver.storage);
1101 return render.compute_column_integ(name, rays, custom_getter).copy_to_stdvec();
1104 if (field_type ==
"f64_3") {
1106 self.ctx, self.solver.solver_config, self.solver.storage);
1107 return render.compute_column_integ(name, rays, std::nullopt).copy_to_stdvec();
1113 py::arg(
"field_type"),
1115 py::arg(
"custom_getter") = std::nullopt)
1119 const std::string &name,
1120 const std::string &field_type,
1121 const std::optional<custom_getter_t> &custom_getter)
1125 if (custom_getter.has_value()) {
1126 if (!(name ==
"custom" && field_type ==
"f64")) {
1128 "custom_getter only available for name=custom and field_type=f64");
1132 if (field_type ==
"f64") {
1134 self.ctx, self.solver.solver_config, self.solver.storage);
1135 return render_field_getter.build_field(name, custom_getter);
1138 if (field_type ==
"f64_3") {
1140 self.ctx, self.solver.solver_config, self.solver.storage);
1141 return render_field_getter.build_field(name, custom_getter);
1147 py::arg(
"field_type"),
1148 py::arg(
"custom_getter") = std::nullopt)
1150 "render_azymuthal_integ",
1152 const std::string &name,
1153 const std::string &field_type,
1155 const std::optional<custom_getter_t> &custom_getter)
1156 -> std::variant<std::vector<f64>, std::vector<f64_3>> {
1157 if (custom_getter.has_value()) {
1158 if (!(name ==
"custom" && field_type ==
"f64")) {
1160 "custom_getter only available for name=custom and field_type=f64");
1164 if (field_type ==
"f64") {
1166 self.ctx, self.solver.solver_config, self.solver.storage);
1167 return render.compute_azymuthal_integ(name, ring_rays, custom_getter)
1171 if (field_type ==
"f64_3") {
1173 self.ctx, self.solver.solver_config, self.solver.storage);
1174 return render.compute_azymuthal_integ(name, ring_rays, std::nullopt)
1181 py::arg(
"field_type"),
1182 py::arg(
"ring_rays"),
1183 py::arg(
"custom_getter") = std::nullopt)
1185 "render_cartesian_slice",
1187 const std::string &name,
1188 const std::string &field_type,
1194 const std::optional<custom_getter_t> &custom_getter)
1195 -> std::variant<py::array_t<Tscal>> {
1196 if (custom_getter.has_value()) {
1197 if (!(name ==
"custom" && field_type ==
"f64")) {
1199 "custom_getter only available for name=custom and field_type=f64");
1203 if (field_type ==
"f64") {
1204 py::array_t<Tscal> ret({ny, nx});
1207 self.ctx, self.solver.solver_config, self.solver.storage);
1209 std::vector<f64> slice
1211 .compute_slice(name, center, delta_x, delta_y, nx, ny, custom_getter)
1214 for (
u32 iy = 0; iy < ny; iy++) {
1215 for (
u32 ix = 0; ix < nx; ix++) {
1216 ret.mutable_at(iy, ix) = slice[ix + nx * iy];
1223 if (field_type ==
"f64_3") {
1224 py::array_t<Tscal> ret({ny, nx, 3_u32});
1227 self.ctx, self.solver.solver_config, self.solver.storage);
1229 std::vector<f64_3> slice
1230 = render.compute_slice(name, center, delta_x, delta_y, nx, ny, std::nullopt)
1233 for (
u32 iy = 0; iy < ny; iy++) {
1234 for (
u32 ix = 0; ix < nx; ix++) {
1235 ret.mutable_at(iy, ix, 0) = slice[ix + nx * iy][0];
1236 ret.mutable_at(iy, ix, 1) = slice[ix + nx * iy][1];
1237 ret.mutable_at(iy, ix, 2) = slice[ix + nx * iy][2];
1245 return py::array_t<Tscal>({nx, ny});
1248 py::arg(
"field_type"),
1254 py::arg(
"custom_getter") = std::nullopt)
1256 "render_cartesian_column_integ",
1258 const std::string &name,
1259 const std::string &field_type,
1265 const std::optional<custom_getter_t> &custom_getter)
1266 -> std::variant<py::array_t<Tscal>> {
1267 if (custom_getter.has_value()) {
1268 if (!(name ==
"custom" && field_type ==
"f64")) {
1270 "custom_getter only available for name=custom and field_type=f64");
1274 if (field_type ==
"f64") {
1275 py::array_t<Tscal> ret({ny, nx});
1278 self.ctx, self.solver.solver_config, self.solver.storage);
1280 std::vector<f64> slice
1282 .compute_column_integ(
1283 name, center, delta_x, delta_y, nx, ny, custom_getter)
1286 for (
u32 iy = 0; iy < ny; iy++) {
1287 for (
u32 ix = 0; ix < nx; ix++) {
1288 ret.mutable_at(iy, ix) = slice[ix + nx * iy];
1295 if (field_type ==
"f64_3") {
1296 py::array_t<Tscal> ret({ny, nx, 3_u32});
1299 self.ctx, self.solver.solver_config, self.solver.storage);
1301 std::vector<f64_3> slice
1303 .compute_column_integ(
1304 name, center, delta_x, delta_y, nx, ny, std::nullopt)
1307 for (
u32 iy = 0; iy < ny; iy++) {
1308 for (
u32 ix = 0; ix < nx; ix++) {
1309 ret.mutable_at(iy, ix, 0) = slice[ix + nx * iy][0];
1310 ret.mutable_at(iy, ix, 1) = slice[ix + nx * iy][1];
1311 ret.mutable_at(iy, ix, 2) = slice[ix + nx * iy][2];
1319 return py::array_t<Tscal>({nx, ny});
1322 py::arg(
"field_type"),
1328 py::arg(
"custom_getter") = std::nullopt)
1330 "gen_config_from_phantom_dump",
1331 [](T &self,
PhantomDump &dump,
bool bypass_error) {
1332 return self.gen_config_from_phantom_dump(dump, bypass_error);
1335 py::arg(
"bypass_error") =
false,
1337 This function generate a shamrock sph solver config from a phantom dump
1342 bypass_error = false (default) bypass any error in the config
1345 "init_from_phantom_dump",
1346 [](T &self,
PhantomDump &dump, Tscal hpart_fact_load) {
1347 self.init_from_phantom_dump(dump, hpart_fact_load);
1350 py::arg(
"hpart_fact_load") = 1.0)
1352 "make_phantom_dump",
1354 return self.make_phantom_dump();
1356 .def(
"do_vtk_dump", &T::do_vtk_dump)
1357 .def(
"set_debug_dump", &T::set_debug_dump)
1358 .def(
"solver_logs_last_rate", &T::solver_logs_last_rate)
1359 .def(
"solver_logs_last_obj_count", &T::solver_logs_last_obj_count)
1361 "solver_logs_last_system_metrics",
1363 auto system_metrics = self.solver.solve_logs.get_last_system_metrics();
1365 ret[
"duration"] = system_metrics.wall_time;
1366 if (system_metrics.rank_energy_consummed.has_value()) {
1367 ret[
"rank_energy_consummed"] = system_metrics.rank_energy_consummed.value();
1369 if (system_metrics.gpu_energy_consummed.has_value()) {
1370 ret[
"gpu_energy_consummed"] = system_metrics.gpu_energy_consummed.value();
1372 if (system_metrics.cpu_energy_consummed.has_value()) {
1373 ret[
"cpu_energy_consummed"] = system_metrics.cpu_energy_consummed.value();
1375 if (system_metrics.dram_energy_consummed.has_value()) {
1376 ret[
"dram_energy_consummed"] = system_metrics.dram_energy_consummed.value();
1380 .def(
"solver_logs_cumulated_step_time", &T::solver_logs_cumulated_step_time)
1381 .def(
"solver_logs_reset_cumulated_step_time", &T::solver_logs_reset_cumulated_step_time)
1382 .def(
"solver_logs_step_count", &T::solver_logs_step_count)
1383 .def(
"solver_logs_reset_step_count", &T::solver_logs_reset_step_count)
1387 return self.solver.solver_config.get_time();
1392 return self.solver.solver_config.get_dt_sph();
1396 [](T &self, Tscal t) {
1397 return self.solver.solver_config.set_time(t);
1401 [](T &self, Tscal dt) {
1402 return self.solver.solver_config.set_next_dt(dt);
1405 "set_cfl_multipler",
1406 [](T &self, Tscal lambda) {
1407 return self.solver.solver_config.set_cfl_multipler(lambda);
1411 "set_cfl_mult_stiffness",
1412 [](T &self, Tscal cstiff) {
1413 return self.solver.solver_config.set_cfl_mult_stiffness(cstiff);
1417 "change_htolerance",
1418 [](T &self, Tscal in) {
1421 ".change_htolerance(val) is deprecated,\n"
1422 " -> calling this is replaced internally by "
1423 ".change_htolerances(coarse=val, fine=min(val, 1.1))\n"
1425 "https://shamrock-code.github.io/Shamrock/mkdocs/models/sph/"
1426 "smoothing_length_tolerance"););
1427 self.change_htolerances(in, std::min(in, (Tscal) 1.1));
1430 "change_htolerances",
1431 [](T &self, Tscal coarse, Tscal fine) {
1432 self.change_htolerances(coarse, fine);
1438 "make_analysis_sodtube",
1446 return std::make_unique<TAnalysisSodTube>(
1448 self.solver.solver_config,
1449 self.solver.storage,
1458 py::arg(
"direction"),
1459 py::arg(
"time_val"),
1464 "make_analysis_disc",
1466 return std::make_unique<TAnalysisDisc>(
1467 self.ctx, self.solver.solver_config, self.solver.storage);
1469 .def(
"load_from_dump", &T::load_from_dump)
1470 .def(
"dump", &T::dump)
1471 .def(
"get_setup", &T::get_setup)
1473 "get_patch_transform",
1476 return sched.get_patch_transform<Tvec>();
1478 .def(
"apply_momentum_offset", &T::apply_momentum_offset)
1479 .def(
"apply_position_offset", &T::apply_position_offset)
1481 "add_timestep_callback",
1483 std::optional<std::function<
void(
void)>> step_begin_callback,
1484 std::optional<std::function<
void(
void)>> step_end_callback) {
1485 self.solver.timestep_callbacks.push_back(
1486 {std::move(step_begin_callback), std::move(step_end_callback)});
1489 py::arg(
"step_begin") = std::nullopt,
1490 py::arg(
"step_end") = std::nullopt);
1493template<
class Tvec,
template<
class>
class SPHKernel>
1494void add_analysisBarycenter_instance(py::module &m,
const std::string &name_model) {
1497 using Tscal = shambase::VecComponent<Tvec>;
1501 py::class_<modules::AnalysisBarycenter<Tvec, SPHKernel>>(m, name_model.c_str())
1502 .def(py::init([](T &model) {
1503 return std::make_unique<modules::AnalysisBarycenter<Tvec, SPHKernel>>(model);
1506 auto result = self.get_barycenter();
1507 return py::make_tuple(result.barycenter, result.mass_disc);
1511template<
class Tvec,
template<
class>
class SPHKernel>
1512void add_analysisEnergyKinetic_instance(py::module &m,
const std::string &name_model) {
1515 using Tscal = shambase::VecComponent<Tvec>;
1518 py::class_<modules::AnalysisEnergyKinetic<Tvec, SPHKernel>>(m, name_model.c_str())
1519 .def(py::init([](T &model) {
1520 return std::make_unique<modules::AnalysisEnergyKinetic<Tvec, SPHKernel>>(model);
1523 return self.get_kinetic_energy();
1527template<
class Tvec,
template<
class>
class SPHKernel>
1528void add_analysisEnergyPotential_instance(py::module &m,
const std::string &name_model) {
1531 using Tscal = shambase::VecComponent<Tvec>;
1534 py::class_<modules::AnalysisEnergyPotential<Tvec, SPHKernel>>(m, name_model.c_str())
1535 .def(py::init([](T &model) {
1536 return std::make_unique<modules::AnalysisEnergyPotential<Tvec, SPHKernel>>(model);
1539 return self.get_potential_energy();
1543template<
class Tvec,
template<
class>
class SPHKernel>
1544void add_analysisTotalMomentum_instance(py::module &m,
const std::string &name_model) {
1547 using Tscal = shambase::VecComponent<Tvec>;
1550 py::class_<modules::AnalysisTotalMomentum<Tvec, SPHKernel>>(m, name_model.c_str())
1551 .def(py::init([](T &model) {
1552 return std::make_unique<modules::AnalysisTotalMomentum<Tvec, SPHKernel>>(model);
1555 return self.get_total_momentum();
1559template<
class Tvec,
template<
class>
class SPHKernel>
1560void add_analysisAngularMomentum_instance(py::module &m,
const std::string &name_model) {
1563 using Tscal = shambase::VecComponent<Tvec>;
1566 py::class_<modules::AnalysisAngularMomentum<Tvec, SPHKernel>>(m, name_model.c_str())
1567 .def(py::init([](T &model) {
1568 return std::make_unique<modules::AnalysisAngularMomentum<Tvec, SPHKernel>>(model);
1571 return self.get_angular_momentum();
1575template<
class Tvec,
template<
class>
class SPHKernel>
1576void add_analysisDustMass_instance(py::module &m,
const std::string &name_model) {
1579 using Tscal = shambase::VecComponent<Tvec>;
1582 py::class_<modules::AnalysisDustMass<Tvec, SPHKernel>>(m, name_model.c_str())
1583 .def(py::init([](T &model) {
1584 return std::make_unique<modules::AnalysisDustMass<Tvec, SPHKernel>>(model);
1587 return self.get_dust_mass();
1593template<
class Analysis,
typename Tvec,
template<
class>
class SPHKernel>
1595 return Analysis(model);
1598template<
template<
class,
template<
class>
class>
class Analysis>
1599void register_analysis_impl_for_each_kernel(py::module &msph, const char *name_class) {
1600 using namespace shammodels::sph;
1602 using SPHModel_f64_3_M4 = shammodels::sph::Model<f64_3, shammath::M4>;
1603 using SPHModel_f64_3_M6 = shammodels::sph::Model<f64_3, shammath::M6>;
1604 using SPHModel_f64_3_M8 = shammodels::sph::Model<f64_3, shammath::M8>;
1606 using SPHModel_f64_3_C2 = shammodels::sph::Model<f64_3, shammath::C2>;
1607 using SPHModel_f64_3_C4 = shammodels::sph::Model<f64_3, shammath::C4>;
1608 using SPHModel_f64_3_C6 = shammodels::sph::Model<f64_3, shammath::C6>;
1612 [](SPHModel_f64_3_M4 &model) {
1613 return analysis_impl<Analysis<f64_3, shammath::M4>>(model);
1620 [](SPHModel_f64_3_M6 &model) {
1621 return analysis_impl<Analysis<f64_3, shammath::M6>>(model);
1628 [](SPHModel_f64_3_M8 &model) {
1629 return analysis_impl<Analysis<f64_3, shammath::M8>>(model);
1636 [](SPHModel_f64_3_C2 &model) {
1637 return analysis_impl<Analysis<f64_3, shammath::C2>>(model);
1644 [](SPHModel_f64_3_C4 &model) {
1645 return analysis_impl<Analysis<f64_3, shammath::C4>>(model);
1652 [](SPHModel_f64_3_C6 &model) {
1653 return analysis_impl<Analysis<f64_3, shammath::C6>>(model);
1660 auto &m = root_module;
1662 py::module msph = m.def_submodule(
"model_sph",
"Shamrock sph solver");
1664 py::class_<EvolveUntilResults>(m,
"EvolveUntilResults")
1665 .def_readwrite(
"reach_target_time", &EvolveUntilResults::reach_target_time)
1666 .def_readwrite(
"reach_niter_max", &EvolveUntilResults::reach_niter_max)
1667 .def_readwrite(
"reach_max_walltime", &EvolveUntilResults::reach_max_walltime)
1668 .def_readwrite(
"iter_count", &EvolveUntilResults::iter_count)
1670 return shambase::format(
1671 "EvolveUntilResults(reach_target_time={}, reach_niter_max={}, "
1672 "reach_max_walltime={}, iter_count={})",
1673 self.reach_target_time,
1674 self.reach_niter_max,
1675 self.reach_max_walltime,
1681 add_instance<f64_3, shammath::M4>(msph,
"SPHModel_f64_3_M4_SolverConfig",
"SPHModel_f64_3_M4");
1682 add_instance<f64_3, shammath::M6>(msph,
"SPHModel_f64_3_M6_SolverConfig",
"SPHModel_f64_3_M6");
1683 add_instance<f64_3, shammath::M8>(msph,
"SPHModel_f64_3_M8_SolverConfig",
"SPHModel_f64_3_M8");
1685 add_instance<f64_3, shammath::C2>(msph,
"SPHModel_f64_3_C2_SolverConfig",
"SPHModel_f64_3_C2");
1686 add_instance<f64_3, shammath::C4>(msph,
"SPHModel_f64_3_C4_SolverConfig",
"SPHModel_f64_3_C4");
1687 add_instance<f64_3, shammath::C6>(msph,
"SPHModel_f64_3_C6_SolverConfig",
"SPHModel_f64_3_C6");
1689 using VariantSPHModelBind = std::variant<
1690 std::unique_ptr<Model<f64_3, shammath::M4>>,
1691 std::unique_ptr<Model<f64_3, shammath::M6>>,
1692 std::unique_ptr<Model<f64_3, shammath::M8>>,
1693 std::unique_ptr<Model<f64_3, shammath::C2>>,
1694 std::unique_ptr<Model<f64_3, shammath::C4>>,
1695 std::unique_ptr<Model<f64_3, shammath::C6>>>;
1700 const std::string &vector_type,
1701 const std::string &kernel) -> VariantSPHModelBind {
1702 VariantSPHModelBind ret;
1704 if (vector_type ==
"f64_3" && kernel ==
"M4") {
1705 ret = std::make_unique<Model<f64_3, shammath::M4>>(ctx);
1706 }
else if (vector_type ==
"f64_3" && kernel ==
"M6") {
1707 ret = std::make_unique<Model<f64_3, shammath::M6>>(ctx);
1708 }
else if (vector_type ==
"f64_3" && kernel ==
"M8") {
1709 ret = std::make_unique<Model<f64_3, shammath::M8>>(ctx);
1710 }
else if (vector_type ==
"f64_3" && kernel ==
"C2") {
1711 ret = std::make_unique<Model<f64_3, shammath::C2>>(ctx);
1712 }
else if (vector_type ==
"f64_3" && kernel ==
"C4") {
1713 ret = std::make_unique<Model<f64_3, shammath::C4>>(ctx);
1714 }
else if (vector_type ==
"f64_3" && kernel ==
"C6") {
1715 ret = std::make_unique<Model<f64_3, shammath::C6>>(ctx);
1718 "unknown combination of representation and kernel");
1725 py::arg(
"vector_type"),
1726 py::arg(
"sph_kernel"));
1730 std::shared_ptr<shammodels::sph::modules::ISPHSetupNode>>(msph,
"ISPHSetupNode")
1731 .def(
"get_dot", [](std::shared_ptr<shammodels::sph::modules::ISPHSetupNode> &self) {
1732 return self->get_dot();
1735 py::class_<shammodels::sph::TimestepLog>(msph,
"TimestepLog")
1737 .def_readwrite(
"rank", &shammodels::sph::TimestepLog::rank)
1738 .def_readwrite(
"rate", &shammodels::sph::TimestepLog::rate)
1739 .def_readwrite(
"npart", &shammodels::sph::TimestepLog::npart)
1740 .def_readwrite(
"tcompute", &shammodels::sph::TimestepLog::tcompute)
1741 .def(
"rate_sum", &shammodels::sph::TimestepLog::rate_sum)
1742 .def(
"npart_sum", &shammodels::sph::TimestepLog::npart_sum);
1744 add_analysisBarycenter_instance<f64_3, shammath::M4>(msph,
"AnalysisBarycenter_f64_3_M4");
1745 add_analysisBarycenter_instance<f64_3, shammath::M6>(msph,
"AnalysisBarycenter_f64_3_M6");
1746 add_analysisBarycenter_instance<f64_3, shammath::M8>(msph,
"AnalysisBarycenter_f64_3_M8");
1748 add_analysisBarycenter_instance<f64_3, shammath::C2>(msph,
"AnalysisBarycenter_f64_3_C2");
1749 add_analysisBarycenter_instance<f64_3, shammath::C4>(msph,
"AnalysisBarycenter_f64_3_C4");
1750 add_analysisBarycenter_instance<f64_3, shammath::C6>(msph,
"AnalysisBarycenter_f64_3_C6");
1752 add_analysisEnergyKinetic_instance<f64_3, shammath::M4>(msph,
"AnalysisEnergyKinetic_f64_3_M4");
1753 add_analysisEnergyKinetic_instance<f64_3, shammath::M6>(msph,
"AnalysisEnergyKinetic_f64_3_M6");
1754 add_analysisEnergyKinetic_instance<f64_3, shammath::M8>(msph,
"AnalysisEnergyKinetic_f64_3_M8");
1756 add_analysisEnergyKinetic_instance<f64_3, shammath::C2>(msph,
"AnalysisEnergyKinetic_f64_3_C2");
1757 add_analysisEnergyKinetic_instance<f64_3, shammath::C4>(msph,
"AnalysisEnergyKinetic_f64_3_C4");
1758 add_analysisEnergyKinetic_instance<f64_3, shammath::C6>(msph,
"AnalysisEnergyKinetic_f64_3_C6");
1760 add_analysisEnergyPotential_instance<f64_3, shammath::M4>(
1761 msph,
"AnalysisEnergyPotential_f64_3_M4");
1762 add_analysisEnergyPotential_instance<f64_3, shammath::M6>(
1763 msph,
"AnalysisEnergyPotential_f64_3_M6");
1764 add_analysisEnergyPotential_instance<f64_3, shammath::M8>(
1765 msph,
"AnalysisEnergyPotential_f64_3_M8");
1767 add_analysisEnergyPotential_instance<f64_3, shammath::C2>(
1768 msph,
"AnalysisEnergyPotential_f64_3_C2");
1769 add_analysisEnergyPotential_instance<f64_3, shammath::C4>(
1770 msph,
"AnalysisEnergyPotential_f64_3_C4");
1771 add_analysisEnergyPotential_instance<f64_3, shammath::C6>(
1772 msph,
"AnalysisEnergyPotential_f64_3_C6");
1774 add_analysisTotalMomentum_instance<f64_3, shammath::M4>(msph,
"AnalysisTotalMomentum_f64_3_M4");
1775 add_analysisTotalMomentum_instance<f64_3, shammath::M6>(msph,
"AnalysisTotalMomentum_f64_3_M6");
1776 add_analysisTotalMomentum_instance<f64_3, shammath::M8>(msph,
"AnalysisTotalMomentum_f64_3_M8");
1778 add_analysisTotalMomentum_instance<f64_3, shammath::C2>(msph,
"AnalysisTotalMomentum_f64_3_C2");
1779 add_analysisTotalMomentum_instance<f64_3, shammath::C4>(msph,
"AnalysisTotalMomentum_f64_3_C4");
1780 add_analysisTotalMomentum_instance<f64_3, shammath::C6>(msph,
"AnalysisTotalMomentum_f64_3_C6");
1782 add_analysisAngularMomentum_instance<f64_3, shammath::M4>(
1783 msph,
"AnalysisAngularMomentum_f64_3_M4");
1784 add_analysisAngularMomentum_instance<f64_3, shammath::M6>(
1785 msph,
"AnalysisAngularMomentum_f64_3_M6");
1786 add_analysisAngularMomentum_instance<f64_3, shammath::M8>(
1787 msph,
"AnalysisAngularMomentum_f64_3_M8");
1789 add_analysisAngularMomentum_instance<f64_3, shammath::C2>(
1790 msph,
"AnalysisAngularMomentum_f64_3_C2");
1791 add_analysisAngularMomentum_instance<f64_3, shammath::C4>(
1792 msph,
"AnalysisAngularMomentum_f64_3_C4");
1793 add_analysisAngularMomentum_instance<f64_3, shammath::C6>(
1794 msph,
"AnalysisAngularMomentum_f64_3_C6");
1796 register_analysis_impl_for_each_kernel<modules::AnalysisBarycenter>(msph,
"analysisBarycenter");
1797 register_analysis_impl_for_each_kernel<modules::AnalysisEnergyKinetic>(
1798 msph,
"analysisEnergyKinetic");
1799 register_analysis_impl_for_each_kernel<modules::AnalysisEnergyPotential>(
1800 msph,
"analysisEnergyPotential");
1801 register_analysis_impl_for_each_kernel<modules::AnalysisTotalMomentum>(
1802 msph,
"analysisTotalMomentum");
1803 register_analysis_impl_for_each_kernel<modules::AnalysisAngularMomentum>(
1804 msph,
"analysisAngularMomentum");
1806 add_analysisDustMass_instance<f64_3, shammath::M4>(msph,
"AnalysisDustMass_f64_3_M4");
1807 add_analysisDustMass_instance<f64_3, shammath::M6>(msph,
"AnalysisDustMass_f64_3_M6");
1808 add_analysisDustMass_instance<f64_3, shammath::M8>(msph,
"AnalysisDustMass_f64_3_M8");
1810 add_analysisDustMass_instance<f64_3, shammath::C2>(msph,
"AnalysisDustMass_f64_3_C2");
1811 add_analysisDustMass_instance<f64_3, shammath::C4>(msph,
"AnalysisDustMass_f64_3_C4");
1812 add_analysisDustMass_instance<f64_3, shammath::C6>(msph,
"AnalysisDustMass_f64_3_C6");
1814 register_analysis_impl_for_each_kernel<modules::AnalysisDustMass>(msph,
"analysisDustMass");
AnalysisAngularMomentum class.
AnalysisBarycenter class with one method AnalysisBarycenter.get_barycenter().
AnalysisEnergyKinetic class with one method AnalysisEnergyKinetic.get_kinetic_energy().
AnalysisEnergyPotential class with one method AnalysisEnergyPotential.get_potential_energy().
AnalysisTotalMomentum class with one method AnalysisTotalMomentum.get_total_momentum().
double f64
Alias for double.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
std::uint16_t u16
16 bit unsigned integer
std::int32_t i32
32 bit integer
This class is an interface that all SPH setup nodes must implement. It describe an operation associat...
This header file contains utility functions related to exception handling in the code.
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.
i32 world_rank()
Gives the rank of the current process in the MPI communicator.
std::shared_ptr< ISPHSetupNode > SetupNodePtr
Alias for a shared pointer to an ISPHSetupNode.
namespace for the sph model
Pybind11 include and definitions.
#define ON_PYTHON_INIT
Register a Python module init function using static initialization.
void warn_ln(std::string module_name, Types... var2)
Prints a log message with multiple arguments followed by a newline.
Utilities to convert JSON objects to Python objects and vice versa. TODO: try to convert directly wit...
Ray representation for intersection testing.
Ring ray representation for intersection testing.
Class representing a Phantom dump file.
Functions related to the MPI communicator.
#define ON_RANK_0(x)
Macro to execute code only on rank 0.