43#include <pybind11/cast.h>
44#include <pybind11/numpy.h>
45#include <pybind11/pytypes.h>
51template<
class Tvec,
template<
class>
class SPHKernel>
52void add_instance(py::module &m, std::string name_config, std::string name_model) {
55 using Tscal = shambase::VecComponent<Tvec>;
62 using TConfig =
typename T::Solver::Config;
64 using custom_getter_t = std::function<pybind11::array_t<f64>(
size_t, pybind11::dict &)>;
66 shamlog_debug_ln(
"[Py]",
"registering class :", name_config,
typeid(T).name());
67 shamlog_debug_ln(
"[Py]",
"registering class :", name_model,
typeid(T).name());
69 py::class_<TConfig> config_cls(m, name_config.c_str());
71 shammodels::common::add_json_defs<TConfig>(config_cls);
73 config_cls.def(
"print_status", &TConfig::print_status)
74 .def(
"set_particle_tracking", &TConfig::set_particle_tracking)
76 "set_scheduler_config",
77 [](TConfig &self,
u64 split_crit,
u64 merge_crit) {
78 self.scheduler_conf.split_load_value = split_crit;
79 self.scheduler_conf.merge_load_value = merge_crit;
82 py::arg(
"split_load_value"),
83 py::arg(
"merge_load_value"))
84 .def(
"set_tree_reduction_level", &TConfig::set_tree_reduction_level)
85 .def(
"set_two_stage_search", &TConfig::set_two_stage_search)
86 .def(
"set_show_neigh_stats", &TConfig::set_show_neigh_stats)
88 "set_max_neigh_cache_size",
89 [](TConfig &self,
const py::object &max_neigh_cache_size) {
92 ".set_max_neigh_cache_size() is deprecated,\n"
93 " -> calling this is a no-op,\n"
94 " -> you can remove the call to that function"););
96 .def(
"set_smoothing_length_density_based", &TConfig::set_smoothing_length_density_based)
98 "set_smoothing_length_density_based_neigh_lim",
99 &TConfig::set_smoothing_length_density_based_neigh_lim)
100 .def(
"set_enable_particle_reordering", &TConfig::set_enable_particle_reordering)
101 .def(
"set_particle_reordering_step_freq", &TConfig::set_particle_reordering_step_freq)
102 .def(
"set_show_ghost_zone_graph", &TConfig::set_show_ghost_zone_graph)
103 .def(
"use_luminosity", &TConfig::use_luminosity)
104 .def(
"set_save_dt_to_fields", &TConfig::set_save_dt_to_fields)
105 .def(
"should_save_dt_to_fields", &TConfig::should_save_dt_to_fields)
106 .def(
"set_eos_isothermal", &TConfig::set_eos_isothermal)
107 .def(
"set_eos_adiabatic", &TConfig::set_eos_adiabatic)
108 .def(
"set_eos_polytropic", &TConfig::set_eos_polytropic)
109 .def(
"set_eos_locally_isothermal", &TConfig::set_eos_locally_isothermal)
111 "set_eos_locally_isothermalLP07",
112 [](TConfig &self, Tscal cs0, Tscal q, Tscal r0) {
113 self.set_eos_locally_isothermalLP07(cs0, q, r0);
120 "set_eos_locally_isothermalFA2014",
121 [](TConfig &self, Tscal h_over_r) {
122 self.set_eos_locally_isothermalFA2014(h_over_r);
127 "set_eos_locally_isothermalFA2014_extended",
128 [](TConfig &self, Tscal cs0, Tscal q, Tscal r0,
u32 n_sinks) {
129 self.set_eos_locally_isothermalFA2014_extended(cs0, q, r0, n_sinks);
138 [](TConfig &self, Tscal mu_e) {
139 self.set_eos_fermi(mu_e);
143 .def(
"set_artif_viscosity_None", &TConfig::set_artif_viscosity_None)
145 "set_artif_viscosity_Constant",
146 [](TConfig &self, Tscal alpha_u, Tscal alpha_AV, Tscal beta_AV) {
147 self.set_artif_viscosity_Constant({alpha_u, alpha_AV, beta_AV});
154 "set_artif_viscosity_VaryingMM97",
161 self.set_artif_viscosity_VaryingMM97(
162 {alpha_min, alpha_max, sigma_decay, alpha_u, beta_AV});
165 py::arg(
"alpha_min"),
166 py::arg(
"alpha_max"),
167 py::arg(
"sigma_decay"),
171 "set_artif_viscosity_VaryingCD10",
178 self.set_artif_viscosity_VaryingCD10(
179 {alpha_min, alpha_max, sigma_decay, alpha_u, beta_AV});
182 py::arg(
"alpha_min"),
183 py::arg(
"alpha_max"),
184 py::arg(
"sigma_decay"),
188 "set_artif_viscosity_ConstantDisc",
189 [](TConfig &self, Tscal alpha_AV, Tscal alpha_u, Tscal beta_AV) {
190 self.set_artif_viscosity_ConstantDisc({alpha_AV, alpha_u, beta_AV});
198 [](TConfig &self, Tscal sigma_mhd, Tscal sigma_u) {
199 self.set_IdealMHD({sigma_mhd, sigma_u});
202 py::arg(
"sigma_mhd"),
205 "set_self_gravity_none",
207 self.self_grav_config.set_none();
210 "set_self_gravity_direct",
211 [](TConfig &self,
bool reference_mode =
false) {
212 self.self_grav_config.set_direct(reference_mode);
215 py::arg(
"reference_mode") =
false)
217 "set_self_gravity_mm",
218 [](TConfig &self,
u32 mm_order,
f64 opening_angle,
u32 reduction_level) {
219 self.self_grav_config.set_mm(mm_order, opening_angle, reduction_level);
223 py::arg(
"opening_angle"),
224 py::arg(
"reduction_level") = 3)
226 "set_self_gravity_fmm",
227 [](TConfig &self,
u32 order,
f64 opening_angle,
u32 reduction_level) {
228 self.self_grav_config.set_fmm(order, opening_angle, reduction_level);
232 py::arg(
"opening_angle"),
233 py::arg(
"reduction_level") = 3)
235 "set_self_gravity_sfmm",
240 u32 reduction_level) {
241 self.self_grav_config.set_sfmm(
242 sfmm_order, opening_angle, leaf_lowering, reduction_level);
246 py::arg(
"opening_angle"),
247 py::arg(
"leaf_lowering") =
true,
248 py::arg(
"reduction_level") = 3)
250 "set_softening_plummer",
251 [](TConfig &self,
f64 epsilon) {
252 self.self_grav_config.set_softening_plummer(epsilon);
257 "set_softening_none",
259 self.self_grav_config.set_softening_none();
261 .def(
"set_boundary_free", &TConfig::set_boundary_free)
262 .def(
"set_boundary_periodic", &TConfig::set_boundary_periodic)
263 .def(
"set_boundary_shearing_periodic", &TConfig::set_boundary_shearing_periodic)
265 "set_dust_mode_none",
267 self.dust_config.set_none();
270 "set_dust_mode_monofluid_tva",
273 bool pure_diffusion_mode,
276 Tscal cfl_density_threshold,
277 bool ensure_s_j_positivity,
278 bool smooth_s_positivity_limiter,
279 bool dust_corrected_av) {
280 self.dust_config.set_monofluid_tva(
285 cfl_density_threshold,
286 ensure_s_j_positivity,
287 smooth_s_positivity_limiter,
292 py::arg(
"pure_diffusion_mode") =
false,
293 py::arg(
"C_1_fluid") = 0.1,
294 py::arg(
"C_drift") = 1.0,
295 py::arg(
"cfl_density_threshold") = shambase::get_epsilon<Tscal>(),
296 py::arg(
"ensure_s_j_positivity") =
true,
297 py::arg(
"smooth_s_positivity_limiter") =
false,
298 py::arg(
"dust_corrected_av") =
false)
300 "set_dust_mode_monofluid_complete",
301 [](TConfig &self,
u32 ndust) {
302 self.dust_config.set_monofluid_complete(ndust);
307 "set_dust_drag_constant",
308 [](TConfig &self, std::vector<Tscal> ts) {
309 self.dust_config.set_drag_constant({.stopping_times = std::move(ts)});
312 "set_dust_drag_epstein",
315 std::vector<Tscal> grain_sizes,
316 std::vector<Tscal> grain_densities) {
317 self.dust_config.set_drag_epstein(
319 .grains_sizes = std::move(grain_sizes),
320 .grains_densities = std::move(grain_densities)});
323 py::arg(
"grain_sizes"),
324 py::arg(
"grain_densities"))
326 "set_dust_ballabio_ts_limiter",
327 [](TConfig &self,
bool enabled) {
328 self.dust_config.ballabio_ts_limiter = enabled;
331 .def(
"add_ext_force_point_mass", &TConfig::add_ext_force_point_mass)
332 .def(
"add_ext_force_paczynski_wiita", &TConfig::add_ext_force_paczynski_wiita)
334 "add_ext_force_lense_thirring",
335 [](TConfig &self, Tscal central_mass, Tscal Racc, Tscal a_spin, Tvec dir_spin) {
336 self.add_ext_force_lense_thirring(central_mass, Racc, a_spin, dir_spin);
339 py::arg(
"central_mass"),
344 "add_ext_force_shearing_box",
345 [](TConfig &self, Tscal Omega_0, Tscal eta, Tscal q) {
346 self.add_ext_force_shearing_box(Omega_0, eta, q);
353 "add_ext_force_velocity_dissipation",
354 [](TConfig &self, Tscal eta) {
355 self.ext_force_config.add_velocity_dissipation(eta);
360 "add_ext_force_vertical_disc_potential",
361 [](TConfig &self, Tscal central_mass, Tscal R0) {
362 self.ext_force_config.add_vertical_disc_potential(central_mass, R0);
365 py::arg(
"central_mass"),
367 .def(
"set_units", &TConfig::set_units)
371 return self.unit_sys;
375 [](TConfig &self, Tscal cfl_cour) {
376 self.cfl_config.cfl_cour = cfl_cour;
380 [](TConfig &self, Tscal cfl_force) {
381 self.cfl_config.cfl_force = cfl_force;
385 [](TConfig &self, Tscal eta_sink) {
386 self.cfl_config.eta_sink = eta_sink;
388 .def(
"set_cfl_mult_stiffness", &TConfig::set_cfl_mult_stiffness)
390 "set_show_cfl_detail",
391 [](TConfig &self,
bool show_cfl_detail) {
392 self.show_cfl_detail = show_cfl_detail;
394 py::arg(
"show_cfl_detail"))
397 [](TConfig &self, Tscal gpart_mass) {
398 self.gpart_mass = gpart_mass;
402 [](TConfig &self,
const Tvec ¢er, Tscal radius) {
403 self.particle_killing.add_kill_sphere(center, radius);
409 std::string sod_tube_analysis_name = name_model +
"_AnalysisSodTube";
410 py::class_<TAnalysisSodTube>(m, sod_tube_analysis_name.c_str())
411 .def(
"compute_L2_dist", [](TAnalysisSodTube &self) -> std::tuple<Tscal, Tvec, Tscal> {
412 auto ret = self.compute_L2_dist();
413 return {ret.rho, ret.v, ret.P};
416 std::string disc_analysis_name = name_model +
"_AnalysisDisc";
417 py::class_<TAnalysisDisc>(m, disc_analysis_name.c_str())
420 [](TAnalysisDisc &self, Tscal Rmin, Tscal Rmax,
u32 Nbin,
ShamrockCtx &ctx) {
421 auto anal = self.compute_analysis(Rmin, Rmax, Nbin, ctx);
424 auto radius = anal.radius.copy_to_stdvec();
425 auto counter = anal.counter.copy_to_stdvec();
426 auto Sigma = anal.Sigma.copy_to_stdvec();
427 auto lx = anal.lx.copy_to_stdvec();
428 auto ly = anal.ly.copy_to_stdvec();
429 auto lz = anal.lz.copy_to_stdvec();
430 auto tilt = anal.tilt.copy_to_stdvec();
431 auto twist = anal.twist.copy_to_stdvec();
432 auto psi = anal.psi.copy_to_stdvec();
433 auto Hsq = anal.Hsq.copy_to_stdvec();
435 dic_out[
"radius"] = radius;
436 dic_out[
"counter"] = counter;
437 dic_out[
"Sigma"] = Sigma;
441 dic_out[
"tilt"] = tilt;
442 dic_out[
"twist"] = twist;
443 dic_out[
"psi"] = psi;
444 dic_out[
"Hsq"] = Hsq;
449 std::string setup_name = name_model +
"_SPHSetup";
450 py::class_<TSPHSetup>(m, setup_name.c_str())
452 "make_generator_lattice_hcp",
453 [](TSPHSetup &self, Tscal dr, Tvec box_min, Tvec box_max,
bool discontinuous) {
454 return self.make_generator_lattice_hcp(dr, {box_min, box_max}, discontinuous);
459 py::arg(
"discontinuous") =
true)
461 "make_generator_lattice_cubic",
462 [](TSPHSetup &self, Tscal dr, Tvec box_min, Tvec box_max) {
463 return self.make_generator_lattice_cubic(dr, {box_min, box_max});
466 "make_generator_disc_mc",
472 std::function<Tscal(Tscal)> sigma_profile,
473 std::function<Tscal(Tscal)> H_profile,
474 std::function<Tscal(Tscal)> rot_profile,
475 std::function<Tscal(Tscal)> cs_profile,
476 std::function<Tvec(Tvec)> velocity_field,
477 std::function<Tscal(Tvec)> cs_field,
479 Tscal init_h_factor) {
480 auto build_vel_lambda = [&]() -> std::function<Tvec(Tvec)> {
481 if (!velocity_field && !rot_profile) {
483 "make_generator_disc_mc: either velocity_field or rot_profile must be "
484 "provided, you must provide one of them");
487 if (velocity_field && rot_profile) {
489 "make_generator_disc_mc: either velocity_field or rot_profile must be "
490 "provided, you cannot provide both");
493 if (velocity_field) {
494 return std::move(velocity_field);
496 return [vth_r = std::move(rot_profile)](Tvec pos) {
498 Tscal r = sycl::length(pos);
500 auto etheta = sycl::vec<Tscal, 3>{-pos.y(), pos.x(), 0};
501 etheta /= sycl::length(etheta);
503 return vth_r(r) * etheta;
507 auto build_cs_lambda = [&]() -> std::function<Tscal(Tvec)> {
508 bool need_cs = self.solver_config.is_eos_locally_isothermal();
515 "make_generator_disc_mc: with the current EOS, cs_field is "
523 "make_generator_disc_mc: with the current EOS, cs_profile is "
527 return std::function<Tscal(Tvec)>{};
530 if (!cs_field && !cs_profile) {
532 "make_generator_disc_mc: either cs_field or cs_profile must be "
533 "provided, you must provide one of them");
536 if (cs_field && cs_profile) {
538 "make_generator_disc_mc: either cs_field or cs_profile must be "
539 "provided, you cannot provide both");
543 return std::move(cs_field);
546 return [cs_r = std::move(cs_profile)](Tvec pos) {
548 Tscal r = sycl::length(pos);
553 return self.make_generator_disc_mc(
558 std::move(sigma_profile),
559 std::move(H_profile),
562 std::mt19937_64(random_seed),
566 py::arg(
"part_mass"),
567 py::arg(
"disc_mass"),
570 py::arg(
"sigma_profile"),
571 py::arg(
"H_profile"),
572 py::arg(
"rot_profile") = std::function<Tscal(Tscal)>{},
573 py::arg(
"cs_profile") = std::function<Tscal(Tscal)>{},
574 py::arg(
"velocity_field") = std::function<Tvec(Tvec)>{},
575 py::arg(
"cs_field") = std::function<Tscal(Tvec)>{},
576 py::arg(
"random_seed"),
577 py::arg(
"init_h_factor") = 0.8,
579 Create a Monte Carlo disc particle generator.
581 Particles are sampled in cylindrical coordinates: the radius is drawn
582 with rejection sampling from ``sigma_profile``, the azimuth is uniform,
583 and the vertical coordinate follows a Gaussian with scale ``H_profile(r)``.
584 The initial density is extrapolated from the surface density profile, and
585 smoothing lengths are set from that density.
588 part_mass: Mass of each SPH particle.
589 disc_mass: Total disc mass. The particle count is ``disc_mass / part_mass``.
590 r_in: Inner disc radius.
591 r_out: Outer disc radius.
592 sigma_profile: Surface density profile ``sigma(r)``.
593 H_profile: Disc scale height profile ``H(r)``.
594 rot_profile: Azimuthal speed profile ``v_theta(r)``. The velocity is
595 projected along the cylindrical azimuthal direction at each
596 particle position. Mutually exclusive with ``velocity_field``.
597 cs_profile: Sound speed profile ``c_s(r)``. Evaluated at the cylindrical
598 radius of each particle. Required when the solver uses a locally
599 isothermal EOS. Mutually exclusive with ``cs_field``.
600 velocity_field: Velocity profile ``v(x, y, z)``. Mutually exclusive
601 with ``rot_profile``.
602 cs_field: Sound speed profile ``c_s(x, y, z)``. Required when the solver
603 uses a locally isothermal EOS. Mutually exclusive with ``cs_profile``.
604 random_seed: Seed for the Monte Carlo sampler.
605 init_h_factor: Multiplier applied to the smoothing length inferred from
606 the generated density. Defaults to ``0.8``.
609 Exactly one of ``velocity_field`` or ``rot_profile`` must be provided.
611 If the solver uses a locally isothermal EOS, exactly one of ``cs_field``
612 or ``cs_profile`` must be provided. Otherwise both sound-speed profiles
613 are ignored and a warning is emitted if either is supplied.
616 A setup node to pass to :py:meth:`apply_setup`.
619 "make_generator_from_context",
621 return self.make_generator_from_context(context_other);
628 return self.make_combiner_add(parent1, parent2);
631 "make_modifier_warp_disc",
638 return self.make_modifier_warp_disc(parent, Rwarp, Hwarp, inclination, posangle);
644 py::arg(
"inclination"),
645 py::arg(
"posangle") = 0.)
647 "make_modifier_custom_warp",
650 std::function<Tscal(Tscal)> inc_profile,
651 std::function<Tscal(Tscal)> psi_profile,
652 std::function<Tvec(Tscal)> k_profile) {
653 return self.make_modifier_custom_warp(parent, inc_profile, psi_profile, k_profile);
657 py::arg(
"inc_profile"),
658 py::arg(
"psi_profile"),
659 py::arg(
"k_profile"))
661 "make_modifier_offset",
665 Tvec offset_velocity) {
666 return self.make_modifier_add_offset(parent, offset_postion, offset_velocity);
670 py::arg(
"offset_position"),
671 py::arg(
"offset_velocity"))
673 "make_modifier_filter",
676 std::function<
bool(Tvec)> filter) {
677 return self.make_modifier_filter(parent, filter);
683 "make_modifier_split_part",
689 return self.make_modifier_split_part(parent, n_split, seed, h_scaling);
695 py::arg(
"h_scaling") = 0.6)
700 bool part_reordering,
701 std::optional<u32> gen_step,
702 std::optional<u32> insert_step,
703 std::optional<u64> msg_count_limit,
704 std::optional<u64> msg_size_limit,
705 std::optional<u64> max_msg_size,
708 bool speculative_balancing) {
710 return self.apply_setup_new(
719 speculative_balancing);
721 if (
bool(gen_step)) {
724 "SPHSetup",
"gen_step is ignored when using old setup"));
726 if (
bool(msg_count_limit)) {
729 "SPHSetup",
"msg_count_limit is ignored when using old setup"));
731 if (
bool(msg_size_limit)) {
734 "SPHSetup",
"msg_size_limit is ignored when using old setup"));
736 if (
bool(max_msg_size)) {
739 "SPHSetup",
"max_msg_size is ignored when using old setup"));
741 if (
bool(do_setup_log)) {
744 "SPHSetup",
"do_setup_log is ignored when using old setup"));
746 return self.apply_setup(setup, part_reordering, insert_step);
751 py::arg(
"part_reordering") =
true,
752 py::arg(
"gen_step") = std::nullopt,
753 py::arg(
"insert_step") = std::nullopt,
754 py::arg(
"msg_count_limit") = std::nullopt,
755 py::arg(
"rank_comm_size_limit") = std::nullopt,
756 py::arg(
"max_msg_size") = std::nullopt,
757 py::arg(
"do_setup_log") =
false,
758 py::arg(
"use_new_setup") =
true,
759 py::arg(
"speculative_balancing") =
false);
761 py::class_<T>(m, name_model.c_str())
763 return std::make_unique<T>(ctx);
765 .def(
"init", &T::init)
766 .def(
"init_scheduler", &T::init_scheduler)
769 "evolve_once_override_time",
770 &T::evolve_once_time_expl,
773 .def(
"evolve_once", &T::evolve_once)
776 [](T &self,
f64 target_time,
i32 niter_max,
f64 max_walltime) {
777 return self.evolve_until(target_time, niter_max, max_walltime);
779 py::arg(
"target_time"),
781 py::arg(
"niter_max") = -1,
782 py::arg(
"max_walltime") = -1)
783 .def(
"timestep", &T::timestep)
784 .def(
"set_cfl_cour", &T::set_cfl_cour, py::arg(
"cfl_cour"))
785 .def(
"set_cfl_force", &T::set_cfl_force, py::arg(
"cfl_force"))
786 .def(
"set_eta_sink", &T::set_eta_sink, py::arg(
"eta_sink"))
787 .def(
"set_particle_mass", &T::set_particle_mass, py::arg(
"gpart_mass"))
788 .def(
"get_particle_mass", &T::get_particle_mass)
789 .def(
"rho_h", &T::rho_h)
790 .def(
"get_hfact", &T::get_hfact)
797 "get_solver_dot_graph",
802 "get_box_dim_fcc_3d",
804 return self.get_box_dim_fcc_3d(dr, xcnt, ycnt, zcnt);
808 [](T &self,
f64 dr, f64_3 box_min, f64_3 box_max) {
812 "The python function get_ideal_fcc_box is deprecated in the SPH model and "
813 "will be removed at some point, replace it by "
814 "shamrock.math.get_ideal_hcp_box"));
815 return shammath::LatticeHCP<f64_3>::get_ideal_hcp_box(dr, {box_min, box_max});
819 [](T &self,
f64 dr, f64_3 box_min, f64_3 box_max) {
823 "The python function get_ideal_hcp_box is deprecated in the SPH model and "
824 "will be removed at some point, replace it by "
825 "shamrock.math.get_ideal_hcp_box"));
826 return shammath::LatticeHCP<f64_3>::get_ideal_hcp_box(dr, {box_min, box_max});
829 "resize_simulation_box",
830 [](T &self, f64_3 box_min, f64_3 box_max) {
831 return self.resize_simulation_box({box_min, box_max});
835 [](T &self, std::vector<f64_3> pos, std::vector<f64> hpart, std::vector<f64> upart) {
836 return self.push_particle(pos, hpart, upart);
841 std::vector<f64_3> pos,
842 std::vector<f64> hpart,
843 std::vector<f64> upart,
844 std::vector<f64_3> B_on_rho,
845 std::vector<f64> psi_on_ch) {
846 return self.push_particle_mhd(pos, hpart, upart, B_on_rho, psi_on_ch);
850 [](T &self,
f64 dr, f64_3 box_min, f64_3 box_max) {
851 return self.add_cube_fcc_3d(dr, {box_min, box_max});
855 [](T &self,
f64 dr, f64_3 box_min, f64_3 box_max) {
856 return self.add_cube_hcp_3d(dr, {box_min, box_max});
859 "add_cube_hcp_3d_v2",
860 [](T &self,
f64 dr, f64_3 box_min, f64_3 box_max) {
861 return self.add_cube_hcp_3d_v2(dr, {box_min, box_max});
864 "add_disc_3d_keplerian",
875 return self.add_cube_disc_3d(center, Npart, p, rho_0, m, r_in, r_out, q, cmass);
889 return self.add_disc_3d(
890 center, central_mass, Npart, r_in, r_out, disc_mass, p, H_r_in, q);
905 self.add_big_disc_3d(
916 return disc_mass / Npart;
918 .def(
"get_total_part_count", &T::get_total_part_count)
919 .def(
"total_mass_to_part_mass", &T::total_mass_to_part_mass)
921 "set_value_in_a_box",
923 const std::string &field_name,
924 const std::string &field_type,
925 const pybind11::object &value,
929 if (field_type ==
"f64") {
930 f64 val = value.cast<
f64>();
931 self.set_value_in_a_box(field_name, val, {box_min, box_max}, ivar);
932 }
else if (field_type ==
"f64_3") {
933 f64_3 val = value.cast<f64_3>();
934 self.set_value_in_a_box(field_name, val, {box_min, box_max}, ivar);
937 "unknown field type");
940 py::arg(
"field_name"),
941 py::arg(
"field_type"),
948 "set_value_in_sphere",
950 const std::string &field_name,
951 const std::string &field_type,
952 const pybind11::object &value,
955 if (field_type ==
"f64") {
956 f64 val = value.cast<
f64>();
957 self.set_value_in_sphere(field_name, val, center, radius);
958 }
else if (field_type ==
"f64_3") {
959 f64_3 val = value.cast<f64_3>();
960 self.set_value_in_sphere(field_name, val, center, radius);
963 "unknown field type");
967 "set_field_value_lambda_f64",
969 std::string field_name,
970 const std::function<
f64(Tvec)> pos_to_val,
972 return self.template set_field_value_lambda<f64>(
973 std::move(field_name), pos_to_val, offset);
975 py::arg(
"field_name"),
976 py::arg(
"pos_to_val"),
977 py::arg(
"offset") = 0)
979 "set_field_value_lambda_f64_3",
981 std::string field_name,
982 const std::function<f64_3(Tvec)> pos_to_val,
984 return self.template set_field_value_lambda<f64_3>(
985 std::move(field_name), pos_to_val, offset);
987 py::arg(
"field_name"),
988 py::arg(
"pos_to_val"),
989 py::arg(
"offset") = 0)
990 .def(
"overwrite_field_value_f64", &T::template overwrite_field_value<f64>)
991 .def(
"overwrite_field_value_f64_3", &T::template overwrite_field_value<f64_3>)
992 .def(
"remap_positions", &T::remap_positions)
1002 const std::string &field_name,
1003 const std::string &field_type,
1004 const pybind11::object &value,
1007 if (field_type ==
"f64") {
1008 f64 val = value.cast<
f64>();
1009 self.add_kernel_value(field_name, val, center, h_ker);
1010 }
else if (field_type ==
"f64_3") {
1011 f64_3 val = value.cast<f64_3>();
1012 self.add_kernel_value(field_name, val, center, h_ker);
1015 "unknown field type");
1020 [](T &self,
const std::string &field_name,
const std::string &field_type) {
1021 if (field_type ==
"f64") {
1022 return py::cast(self.template get_sum<f64>(field_name));
1023 }
else if (field_type ==
"f64_3") {
1024 return py::cast(self.template get_sum<f64_3>(field_name));
1027 "unknown field type");
1031 "get_closest_part_to",
1032 [](T &self, f64_3 pos) -> f64_3 {
1033 return self.get_closest_part_to(pos);
1036 "gen_default_config",
1038 return typename T::Solver::Config{};
1041 "get_current_config",
1043 return self.solver.solver_config;
1045 .def(
"set_solver_config", &T::set_solver_config)
1046 .def(
"add_sink", &T::add_sink)
1056 sink_dic[
"pos"] = sink.pos;
1057 sink_dic[
"velocity"] = sink.velocity;
1058 sink_dic[
"sph_acceleration"] = sink.sph_acceleration;
1059 sink_dic[
"ext_acceleration"] = sink.ext_acceleration;
1060 sink_dic[
"mass"] = sink.mass;
1061 sink_dic[
"angular_momentum"] = sink.angular_momentum;
1062 sink_dic[
"accretion_radius"] = sink.accretion_radius;
1063 list_out.append(sink_dic);
1071 return self.solver.solver_config.unit_sys;
1076 const std::string &name,
1077 const std::string &field_type,
1078 const std::vector<Tvec> &positions,
1079 const std::optional<custom_getter_t> &custom_getter)
1080 -> std::variant<std::vector<f64>, std::vector<f64_3>> {
1081 if (custom_getter.has_value()) {
1082 if (!(name ==
"custom" && field_type ==
"f64")) {
1084 "custom_getter only available for name=custom and field_type=f64");
1088 if (field_type ==
"f64") {
1090 self.ctx, self.solver.solver_config, self.solver.storage);
1091 return render.compute_slice(name, positions, custom_getter).copy_to_stdvec();
1094 if (field_type ==
"f64_3") {
1096 self.ctx, self.solver.solver_config, self.solver.storage);
1097 return render.compute_slice(name, positions, std::nullopt).copy_to_stdvec();
1103 py::arg(
"field_type"),
1104 py::arg(
"positions"),
1105 py::arg(
"custom_getter") = std::nullopt)
1107 "render_column_integ",
1109 const std::string &name,
1110 const std::string &field_type,
1112 const std::optional<custom_getter_t> &custom_getter)
1113 -> std::variant<std::vector<f64>, std::vector<f64_3>> {
1114 if (custom_getter.has_value()) {
1115 if (!(name ==
"custom" && field_type ==
"f64")) {
1117 "custom_getter only available for name=custom and field_type=f64");
1121 if (field_type ==
"f64") {
1123 self.ctx, self.solver.solver_config, self.solver.storage);
1124 return render.compute_column_integ(name, rays, custom_getter).copy_to_stdvec();
1127 if (field_type ==
"f64_3") {
1129 self.ctx, self.solver.solver_config, self.solver.storage);
1130 return render.compute_column_integ(name, rays, std::nullopt).copy_to_stdvec();
1136 py::arg(
"field_type"),
1138 py::arg(
"custom_getter") = std::nullopt)
1142 const std::string &name,
1143 const std::string &field_type,
1144 const std::optional<custom_getter_t> &custom_getter)
1148 if (custom_getter.has_value()) {
1149 if (!(name ==
"custom" && field_type ==
"f64")) {
1151 "custom_getter only available for name=custom and field_type=f64");
1155 if (field_type ==
"f64") {
1157 self.ctx, self.solver.solver_config, self.solver.storage);
1158 return render_field_getter.build_field(name, custom_getter);
1161 if (field_type ==
"f64_3") {
1163 self.ctx, self.solver.solver_config, self.solver.storage);
1164 return render_field_getter.build_field(name, custom_getter);
1170 py::arg(
"field_type"),
1171 py::arg(
"custom_getter") = std::nullopt)
1173 "render_azymuthal_integ",
1175 const std::string &name,
1176 const std::string &field_type,
1178 const std::optional<custom_getter_t> &custom_getter)
1179 -> std::variant<std::vector<f64>, std::vector<f64_3>> {
1180 if (custom_getter.has_value()) {
1181 if (!(name ==
"custom" && field_type ==
"f64")) {
1183 "custom_getter only available for name=custom and field_type=f64");
1187 if (field_type ==
"f64") {
1189 self.ctx, self.solver.solver_config, self.solver.storage);
1190 return render.compute_azymuthal_integ(name, ring_rays, custom_getter)
1194 if (field_type ==
"f64_3") {
1196 self.ctx, self.solver.solver_config, self.solver.storage);
1197 return render.compute_azymuthal_integ(name, ring_rays, std::nullopt)
1204 py::arg(
"field_type"),
1205 py::arg(
"ring_rays"),
1206 py::arg(
"custom_getter") = std::nullopt)
1208 "render_cartesian_slice",
1210 const std::string &name,
1211 const std::string &field_type,
1217 const std::optional<custom_getter_t> &custom_getter)
1218 -> std::variant<py::array_t<Tscal>> {
1219 if (custom_getter.has_value()) {
1220 if (!(name ==
"custom" && field_type ==
"f64")) {
1222 "custom_getter only available for name=custom and field_type=f64");
1226 if (field_type ==
"f64") {
1227 py::array_t<Tscal> ret({ny, nx});
1230 self.ctx, self.solver.solver_config, self.solver.storage);
1232 std::vector<f64> slice
1234 .compute_slice(name, center, delta_x, delta_y, nx, ny, custom_getter)
1237 for (
u32 iy = 0; iy < ny; iy++) {
1238 for (
u32 ix = 0; ix < nx; ix++) {
1239 ret.mutable_at(iy, ix) = slice[ix + nx * iy];
1246 if (field_type ==
"f64_3") {
1247 py::array_t<Tscal> ret({ny, nx, 3_u32});
1250 self.ctx, self.solver.solver_config, self.solver.storage);
1252 std::vector<f64_3> slice
1253 = render.compute_slice(name, center, delta_x, delta_y, nx, ny, std::nullopt)
1256 for (
u32 iy = 0; iy < ny; iy++) {
1257 for (
u32 ix = 0; ix < nx; ix++) {
1258 ret.mutable_at(iy, ix, 0) = slice[ix + nx * iy][0];
1259 ret.mutable_at(iy, ix, 1) = slice[ix + nx * iy][1];
1260 ret.mutable_at(iy, ix, 2) = slice[ix + nx * iy][2];
1268 return py::array_t<Tscal>({nx, ny});
1271 py::arg(
"field_type"),
1277 py::arg(
"custom_getter") = std::nullopt)
1279 "render_cartesian_column_integ",
1281 const std::string &name,
1282 const std::string &field_type,
1288 const std::optional<custom_getter_t> &custom_getter)
1289 -> std::variant<py::array_t<Tscal>> {
1290 if (custom_getter.has_value()) {
1291 if (!(name ==
"custom" && field_type ==
"f64")) {
1293 "custom_getter only available for name=custom and field_type=f64");
1297 if (field_type ==
"f64") {
1298 py::array_t<Tscal> ret({ny, nx});
1301 self.ctx, self.solver.solver_config, self.solver.storage);
1303 std::vector<f64> slice
1305 .compute_column_integ(
1306 name, center, delta_x, delta_y, nx, ny, custom_getter)
1309 for (
u32 iy = 0; iy < ny; iy++) {
1310 for (
u32 ix = 0; ix < nx; ix++) {
1311 ret.mutable_at(iy, ix) = slice[ix + nx * iy];
1318 if (field_type ==
"f64_3") {
1319 py::array_t<Tscal> ret({ny, nx, 3_u32});
1322 self.ctx, self.solver.solver_config, self.solver.storage);
1324 std::vector<f64_3> slice
1326 .compute_column_integ(
1327 name, center, delta_x, delta_y, nx, ny, std::nullopt)
1330 for (
u32 iy = 0; iy < ny; iy++) {
1331 for (
u32 ix = 0; ix < nx; ix++) {
1332 ret.mutable_at(iy, ix, 0) = slice[ix + nx * iy][0];
1333 ret.mutable_at(iy, ix, 1) = slice[ix + nx * iy][1];
1334 ret.mutable_at(iy, ix, 2) = slice[ix + nx * iy][2];
1342 return py::array_t<Tscal>({nx, ny});
1345 py::arg(
"field_type"),
1351 py::arg(
"custom_getter") = std::nullopt)
1353 "gen_config_from_phantom_dump",
1354 [](T &self,
PhantomDump &dump,
bool bypass_error) {
1355 return self.gen_config_from_phantom_dump(dump, bypass_error);
1358 py::arg(
"bypass_error") =
false,
1360 This function generate a shamrock sph solver config from a phantom dump
1365 bypass_error = false (default) bypass any error in the config
1368 "init_from_phantom_dump",
1369 [](T &self,
PhantomDump &dump, Tscal hpart_fact_load) {
1370 self.init_from_phantom_dump(dump, hpart_fact_load);
1373 py::arg(
"hpart_fact_load") = 1.0)
1375 "make_phantom_dump",
1377 return self.make_phantom_dump();
1379 .def(
"do_vtk_dump", &T::do_vtk_dump)
1380 .def(
"set_debug_dump", &T::set_debug_dump)
1381 .def(
"solver_logs_last_rate", &T::solver_logs_last_rate)
1382 .def(
"solver_logs_last_obj_count", &T::solver_logs_last_obj_count)
1384 "solver_logs_last_system_metrics",
1386 auto system_metrics = self.solver.solve_logs.get_last_system_metrics();
1388 ret[
"duration"] = system_metrics.wall_time;
1389 if (system_metrics.rank_energy_consummed.has_value()) {
1390 ret[
"rank_energy_consummed"] = system_metrics.rank_energy_consummed.value();
1392 if (system_metrics.gpu_energy_consummed.has_value()) {
1393 ret[
"gpu_energy_consummed"] = system_metrics.gpu_energy_consummed.value();
1395 if (system_metrics.cpu_energy_consummed.has_value()) {
1396 ret[
"cpu_energy_consummed"] = system_metrics.cpu_energy_consummed.value();
1398 if (system_metrics.dram_energy_consummed.has_value()) {
1399 ret[
"dram_energy_consummed"] = system_metrics.dram_energy_consummed.value();
1403 .def(
"solver_logs_cumulated_step_time", &T::solver_logs_cumulated_step_time)
1404 .def(
"solver_logs_reset_cumulated_step_time", &T::solver_logs_reset_cumulated_step_time)
1405 .def(
"solver_logs_step_count", &T::solver_logs_step_count)
1406 .def(
"solver_logs_reset_step_count", &T::solver_logs_reset_step_count)
1410 return self.get_time();
1415 return self.get_dt_sph();
1419 [](T &self, Tscal t) {
1420 return self.set_time(t);
1424 [](T &self, Tscal dt) {
1425 return self.set_next_dt(dt);
1429 [](T &self,
f64 dt) {
1430 self.set_next_dt(dt);
1433 "set_cfl_multipler",
1434 [](T &self, Tscal lambda) {
1435 return self.set_cfl_multipler(lambda);
1439 "set_cfl_mult_stiffness",
1440 [](T &self, Tscal cstiff) {
1441 return self.solver.solver_config.set_cfl_mult_stiffness(cstiff);
1445 "change_htolerance",
1446 [](T &self, Tscal in) {
1449 ".change_htolerance(val) is deprecated,\n"
1450 " -> calling this is replaced internally by "
1451 ".change_htolerances(coarse=val, fine=min(val, 1.1))\n"
1453 "https://shamrock-code.github.io/Shamrock/mkdocs/models/sph/"
1454 "smoothing_length_tolerance"););
1455 self.change_htolerances(in, std::min(in, (Tscal) 1.1));
1458 "change_htolerances",
1459 [](T &self, Tscal coarse, Tscal fine) {
1460 self.change_htolerances(coarse, fine);
1466 "make_analysis_sodtube",
1474 return std::make_unique<TAnalysisSodTube>(
1476 self.solver.solver_config,
1477 self.solver.storage,
1486 py::arg(
"direction"),
1487 py::arg(
"time_val"),
1492 "make_analysis_disc",
1494 return std::make_unique<TAnalysisDisc>(
1495 self.ctx, self.solver.solver_config, self.solver.storage);
1497 .def(
"load_from_dump", &T::load_from_dump)
1498 .def(
"dump", &T::dump)
1499 .def(
"get_setup", &T::get_setup)
1501 "get_patch_transform",
1504 return sched.get_patch_transform<Tvec>();
1506 .def(
"apply_momentum_offset", &T::apply_momentum_offset)
1507 .def(
"apply_position_offset", &T::apply_position_offset)
1509 "add_timestep_callback",
1511 std::optional<std::function<
void(
void)>> step_begin_callback,
1512 std::optional<std::function<
void(
void)>> step_end_callback) {
1513 self.solver.timestep_callbacks.push_back(
1514 {std::move(step_begin_callback), std::move(step_end_callback)});
1517 py::arg(
"step_begin") = std::nullopt,
1518 py::arg(
"step_end") = std::nullopt);
1521template<
class Tvec,
template<
class>
class SPHKernel>
1522void add_analysisBarycenter_instance(py::module &m,
const std::string &name_model) {
1525 using Tscal = shambase::VecComponent<Tvec>;
1529 py::class_<modules::AnalysisBarycenter<Tvec, SPHKernel>>(m, name_model.c_str())
1530 .def(py::init([](T &model) {
1531 return std::make_unique<modules::AnalysisBarycenter<Tvec, SPHKernel>>(model);
1534 auto result = self.get_barycenter();
1535 return py::make_tuple(result.barycenter, result.mass_disc);
1539template<
class Tvec,
template<
class>
class SPHKernel>
1540void add_analysisEnergyKinetic_instance(py::module &m,
const std::string &name_model) {
1543 using Tscal = shambase::VecComponent<Tvec>;
1546 py::class_<modules::AnalysisEnergyKinetic<Tvec, SPHKernel>>(m, name_model.c_str())
1547 .def(py::init([](T &model) {
1548 return std::make_unique<modules::AnalysisEnergyKinetic<Tvec, SPHKernel>>(model);
1551 return self.get_kinetic_energy();
1555template<
class Tvec,
template<
class>
class SPHKernel>
1556void add_analysisEnergyPotential_instance(py::module &m,
const std::string &name_model) {
1559 using Tscal = shambase::VecComponent<Tvec>;
1562 py::class_<modules::AnalysisEnergyPotential<Tvec, SPHKernel>>(m, name_model.c_str())
1563 .def(py::init([](T &model) {
1564 return std::make_unique<modules::AnalysisEnergyPotential<Tvec, SPHKernel>>(model);
1567 return self.get_potential_energy();
1571template<
class Tvec,
template<
class>
class SPHKernel>
1572void add_analysisTotalMomentum_instance(py::module &m,
const std::string &name_model) {
1575 using Tscal = shambase::VecComponent<Tvec>;
1578 py::class_<modules::AnalysisTotalMomentum<Tvec, SPHKernel>>(m, name_model.c_str())
1579 .def(py::init([](T &model) {
1580 return std::make_unique<modules::AnalysisTotalMomentum<Tvec, SPHKernel>>(model);
1583 return self.get_total_momentum();
1587template<
class Tvec,
template<
class>
class SPHKernel>
1588void add_analysisAngularMomentum_instance(py::module &m,
const std::string &name_model) {
1591 using Tscal = shambase::VecComponent<Tvec>;
1594 py::class_<modules::AnalysisAngularMomentum<Tvec, SPHKernel>>(m, name_model.c_str())
1595 .def(py::init([](T &model) {
1596 return std::make_unique<modules::AnalysisAngularMomentum<Tvec, SPHKernel>>(model);
1599 return self.get_angular_momentum();
1603template<
class Tvec,
template<
class>
class SPHKernel>
1604void add_analysisDustMass_instance(py::module &m,
const std::string &name_model) {
1607 using Tscal = shambase::VecComponent<Tvec>;
1610 py::class_<modules::AnalysisDustMass<Tvec, SPHKernel>>(m, name_model.c_str())
1611 .def(py::init([](T &model) {
1612 return std::make_unique<modules::AnalysisDustMass<Tvec, SPHKernel>>(model);
1615 return self.get_dust_mass();
1621template<
class Analysis,
typename Tvec,
template<
class>
class SPHKernel>
1623 return Analysis(model);
1626template<
template<
class,
template<
class>
class>
class Analysis>
1627void register_analysis_impl_for_each_kernel(py::module &msph, const char *name_class) {
1628 using namespace shammodels::sph;
1630 using SPHModel_f64_3_M4 = shammodels::sph::Model<f64_3, shammath::M4>;
1631 using SPHModel_f64_3_M6 = shammodels::sph::Model<f64_3, shammath::M6>;
1632 using SPHModel_f64_3_M8 = shammodels::sph::Model<f64_3, shammath::M8>;
1634 using SPHModel_f64_3_C2 = shammodels::sph::Model<f64_3, shammath::C2>;
1635 using SPHModel_f64_3_C4 = shammodels::sph::Model<f64_3, shammath::C4>;
1636 using SPHModel_f64_3_C6 = shammodels::sph::Model<f64_3, shammath::C6>;
1640 [](SPHModel_f64_3_M4 &model) {
1641 return analysis_impl<Analysis<f64_3, shammath::M4>>(model);
1648 [](SPHModel_f64_3_M6 &model) {
1649 return analysis_impl<Analysis<f64_3, shammath::M6>>(model);
1656 [](SPHModel_f64_3_M8 &model) {
1657 return analysis_impl<Analysis<f64_3, shammath::M8>>(model);
1664 [](SPHModel_f64_3_C2 &model) {
1665 return analysis_impl<Analysis<f64_3, shammath::C2>>(model);
1672 [](SPHModel_f64_3_C4 &model) {
1673 return analysis_impl<Analysis<f64_3, shammath::C4>>(model);
1680 [](SPHModel_f64_3_C6 &model) {
1681 return analysis_impl<Analysis<f64_3, shammath::C6>>(model);
1688 auto &m = root_module;
1690 py::module msph = m.def_submodule(
"model_sph",
"Shamrock sph solver");
1692 py::class_<EvolveUntilResults>(m,
"EvolveUntilResults")
1693 .def_readwrite(
"reach_target_time", &EvolveUntilResults::reach_target_time)
1694 .def_readwrite(
"reach_niter_max", &EvolveUntilResults::reach_niter_max)
1695 .def_readwrite(
"reach_max_walltime", &EvolveUntilResults::reach_max_walltime)
1696 .def_readwrite(
"iter_count", &EvolveUntilResults::iter_count)
1698 return shambase::format(
1699 "EvolveUntilResults(reach_target_time={}, reach_niter_max={}, "
1700 "reach_max_walltime={}, iter_count={})",
1701 self.reach_target_time,
1702 self.reach_niter_max,
1703 self.reach_max_walltime,
1709 add_instance<f64_3, shammath::M4>(msph,
"SPHModel_f64_3_M4_SolverConfig",
"SPHModel_f64_3_M4");
1710 add_instance<f64_3, shammath::M6>(msph,
"SPHModel_f64_3_M6_SolverConfig",
"SPHModel_f64_3_M6");
1711 add_instance<f64_3, shammath::M8>(msph,
"SPHModel_f64_3_M8_SolverConfig",
"SPHModel_f64_3_M8");
1713 add_instance<f64_3, shammath::C2>(msph,
"SPHModel_f64_3_C2_SolverConfig",
"SPHModel_f64_3_C2");
1714 add_instance<f64_3, shammath::C4>(msph,
"SPHModel_f64_3_C4_SolverConfig",
"SPHModel_f64_3_C4");
1715 add_instance<f64_3, shammath::C6>(msph,
"SPHModel_f64_3_C6_SolverConfig",
"SPHModel_f64_3_C6");
1717 using VariantSPHModelBind = std::variant<
1718 std::unique_ptr<Model<f64_3, shammath::M4>>,
1719 std::unique_ptr<Model<f64_3, shammath::M6>>,
1720 std::unique_ptr<Model<f64_3, shammath::M8>>,
1721 std::unique_ptr<Model<f64_3, shammath::C2>>,
1722 std::unique_ptr<Model<f64_3, shammath::C4>>,
1723 std::unique_ptr<Model<f64_3, shammath::C6>>>;
1728 const std::string &vector_type,
1729 const std::string &kernel) -> VariantSPHModelBind {
1730 VariantSPHModelBind ret;
1732 if (vector_type ==
"f64_3" && kernel ==
"M4") {
1733 ret = std::make_unique<Model<f64_3, shammath::M4>>(ctx);
1734 }
else if (vector_type ==
"f64_3" && kernel ==
"M6") {
1735 ret = std::make_unique<Model<f64_3, shammath::M6>>(ctx);
1736 }
else if (vector_type ==
"f64_3" && kernel ==
"M8") {
1737 ret = std::make_unique<Model<f64_3, shammath::M8>>(ctx);
1738 }
else if (vector_type ==
"f64_3" && kernel ==
"C2") {
1739 ret = std::make_unique<Model<f64_3, shammath::C2>>(ctx);
1740 }
else if (vector_type ==
"f64_3" && kernel ==
"C4") {
1741 ret = std::make_unique<Model<f64_3, shammath::C4>>(ctx);
1742 }
else if (vector_type ==
"f64_3" && kernel ==
"C6") {
1743 ret = std::make_unique<Model<f64_3, shammath::C6>>(ctx);
1746 "unknown combination of representation and kernel");
1753 py::arg(
"vector_type"),
1754 py::arg(
"sph_kernel"));
1758 std::shared_ptr<shammodels::sph::modules::ISPHSetupNode>>(msph,
"ISPHSetupNode")
1759 .def(
"get_dot", [](std::shared_ptr<shammodels::sph::modules::ISPHSetupNode> &self) {
1760 return self->get_dot();
1763 py::class_<shammodels::sph::TimestepLog>(msph,
"TimestepLog")
1765 .def_readwrite(
"rank", &shammodels::sph::TimestepLog::rank)
1766 .def_readwrite(
"rate", &shammodels::sph::TimestepLog::rate)
1767 .def_readwrite(
"npart", &shammodels::sph::TimestepLog::npart)
1768 .def_readwrite(
"tcompute", &shammodels::sph::TimestepLog::tcompute)
1769 .def(
"rate_sum", &shammodels::sph::TimestepLog::rate_sum)
1770 .def(
"npart_sum", &shammodels::sph::TimestepLog::npart_sum);
1772 add_analysisBarycenter_instance<f64_3, shammath::M4>(msph,
"AnalysisBarycenter_f64_3_M4");
1773 add_analysisBarycenter_instance<f64_3, shammath::M6>(msph,
"AnalysisBarycenter_f64_3_M6");
1774 add_analysisBarycenter_instance<f64_3, shammath::M8>(msph,
"AnalysisBarycenter_f64_3_M8");
1776 add_analysisBarycenter_instance<f64_3, shammath::C2>(msph,
"AnalysisBarycenter_f64_3_C2");
1777 add_analysisBarycenter_instance<f64_3, shammath::C4>(msph,
"AnalysisBarycenter_f64_3_C4");
1778 add_analysisBarycenter_instance<f64_3, shammath::C6>(msph,
"AnalysisBarycenter_f64_3_C6");
1780 add_analysisEnergyKinetic_instance<f64_3, shammath::M4>(msph,
"AnalysisEnergyKinetic_f64_3_M4");
1781 add_analysisEnergyKinetic_instance<f64_3, shammath::M6>(msph,
"AnalysisEnergyKinetic_f64_3_M6");
1782 add_analysisEnergyKinetic_instance<f64_3, shammath::M8>(msph,
"AnalysisEnergyKinetic_f64_3_M8");
1784 add_analysisEnergyKinetic_instance<f64_3, shammath::C2>(msph,
"AnalysisEnergyKinetic_f64_3_C2");
1785 add_analysisEnergyKinetic_instance<f64_3, shammath::C4>(msph,
"AnalysisEnergyKinetic_f64_3_C4");
1786 add_analysisEnergyKinetic_instance<f64_3, shammath::C6>(msph,
"AnalysisEnergyKinetic_f64_3_C6");
1788 add_analysisEnergyPotential_instance<f64_3, shammath::M4>(
1789 msph,
"AnalysisEnergyPotential_f64_3_M4");
1790 add_analysisEnergyPotential_instance<f64_3, shammath::M6>(
1791 msph,
"AnalysisEnergyPotential_f64_3_M6");
1792 add_analysisEnergyPotential_instance<f64_3, shammath::M8>(
1793 msph,
"AnalysisEnergyPotential_f64_3_M8");
1795 add_analysisEnergyPotential_instance<f64_3, shammath::C2>(
1796 msph,
"AnalysisEnergyPotential_f64_3_C2");
1797 add_analysisEnergyPotential_instance<f64_3, shammath::C4>(
1798 msph,
"AnalysisEnergyPotential_f64_3_C4");
1799 add_analysisEnergyPotential_instance<f64_3, shammath::C6>(
1800 msph,
"AnalysisEnergyPotential_f64_3_C6");
1802 add_analysisTotalMomentum_instance<f64_3, shammath::M4>(msph,
"AnalysisTotalMomentum_f64_3_M4");
1803 add_analysisTotalMomentum_instance<f64_3, shammath::M6>(msph,
"AnalysisTotalMomentum_f64_3_M6");
1804 add_analysisTotalMomentum_instance<f64_3, shammath::M8>(msph,
"AnalysisTotalMomentum_f64_3_M8");
1806 add_analysisTotalMomentum_instance<f64_3, shammath::C2>(msph,
"AnalysisTotalMomentum_f64_3_C2");
1807 add_analysisTotalMomentum_instance<f64_3, shammath::C4>(msph,
"AnalysisTotalMomentum_f64_3_C4");
1808 add_analysisTotalMomentum_instance<f64_3, shammath::C6>(msph,
"AnalysisTotalMomentum_f64_3_C6");
1810 add_analysisAngularMomentum_instance<f64_3, shammath::M4>(
1811 msph,
"AnalysisAngularMomentum_f64_3_M4");
1812 add_analysisAngularMomentum_instance<f64_3, shammath::M6>(
1813 msph,
"AnalysisAngularMomentum_f64_3_M6");
1814 add_analysisAngularMomentum_instance<f64_3, shammath::M8>(
1815 msph,
"AnalysisAngularMomentum_f64_3_M8");
1817 add_analysisAngularMomentum_instance<f64_3, shammath::C2>(
1818 msph,
"AnalysisAngularMomentum_f64_3_C2");
1819 add_analysisAngularMomentum_instance<f64_3, shammath::C4>(
1820 msph,
"AnalysisAngularMomentum_f64_3_C4");
1821 add_analysisAngularMomentum_instance<f64_3, shammath::C6>(
1822 msph,
"AnalysisAngularMomentum_f64_3_C6");
1824 register_analysis_impl_for_each_kernel<modules::AnalysisBarycenter>(msph,
"analysisBarycenter");
1825 register_analysis_impl_for_each_kernel<modules::AnalysisEnergyKinetic>(
1826 msph,
"analysisEnergyKinetic");
1827 register_analysis_impl_for_each_kernel<modules::AnalysisEnergyPotential>(
1828 msph,
"analysisEnergyPotential");
1829 register_analysis_impl_for_each_kernel<modules::AnalysisTotalMomentum>(
1830 msph,
"analysisTotalMomentum");
1831 register_analysis_impl_for_each_kernel<modules::AnalysisAngularMomentum>(
1832 msph,
"analysisAngularMomentum");
1834 add_analysisDustMass_instance<f64_3, shammath::M4>(msph,
"AnalysisDustMass_f64_3_M4");
1835 add_analysisDustMass_instance<f64_3, shammath::M6>(msph,
"AnalysisDustMass_f64_3_M6");
1836 add_analysisDustMass_instance<f64_3, shammath::M8>(msph,
"AnalysisDustMass_f64_3_M8");
1838 add_analysisDustMass_instance<f64_3, shammath::C2>(msph,
"AnalysisDustMass_f64_3_C2");
1839 add_analysisDustMass_instance<f64_3, shammath::C4>(msph,
"AnalysisDustMass_f64_3_C4");
1840 add_analysisDustMass_instance<f64_3, shammath::C6>(msph,
"AnalysisDustMass_f64_3_C6");
1842 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
std::vector< SinkParticle< Tvec > > to_sink_particles(const SinkEdges< Tvec > &e)
Build an AoS sink list from the current SoA edges (Python API / dump helpers).
SinkEdges< Tvec > get_sink_edges(shamrock::solvergraph::SolverGraphSerializable &sync)
Fetch mutable references to the sink SoA synchronized edges.
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...
Helpers to access SPH sink particles stored as SoA synchronized data edges.
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.