Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
SolverConfig.hpp
Go to the documentation of this file.
1// -------------------------------------------------------//
2//
3// SHAMROCK code for hydrodynamics
4// Copyright (c) 2021-2026 Timothée David--Cléris <tim.shamrock@proton.me>
5// SPDX-License-Identifier: CeCILL Free Software License Agreement v2.1
6// Shamrock is licensed under the CeCILL 2.1 License, see LICENSE for more information
7//
8// -------------------------------------------------------//
9
10#pragma once
11
22#include "config/AVConfig.hpp"
23#include "config/BCConfig.hpp"
24#include "shambackends/math.hpp"
27#include "shambackends/vec.hpp"
46#include <variant>
47#include <vector>
48
49namespace shammodels::sph {
50
57 template<class Tvec, template<class> class SPHKernel>
58 struct SolverConfig;
59
65 template<class Tvec>
66 struct SolverStatusVar;
67
73 template<class Tscal>
74 struct CFLConfig {
75
79 Tscal cfl_cour;
80
84 Tscal cfl_force;
85
90
92 Tscal eta_sink = 0.05;
93 };
94
95 template<class Tvec>
97 using Tscal = shambase::VecComponent<Tvec>;
98 struct Sphere {
99 Tvec center;
100 Tscal radius;
101 };
102
103 using kill_t = std::variant<Sphere>;
104
105 std::vector<kill_t> kill_list;
106
107 inline void add_kill_sphere(const Tvec &center, Tscal radius) {
108 kill_list.push_back(Sphere{center, radius});
109 }
110 };
111
112 template<class Tscal>
113 struct DustConfig {
114
115 struct None {};
116
118 u32 ndust;
119 };
120
122 u32 ndust;
123 };
124
126 using Variant = std::variant<None, MonofluidTVI, MonofluidComplete>;
127
128 Variant current_mode = None{};
129
130 inline void set_none() { current_mode = None{}; }
131 inline void set_monofluid_tvi(u32 nvar) { current_mode = MonofluidTVI{nvar}; }
132 inline void set_monofluid_complete(u32 nvar) { current_mode = MonofluidComplete{nvar}; }
133
134 inline bool has_epsilon_field() {
135 return bool(std::get_if<MonofluidTVI>(&current_mode))
136 || bool(std::get_if<MonofluidComplete>(&current_mode));
137 }
138
139 inline bool has_deltav_field() {
140 return bool(std::get_if<MonofluidComplete>(&current_mode));
141 }
142
143 inline u32 get_dust_nvar() {
144 if (None *cfg = std::get_if<None>(&current_mode)) {
146 "Querying a dust nvar with no dust as config is ... discutable ...");
147 return 0;
148 } else if (MonofluidTVI *cfg = std::get_if<MonofluidTVI>(&current_mode)) {
149 return cfg->ndust;
150 } else if (MonofluidComplete *cfg = std::get_if<MonofluidComplete>(&current_mode)) {
151 return cfg->ndust;
152 } else {
153 shambase::throw_unimplemented("How did you get here ???");
154 }
155 return 0;
156 }
157
158 inline void check_config() {
159 bool is_not_none = bool(std::get_if<MonofluidTVI>(&current_mode))
160 || bool(std::get_if<MonofluidComplete>(&current_mode));
161 if (is_not_none) {
162 ON_RANK_0(
163 logger::warn_ln(
164 "SPH::config",
165 "Dust config != None is work in progress, use it at your own risk"));
166 }
167 }
168 };
169
171 struct DensityBased {};
173 u32 max_neigh_count = 500;
174 };
175
176 using mode = std::variant<DensityBased, DensityBasedNeighLim>;
177
178 mode config = DensityBased{};
179
180 void set_density_based() { config = DensityBased{}; }
181 void set_density_based_neigh_lim(u32 max_neigh_count) {
182 config = DensityBasedNeighLim{max_neigh_count};
183 }
184
185 bool is_density_based_neigh_lim() const {
186 return std::holds_alternative<DensityBasedNeighLim>(config);
187 }
188 };
189
191
192 struct SFMM {
193 u32 order;
194 f64 opening_angle;
195 bool leaf_lowering;
196 u32 reduction_level;
197 };
198
199 struct FMM {
200 u32 order;
201 f64 opening_angle;
202 u32 reduction_level;
203 };
204
205 struct MM {
206 u32 order;
207 f64 opening_angle;
208 u32 reduction_level;
209 };
210
211 struct Direct {
212 bool reference_mode = false;
213 };
214
215 struct None {};
216
217 using mode = std::variant<SFMM, FMM, MM, Direct, None>;
218
219 mode config = None{};
220
221 void set_none() { config = None{}; }
222 void set_direct(bool reference_mode = false) { config = Direct{reference_mode}; }
223 void set_mm(u32 mm_order, f64 opening_angle, u32 reduction_level) {
224 config = MM{mm_order, opening_angle, reduction_level};
225 }
226 void set_fmm(u32 order, f64 opening_angle, u32 reduction_level) {
227 config = FMM{order, opening_angle, reduction_level};
228 }
229 void set_sfmm(u32 order, f64 opening_angle, bool leaf_lowering, u32 reduction_level) {
230 config = SFMM{order, opening_angle, leaf_lowering, reduction_level};
231 }
232
233 bool is_none() const { return std::holds_alternative<None>(config); }
234 bool is_direct() const { return std::holds_alternative<Direct>(config); }
235 bool is_mm() const { return std::holds_alternative<MM>(config); }
236 bool is_fmm() const { return std::holds_alternative<FMM>(config); }
237 bool is_sfmm() const { return std::holds_alternative<SFMM>(config); }
238
239 bool is_sg_on() const { return !is_none(); }
240 bool is_sg_off() const { return is_none(); }
241
243 f64 epsilon;
244 };
245
246 using mode_soft = std::variant<SofteningPlummer>;
247 mode_soft softening_mode = SofteningPlummer{1e-9};
248
249 void set_softening_plummer(f64 epsilon) { softening_mode = SofteningPlummer{epsilon}; }
250 void set_softening_none() { set_softening_plummer(0.); }
251
252 bool is_softening_plummer() const {
253 return std::holds_alternative<SofteningPlummer>(softening_mode);
254 }
255 };
256
257} // namespace shammodels::sph
258
259template<class Tvec>
261
263 using Tscal = shambase::VecComponent<Tvec>;
264
267
269};
270
271template<class Tvec, template<class> class SPHKernel>
273
275 using Tscal = shambase::VecComponent<Tvec>;
279 using Kernel = SPHKernel<Tscal>;
281 using u_morton = u32;
282
284
286 static constexpr Tscal Rkern = Kernel::Rkern;
287
290
291 bool track_particles_id = false;
292
293 inline void set_particle_tracking(bool state) { track_particles_id = state; }
294
295 PatchSchedulerConfig scheduler_conf = {};
296
298 // Units Config
300
302 std::optional<shamunits::UnitSystem<Tscal>> unit_sys = {};
303
305 inline void set_units(shamunits::UnitSystem<Tscal> new_sys) { unit_sys = new_sys; }
306
309 if (!unit_sys) {
310 ON_RANK_0(logger::warn_ln("sph::Config", "the unit system is not set"));
312 return ctes.G();
313 } else {
315 }
316 }
317
320 if (!unit_sys) {
321 ON_RANK_0(logger::warn_ln("sph::Config", "the unit system is not set"));
323 return ctes.c();
324 } else {
326 }
327 }
328
331 if (!unit_sys) {
332 ON_RANK_0(logger::warn_ln("sph::Config", "the unit system is not set"));
334 return ctes.mu_0();
335 } else {
337 }
338 }
339
341 // Units Config (END)
343
345 // Particle killing config
347
348 ParticleKillingConfig<Tvec> particle_killing;
349
351 // Particle killing config (END)
353
355 // Solver status variables
357
360
363
365 inline void set_time(Tscal t) { time_state.time = t; }
366
368 inline void set_next_dt(Tscal dt) { time_state.dt_sph = dt; }
369
371 inline Tscal get_time() { return time_state.time; }
372
374 inline Tscal get_dt_sph() { return time_state.dt_sph; }
375
377 inline void set_cfl_multipler(Tscal lambda) { time_state.cfl_multiplier = lambda; }
378
380 inline Tscal get_cfl_multipler() { return time_state.cfl_multiplier; }
381
383 inline void set_cfl_mult_stiffness(Tscal cstiff) {
384 cfl_config.cfl_multiplier_stiffness = cstiff;
385 }
386
388 inline Tscal get_cfl_mult_stiffness() { return cfl_config.cfl_multiplier_stiffness; }
389
391 // Solver status variables (END)
393
395 // MHD Config
397
399 MHDConfig mhd_config = {};
400
402 inline void set_noMHD() {
403 using Tmp = typename MHDConfig::None;
404 mhd_config.set(Tmp{});
405 }
406
409 mhd_config.set(v);
410 }
411
412 inline void set_NonIdealMHD(typename MHDConfig::NonIdealMHD v) { mhd_config.set(v); }
413
415 // MHD Config (END)
417
419 // Dust config
421
422 using DustConfig = DustConfig<Tscal>;
423 DustConfig dust_config = {};
424
426 // Dust config (END)
428
430 // Self gravity config
432
433 SelfGravConfig self_grav_config = SelfGravConfig{};
434
436 // Self gravity config (END)
438
440 // Tree config
442
445
447 inline void set_tree_reduction_level(u32 level) { tree_reduction_level = level; }
449 inline void set_two_stage_search(bool enable) { use_two_stage_search = enable; }
450
451 bool show_neigh_stats = false;
452 inline void set_show_neigh_stats(bool enable) { show_neigh_stats = enable; }
454 // Tree config (END)
456
458 // Solver behavior config
460
470
471 SmoothingLengthConfig smoothing_length_config;
472
473 inline void set_smoothing_length_density_based() {
474 smoothing_length_config.set_density_based();
475 }
476 inline void set_smoothing_length_density_based_neigh_lim(u32 max_neigh_count) {
477 smoothing_length_config.set_density_based_neigh_lim(max_neigh_count);
478 }
479
480 bool enable_particle_reordering = false;
481 inline void set_enable_particle_reordering(bool enable) { enable_particle_reordering = enable; }
482 u64 particle_reordering_step_freq = 1000;
483 inline void set_particle_reordering_step_freq(u64 freq) {
484 if (freq == 0) {
486 "particle_reordering_step_freq cannot be zero");
487 }
488 particle_reordering_step_freq = freq;
489 }
490
491 bool save_dt_to_fields = false;
492 inline void set_save_dt_to_fields(bool enable) { save_dt_to_fields = enable; }
493 inline bool should_save_dt_to_fields() const { return save_dt_to_fields; }
494
495 bool show_ghost_zone_graph = false;
496 inline void set_show_ghost_zone_graph(bool enable) { show_ghost_zone_graph = enable; }
497
499 // Solver behavior config (END)
501
503 // EOS Config
505
508
511
514 using T = typename EOSConfig::LocallyIsothermal;
515 return bool(std::get_if<T>(&eos_config.config));
516 }
517
519 inline bool is_eos_adiabatic() {
520 using T = typename EOSConfig::Adiabatic;
521 return bool(std::get_if<T>(&eos_config.config));
522 }
523
525 inline bool is_eos_polytropic() {
526 using T = typename EOSConfig::Polytropic;
527 return bool(std::get_if<T>(&eos_config.config));
528 }
529
531 inline bool is_eos_isothermal() {
532 using T = typename EOSConfig::Isothermal;
533 return bool(std::get_if<T>(&eos_config.config));
534 }
535
537 inline bool is_eos_fermi() {
538 using T = typename EOSConfig::Fermi;
539 return bool(std::get_if<T>(&eos_config.config));
540 }
541
548
554 inline void set_eos_adiabatic(Tscal gamma) { eos_config.set_adiabatic(gamma); }
555
561 inline void set_eos_polytropic(Tscal K, Tscal gamma) { eos_config.set_polytropic(K, gamma); }
562
567
579
588 eos_config.set_locally_isothermalFA2014(h_over_r);
589 }
590
601 Tscal cs0, Tscal q, Tscal r0, u32 n_sinks) {
602 eos_config.set_locally_isothermalFA2014_extended(cs0, q, r0, n_sinks);
603 }
604
610 inline void set_eos_fermi(Tscal mu_e) { eos_config.set_fermi(mu_e); }
611
613 // EOS Config (END)
615
617 // Artificial viscosity Config
619
632
635
640 using Tmp = typename AVConfig::None;
641 artif_viscosity.set(Tmp{});
642 }
643
650 artif_viscosity.set(v);
651 }
652
660 artif_viscosity.set(v);
661 }
662
670 artif_viscosity.set(v);
671 }
672
680
682 // Artificial viscosity Config (END)
684
686 // Boundary Config
688
693
700
704 inline void set_boundary_free() { boundary_config.set_free(); }
705
709 inline void set_boundary_periodic() { boundary_config.set_periodic(); }
710
722 inline void set_boundary_shearing_periodic(i32_3 shear_base, i32_3 shear_dir, Tscal speed) {
723 boundary_config.set_shearing_periodic(shear_base, shear_dir, speed);
724 }
725
727 // Boundary Config (END)
729
731 // Ext force Config
733
746
751
758 inline void add_ext_force_point_mass(Tscal central_mass, Tscal Racc) {
759 ext_force_config.add_point_mass(central_mass, Racc);
760 }
761
771 Tscal central_mass, Tscal Racc, Tscal a_spin, Tvec dir_spin) {
772 ext_force_config.add_lense_thirring(central_mass, Racc, a_spin, dir_spin);
773 }
774
782 inline void add_ext_force_shearing_box(Tscal Omega_0, Tscal eta, Tscal q) {
783 ext_force_config.add_shearing_box(Omega_0, eta, q);
784 }
785
787 // Ext force Config (END)
789
791 // Debug dump config
793
795 bool do_debug_dump = false;
796
798 std::string debug_dump_filename = "";
799
804 inline void set_debug_dump(bool _do_debug_dump, std::string _debug_dump_filename) {
805 this->do_debug_dump = _do_debug_dump;
806 this->debug_dump_filename = _debug_dump_filename;
807 }
808
810 inline constexpr bool do_MHD_debug() { return false; }
811
813 // Debug dump config (END)
815
818
822 inline bool has_field_uint() {
823 // no barotropic for now
824 return true;
825 }
826
828 inline bool has_field_alphaAV() { return artif_viscosity.has_alphaAV_field(); }
829
831 inline bool has_field_divv() { return artif_viscosity.has_alphaAV_field(); }
832
834 inline bool has_field_dtdivv() { return artif_viscosity.has_dtdivv_field(); }
835
837 inline bool has_field_curlv() { return artif_viscosity.has_curlv_field() && (dim == 3); }
838
840 inline bool has_axyz_in_ghost() { return has_field_dtdivv(); }
841
843 inline bool has_field_soundspeed() {
844 return artif_viscosity.has_field_soundspeed() || is_eos_locally_isothermal();
845 }
846
848 inline bool has_field_B_on_rho() { return mhd_config.has_B_field() && (dim == 3); }
849
851 inline bool has_field_psi_on_ch() { return mhd_config.has_psi_field(); }
852
854 inline bool has_field_divB() { return mhd_config.has_divB_field(); }
855
857 inline bool has_field_curlB() { return mhd_config.has_curlB_field() && (dim == 3); }
858
860 inline bool has_field_dtdivB() { return mhd_config.has_dtdivB_field(); }
861
863 bool compute_luminosity = false;
864 inline void use_luminosity(bool enable) { compute_luminosity = enable; }
865
867 inline void print_status() {
868 if (shamcomm::world_rank() != 0) {
869 return;
870 }
871 logger::raw_ln("----- SPH Solver configuration -----");
872 logger::raw_ln(nlohmann::json{*this}.dump(4));
873 logger::raw_ln("------------------------------------");
874 }
875
876 inline void check_config() {
877 dust_config.check_config();
878
879 if (track_particles_id && false /*particle injection when added*/) {
881 "particle injection is not yet compatible with particle id tracking");
882 }
883
884 if (track_particles_id) {
885 shamrock::experimental_feature_check("Particle tracking is experimental");
886 }
887
888 if (!self_grav_config.is_none()) {
890 "Self gravity is experimental, please enable experimental features to use it");
891 }
892 }
893
894 void set_layout(shamrock::patch::PatchDataLayerLayout &pdl);
895 void set_ghost_layout(shamrock::patch::PatchDataLayerLayout &ghost_layout);
896};
897
898namespace shammodels::sph {
899
906 template<class Tscal>
907 inline void to_json(nlohmann::json &j, const CFLConfig<Tscal> &p) {
908 j = nlohmann::json{
909 {"cfl_cour", p.cfl_cour},
910 {"cfl_force", p.cfl_force},
911 {"cfl_multiplier_stiffness", p.cfl_multiplier_stiffness},
912 {"eta_sink", p.eta_sink}};
913 }
914
921 template<class Tscal>
922 inline void from_json(const nlohmann::json &j, CFLConfig<Tscal> &p) {
923 j.at("cfl_cour").get_to<Tscal>(p.cfl_cour);
924 j.at("cfl_force").get_to<Tscal>(p.cfl_force);
925 j.at("cfl_multiplier_stiffness").get_to<Tscal>(p.cfl_multiplier_stiffness);
926
927 if (j.contains("eta_sink")) {
928 j.at("eta_sink").get_to<Tscal>(p.eta_sink);
929 } else {
930 // Already set to default value
931 ON_RANK_0(shamlog_warn_ln(
932 "SPHConfig", "eta_sink not found when deserializing, defaulting to", p.eta_sink));
933 }
934 }
935
942 template<class Tvec>
943 inline void to_json(nlohmann::json &j, const SolverStatusVar<Tvec> &p) {
944 j = nlohmann::json{
945 {"time", p.time}, {"dt_sph", p.dt_sph}, {"cfl_multiplier", p.cfl_multiplier}};
946 }
947
954 template<class Tvec>
955 inline void from_json(const nlohmann::json &j, SolverStatusVar<Tvec> &p) {
956 using Tscal = typename SolverStatusVar<Tvec>::Tscal;
957 j.at("time").get_to<Tscal>(p.time);
958 j.at("dt_sph").get_to<Tscal>(p.dt_sph);
959 j.at("cfl_multiplier").get_to<Tscal>(p.cfl_multiplier);
960 }
961
962 // JSON serialization for ParticleKillingConfig
963 template<class Tvec>
964 inline void to_json(nlohmann::json &j, const ParticleKillingConfig<Tvec> &p) {
965 j = nlohmann::json::array();
966 for (const auto &kill : p.kill_list) {
967 if (std::holds_alternative<typename ParticleKillingConfig<Tvec>::Sphere>(kill)) {
968 const auto &sphere = std::get<typename ParticleKillingConfig<Tvec>::Sphere>(kill);
969 j.push_back(
970 {{"type", "sphere"}, {"center", sphere.center}, {"radius", sphere.radius}});
971 }
972 // If more types are added to kill_t, handle them here
973 }
974 }
975
976 template<class Tvec>
977 inline void from_json(const nlohmann::json &j, ParticleKillingConfig<Tvec> &p) {
978 p.kill_list.clear();
979 for (const auto &item : j) {
980 std::string type = item.at("type").get<std::string>();
981 if (type == "sphere") {
982 typename ParticleKillingConfig<Tvec>::Sphere sphere;
983 item.at("center").get_to(sphere.center);
984 item.at("radius").get_to(sphere.radius);
985 p.kill_list.push_back(sphere);
986 }
987 // If more types are added to kill_t, handle them here
988 }
989 }
990
991 // JSON serialization for SmoothingLengthConfig
992 inline void to_json(nlohmann::json &j, const SmoothingLengthConfig &p) {
993 if (const SmoothingLengthConfig::DensityBased *conf
994 = std::get_if<SmoothingLengthConfig::DensityBased>(&p.config)) {
995 j = {
996 {"type", "density_based"},
997 };
998
999 } else if (
1000 const SmoothingLengthConfig::DensityBasedNeighLim *conf
1001 = std::get_if<SmoothingLengthConfig::DensityBasedNeighLim>(&p.config)) {
1002
1003 j = {
1004 {"type", "density_based_neigh_lim"},
1005 {"max_neigh_count", conf->max_neigh_count},
1006 };
1007 } else {
1009 }
1010 }
1011
1012 inline void from_json(const nlohmann::json &j, SmoothingLengthConfig &p) {
1013 if (j.at("type").get<std::string>() == "density_based") {
1014 p.config = SmoothingLengthConfig::DensityBased{};
1015 } else if (j.at("type").get<std::string>() == "density_based_neigh_lim") {
1016 p.config
1017 = SmoothingLengthConfig::DensityBasedNeighLim{j.at("max_neigh_count").get<u32>()};
1018 } else {
1020 }
1021 }
1022
1024 inline void to_json(nlohmann::json &j, const SelfGravConfig &p) {
1025 if (const SelfGravConfig::SFMM *conf = std::get_if<SelfGravConfig::SFMM>(&p.config)) {
1026 j = {
1027 {"type", "sfmm"},
1028 {"order", conf->order},
1029 {"opening_angle", conf->opening_angle},
1030 {"reduction_level", conf->reduction_level},
1031 {"leaf_lowering", conf->leaf_lowering},
1032 };
1033 } else if (const SelfGravConfig::FMM *conf = std::get_if<SelfGravConfig::FMM>(&p.config)) {
1034 j = {
1035 {"type", "fmm"},
1036 {"order", conf->order},
1037 {"opening_angle", conf->opening_angle},
1038 {"reduction_level", conf->reduction_level},
1039 };
1040 } else if (const SelfGravConfig::MM *conf = std::get_if<SelfGravConfig::MM>(&p.config)) {
1041 j = {
1042 {"type", "mm"},
1043 {"order", conf->order},
1044 {"opening_angle", conf->opening_angle},
1045 {"reduction_level", conf->reduction_level},
1046 };
1047 } else if (
1048 const SelfGravConfig::Direct *conf = std::get_if<SelfGravConfig::Direct>(&p.config)) {
1049 j = {
1050 {"type", "direct"},
1051 {"reference_mode", conf->reference_mode},
1052 };
1053 } else if (
1054 const SelfGravConfig::None *conf = std::get_if<SelfGravConfig::None>(&p.config)) {
1055 j = {
1056 {"type", "none"},
1057 };
1058 }
1059
1060 if (const SelfGravConfig::SofteningPlummer *conf
1061 = std::get_if<SelfGravConfig::SofteningPlummer>(&p.softening_mode)) {
1062 j["softening_mode"] = "plummer";
1063 j["softening_length"] = conf->epsilon;
1064 } else {
1066 }
1067 }
1068
1070 inline void from_json(const nlohmann::json &j, SelfGravConfig &p) {
1071 if (j.at("type").get<std::string>() == "sfmm") {
1072 p.config = SelfGravConfig::SFMM{
1073 j.at("order").get<u32>(),
1074 j.at("opening_angle").get<f64>(),
1075 j.at("leaf_lowering").get<bool>(),
1076 j.at("reduction_level").get<u32>()};
1077 } else if (j.at("type").get<std::string>() == "fmm") {
1078 p.config = SelfGravConfig::FMM{
1079 j.at("order").get<u32>(),
1080 j.at("opening_angle").get<f64>(),
1081 j.at("reduction_level").get<u32>()};
1082 } else if (j.at("type").get<std::string>() == "mm") {
1083 p.config = SelfGravConfig::MM{
1084 j.at("order").get<u32>(),
1085 j.at("opening_angle").get<f64>(),
1086 j.at("reduction_level").get<u32>()};
1087 } else if (j.at("type").get<std::string>() == "direct") {
1088 p.config = SelfGravConfig::Direct{j.at("reference_mode").get<bool>()};
1089 } else if (j.at("type").get<std::string>() == "none") {
1090 p.config = SelfGravConfig::None{};
1091 } else {
1093 "Invalid self gravity type: " + j.at("type").get<std::string>());
1094 }
1095
1096 if (j.contains("softening_mode")) {
1097 std::string softening_mode = j.at("softening_mode").get<std::string>();
1098 if (softening_mode == "plummer") {
1099 p.softening_mode
1100 = SelfGravConfig::SofteningPlummer{j.at("softening_length").get<f64>()};
1101 } else {
1103 "Invalid softening mode: " + softening_mode);
1104 }
1105 }
1106 }
1107
1114 template<class Tvec, template<class> class SPHKernel>
1115 inline void to_json(nlohmann::json &j, const SolverConfig<Tvec, SPHKernel> &p) {
1117 using Tkernel = typename T::Kernel;
1118
1119 std::string kernel_id = shambase::get_type_name<Tkernel>();
1120 std::string type_id = shambase::get_type_name<Tvec>();
1121
1122 j = nlohmann::json{
1123 // used for type checking
1124 {"kernel_id", kernel_id},
1125 {"type_id", type_id},
1126 // scheduler config
1127 {"scheduler_config", p.scheduler_conf},
1128 // actual data stored in the json
1129 {"gpart_mass", p.gpart_mass},
1130 {"cfl_config", p.cfl_config},
1131 {"unit_sys", p.unit_sys},
1132 {"time_state", p.time_state},
1133 // mhd config
1134 {"mhd_config", p.mhd_config},
1135 // self gravity config
1136 {"self_grav_config", p.self_grav_config},
1137 // tree config
1138 {"tree_reduction_level", p.tree_reduction_level},
1139 {"use_two_stage_search", p.use_two_stage_search},
1140 {"show_neigh_stats", p.show_neigh_stats},
1141 // solver behavior config
1142 {"combined_dtdiv_divcurlv_compute", p.combined_dtdiv_divcurlv_compute},
1143 {"htol_up_coarse_cycle", p.htol_up_coarse_cycle},
1144 {"htol_up_fine_cycle", p.htol_up_fine_cycle},
1145 {"epsilon_h", p.epsilon_h},
1146 {"smoothing_length_config", p.smoothing_length_config},
1147 {"h_iter_per_subcycles", p.h_iter_per_subcycles},
1148 {"h_max_subcycles_count", p.h_max_subcycles_count},
1149
1150 {"enable_particle_reordering", p.enable_particle_reordering},
1151 {"particle_reordering_step_freq", p.particle_reordering_step_freq},
1152
1153 {"save_dt_to_fields", p.save_dt_to_fields},
1154 {"show_ghost_zone_graph", p.show_ghost_zone_graph},
1155
1156 {"eos_config", p.eos_config},
1157
1158 {"artif_viscosity", p.artif_viscosity},
1159 {"boundary_config", p.boundary_config},
1160 {"ext_force_config", p.ext_force_config},
1161
1162 {"do_debug_dump", p.do_debug_dump},
1163 {"debug_dump_filename", p.debug_dump_filename},
1164 // particle killing config
1165 {"particle_killing", p.particle_killing},
1166 };
1167 }
1168
1175 template<class Tvec, template<class> class SPHKernel>
1176 inline void from_json(const nlohmann::json &j, SolverConfig<Tvec, SPHKernel> &p) {
1178 using Tkernel = typename T::Kernel;
1179
1180 // type checking
1181 if (j.contains("kernel_id")) {
1182
1183 std::string kernel_id = j.at("kernel_id").get<std::string>();
1184
1185 if (kernel_id != shambase::get_type_name<Tkernel>()) {
1187 "Invalid type to deserialize, wanted " + shambase::get_type_name<Tvec>()
1188 + " but got " + kernel_id);
1189 }
1190 }
1191
1192 if (j.contains("type_id")) {
1193
1194 std::string type_id = j.at("type_id").get<std::string>();
1195
1196 if (type_id != shambase::get_type_name<Tvec>()) {
1198 "Invalid type to deserialize, wanted " + shambase::get_type_name<Tvec>()
1199 + " but got " + type_id);
1200 }
1201 }
1202
1203 bool has_used_defaults = false;
1204 bool has_updated_config = false;
1205
1206 auto _get_to_if_contains = [&](const std::string &key, auto &value) {
1207 shamrock::get_to_if_contains(j, key, value, has_used_defaults);
1208 };
1209
1210 auto _get_to_if_contains_fallbacks = [&](const std::string &key,
1211 auto &value,
1212 std::initializer_list<const char *> fallbacks) {
1214 j, key, value, fallbacks, has_used_defaults, has_updated_config);
1215 };
1216
1217 _get_to_if_contains("scheduler_config", p.scheduler_conf);
1218
1219 // actual data stored in the json
1220 _get_to_if_contains("gpart_mass", p.gpart_mass);
1221 _get_to_if_contains("cfl_config", p.cfl_config);
1222 _get_to_if_contains("unit_sys", p.unit_sys);
1223 _get_to_if_contains("time_state", p.time_state);
1224 _get_to_if_contains("mhd_config", p.mhd_config);
1225 _get_to_if_contains("self_grav_config", p.self_grav_config);
1226 _get_to_if_contains("tree_reduction_level", p.tree_reduction_level);
1227 _get_to_if_contains("use_two_stage_search", p.use_two_stage_search);
1228 _get_to_if_contains("show_neigh_stats", p.show_neigh_stats);
1229 _get_to_if_contains("combined_dtdiv_divcurlv_compute", p.combined_dtdiv_divcurlv_compute);
1230
1231 // Try new names first, fall back to old names for backward compatibility
1232 _get_to_if_contains_fallbacks(
1233 "htol_up_coarse_cycle", p.htol_up_coarse_cycle, {"htol_up_tol"});
1234 _get_to_if_contains_fallbacks("htol_up_fine_cycle", p.htol_up_fine_cycle, {"htol_up_iter"});
1235
1236 _get_to_if_contains("epsilon_h", p.epsilon_h);
1237 _get_to_if_contains("smoothing_length_config", p.smoothing_length_config);
1238 _get_to_if_contains("h_iter_per_subcycles", p.h_iter_per_subcycles);
1239 _get_to_if_contains("h_max_subcycles_count", p.h_max_subcycles_count);
1240 _get_to_if_contains("enable_particle_reordering", p.enable_particle_reordering);
1241 _get_to_if_contains("particle_reordering_step_freq", p.particle_reordering_step_freq);
1242 _get_to_if_contains("save_dt_to_fields", p.save_dt_to_fields);
1243 _get_to_if_contains("show_ghost_zone_graph", p.show_ghost_zone_graph);
1244 _get_to_if_contains("eos_config", p.eos_config);
1245 _get_to_if_contains("artif_viscosity", p.artif_viscosity);
1246 _get_to_if_contains("boundary_config", p.boundary_config);
1247 _get_to_if_contains("ext_force_config", p.ext_force_config);
1248 _get_to_if_contains("do_debug_dump", p.do_debug_dump);
1249 _get_to_if_contains("debug_dump_filename", p.debug_dump_filename);
1250 _get_to_if_contains("particle_killing", p.particle_killing);
1251
1252 if (has_used_defaults || has_updated_config) {
1253 if (shamcomm::world_rank() == 0) {
1254 logger::info_ln(
1255 "SPH::SolverConfig",
1256 shamrock::log_json_changes(p, j, has_used_defaults, has_updated_config));
1257 }
1258 }
1259 }
1260
1261} // namespace shammodels::sph
Header file describing a Node Instance.
MPI scheduler.
double f64
Alias for double.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
A Compressed Leaf Bounding Volume Hierarchy (CLBVH) for neighborhood queries.
Defines a unit system.
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.
void throw_unimplemented(SourceLocation loc=SourceLocation{})
Throw a std::runtime_error saying that the function is unimplemented.
i32 world_rank()
Gives the rank of the current process in the MPI communicator.
Definition worldInfo.cpp:40
namespace for the sph model
void to_json(nlohmann::json &j, const EOSConfig< Tvec > &p)
Serialize EOSConfig to json.
Definition EOSConfig.cpp:43
void from_json(const nlohmann::json &j, EOSConfig< Tvec > &p)
Deserializes an EOSConfig<Tvec> from a JSON object.
void get_to_if_contains(const nlohmann::json &j, const std::string &key, T &value, bool &has_used_defaults)
void experimental_feature_check(const std::string &message, SourceLocation loc=SourceLocation{})
Check if experimental features are enabled, if not throw with the given message.
std::string log_json_changes(const nlohmann::json &j_current, const nlohmann::json &j, bool has_used_defaults, bool has_updated_config)
Shown the changes between two JSON objects to log config changes.
void get_to_if_contains_fallbacks(const nlohmann::json &j, const std::string &key, T &value, std::initializer_list< const char * > fallbacks, bool &has_used_defaults, bool &has_updated_config)
Contains traits and utilities for backend related types.
sph kernels
Locally isothermal equation of state configuration.
Definition EOSConfig.hpp:61
Configuration struct for the equation of state used in the hydrodynamic models.
Definition EOSConfig.hpp:42
void set_isothermal(Tscal cs)
Set the EOS configuration to an isothermal equation of state.
Definition EOSConfig.hpp:96
Variant config
Current EOS configuration.
Definition EOSConfig.hpp:89
shamphys::EOS_Config_Polytropic< Tscal > Polytropic
Polytropic equation of state configuration.
Definition EOSConfig.hpp:55
shamphys::EOS_Config_Isothermal< Tscal > Isothermal
Isothermal equation of state configuration.
Definition EOSConfig.hpp:58
void set_adiabatic(Tscal gamma)
Set the EOS configuration to an adiabatic equation of state.
shamphys::EOS_Config_Fermi< Tscal > Fermi
Fermi equation of state configuration.
Definition EOSConfig.hpp:75
void set_polytropic(Tscal K, Tscal gamma)
Set the EOS configuration to an polytropic equation of state.
void set_fermi(Tscal mu_e)
Set the EOS configuration to a Fermi equation of state.
void set_locally_isothermalLP07(Tscal cs0, Tscal q, Tscal r0)
Set the EOS configuration to a locally isothermal equation of state (Lodato Price 2007)
shamphys::EOS_Config_Adiabatic< Tscal > Adiabatic
Adiabatic equation of state configuration.
Definition EOSConfig.hpp:52
void set_locally_isothermal()
Set the EOS configuration to a locally isothermal equation of state.
void add_shearing_box(Tscal Omega_0, Tscal eta, Tscal q)
Constant artificial viscosity for alpha disc viscosity.
Definition AVConfig.hpp:147
Constant artificial viscosity: .
Definition AVConfig.hpp:49
No artificial viscosity: .
Definition AVConfig.hpp:33
The configuration for the CFL condition.
Tscal eta_sink
eta sink to control the sink integrator
Tscal cfl_cour
The CFL condition for the courant factor.
Tscal cfl_multiplier_stiffness
The CFL multiplier stiffness.
Tscal cfl_force
The CFL condition for the force.
std::variant< None, MonofluidTVI, MonofluidComplete > Variant
Variant type to store the EOS configuration.
The configuration for a sph solver.
bool ghost_has_soundspeed()
Whether the ghost cells have a sound speed (i.e. the eos is locally isothermal)
AVConfig artif_viscosity
Configuration for the Artificial Viscosity (AV)
void set_eos_isothermal(Tscal cs)
Set the EOS configuration to an isothermal equation of state.
Tscal gpart_mass
The mass of each gas particle.
u32 h_max_subcycles_count
Maximum number of subcycles before solver crash.
bool compute_luminosity
Whether to store luminosity.
void print_status()
Print the current status of the solver config.
void set_eos_adiabatic(Tscal gamma)
Set the EOS configuration to an adiabatic equation of state.
bool has_field_uint()
Whether the solver has a field for the particle's uint.
bool is_eos_isothermal()
Check if the EOS is an isothermal equation of state.
BCConfig boundary_config
Boundary condition configuration.
bool has_field_psi_on_ch()
Whether the solver has a field for psi_on_ch.
void set_cfl_mult_stiffness(Tscal cstiff)
Set the CFL multiplier for the stiffness.
bool use_two_stage_search
Use two stage neighbors search (see shamrock paper)
Tscal get_cfl_multipler()
Get the CFL multiplier for the time step.
bool has_field_dtdivB()
Whether the solver has a field for dt divB.
bool has_axyz_in_ghost()
Whether the solver has a field for ax, ay, az in ghost cells.
void set_time(Tscal t)
Set the current time.
void set_eos_locally_isothermalLP07(Tscal cs0, Tscal q, Tscal r0)
Set the EOS configuration to a locally isothermal equation of state from Lodato Price 2007.
CFLConfig< Tscal > cfl_config
The configuration for the CFL condition.
bool has_field_divB()
Whether the solver has a field for divB.
Tscal get_time()
Get the current time.
void set_artif_viscosity_VaryingMM97(typename AVConfig::VaryingMM97 v)
Set the artificial viscosity configuration to a varying value using the prescription of Monaghan & Gi...
SolverStatusVar< Tvec > SolverStatusVar
Alias to SolverStatusVar type.
Tscal epsilon_h
Convergence criteria for the smoothing length.
SPHKernel< Tscal > Kernel
The type of the kernel used for the SPH interactions.
bool has_field_curlB()
Whether the solver has a field for curlB.
void add_ext_force_point_mass(Tscal central_mass, Tscal Racc)
Add a point mass external force.
bool do_debug_dump
Whether to dump debug information to file.
bool has_field_divv()
Whether the solver has a field for divv.
shambase::VecComponent< Tvec > Tscal
The type of the scalar used to represent the quantities.
Tscal get_cfl_mult_stiffness()
Get the CFL multiplier for the stiffness.
bool has_field_alphaAV()
Whether the solver has a field for alpha AV.
void set_debug_dump(bool _do_debug_dump, std::string _debug_dump_filename)
Set whether to dump debug information to file.
u32 h_iter_per_subcycles
Maximum number of iterations per subcycle.
bool is_eos_adiabatic()
Check if the EOS is an adiabatic equation of state.
void set_artif_viscosity_VaryingCD10(typename AVConfig::VaryingCD10 v)
Set the artificial viscosity configuration to a varying value using the prescription of Cullen & Dehn...
void set_two_stage_search(bool enable)
Setter for the two stage search.
void set_boundary_free()
Set the boundary condition to free boundary.
SolverStatusVar time_state
The time sate of the simulation.
bool has_field_curlv()
Whether the solver has a field for curlv.
bool has_field_dtdivv()
Whether the solver has a field for dt divv.
std::string debug_dump_filename
The filename to dump debug information in.
bool is_eos_locally_isothermal()
Check if the EOS is a locally isothermal equation of state.
static constexpr Tscal Rkern
The radius of the sph kernel.
void set_eos_locally_isothermalFA2014_extended(Tscal cs0, Tscal q, Tscal r0, u32 n_sinks)
Set the EOS configuration to a locally isothermal equation of state from Farris 2014 extended to q !...
void set_eos_locally_isothermal()
Set the EOS configuration to a locally isothermal equation of state.
Tscal get_constant_G()
Retrieves the value of the constant G based on the unit system.
void set_eos_locally_isothermalFA2014(Tscal h_over_r)
Set the EOS configuration to a locally isothermal equation of state fromFarris 2014.
u32 u_morton
The type of the Morton code for the tree.
Tscal get_constant_mu_0()
Retrieves the value of the constant mu_0 based on the unit system.
void set_units(shamunits::UnitSystem< Tscal > new_sys)
Set the unit system of the simulation.
void set_artif_viscosity_None()
Set the artificial viscosity configuration to None.
bool is_eos_fermi()
Check if the EOS is a Fermi equation of state.
Tscal get_dt_sph()
Get the time step for the next iteration.
void set_IdealMHD(typename MHDConfig::IdealMHD_constrained_hyper_para v)
Enable the ideal MHD hydro solver.
void set_tree_reduction_level(u32 level)
Setter for the tree reduction level.
static constexpr u32 dim
The dimension of the problem.
void set_eos_polytropic(Tscal K, Tscal gamma)
Set the EOS configuration to an polytropic equation of state.
Tscal get_constant_c()
Retrieves the value of the constant c based on the unit system.
void set_artif_viscosity_Constant(typename AVConfig::Constant v)
Set the artificial viscosity configuration to a constant value.
bool is_eos_polytropic()
Check if the EOS is a polytropic equation of state.
AVConfig< Tvec > AVConfig
Configuration for the Artificial Viscosity (AV)
BCConfig< Tvec > BCConfig
Configuration of the boundary conditions.
void set_boundary_shearing_periodic(i32_3 shear_base, i32_3 shear_dir, Tscal speed)
Set the boundary condition to shearing periodic boundary.
Tscal htol_up_fine_cycle
Maximum factor of the smoothing length evolution per subcycles.
void set_boundary_periodic()
Set the boundary condition to periodic boundary.
u32 tree_reduction_level
Reduction level to be used in the tree build.
bool has_field_B_on_rho()
Whether the solver has a field for B_on_rho.
constexpr bool do_MHD_debug()
Whether to add debug fields to the pdl.
std::optional< shamunits::UnitSystem< Tscal > > unit_sys
The unit system of the simulation.
EOSConfig eos_config
EOS configuration.
bool has_field_soundspeed()
Whether the solver has a field for sound speed.
void set_noMHD()
disable MHD in the SPH solver
void set_next_dt(Tscal dt)
Set the time step for the next iteration.
ExtForceConfig ext_force_config
External force configuration.
void add_ext_force_shearing_box(Tscal Omega_0, Tscal eta, Tscal q)
Add a shearing box external force.
void set_artif_viscosity_ConstantDisc(typename AVConfig::ConstantDisc v)
Set the artificial viscosity configuration to a constant value in the disc plane.
void add_ext_force_lense_thirring(Tscal central_mass, Tscal Racc, Tscal a_spin, Tvec dir_spin)
Add a Lense-Thirring external force.
void set_cfl_multipler(Tscal lambda)
Set the CFL multiplier for the time step.
void set_eos_fermi(Tscal mu_e)
Set the EOS configuration to a Fermi equation of state.
Solver status variables.
Tscal dt_sph
Current time step.
Tscal cfl_multiplier
Current cfl multiplier.
shambase::VecComponent< Tvec > Tscal
The type of the scalar used to represent the quantities.
Physical constants.
constexpr T c()
get c in the current unit system units (m.s-1)
constexpr T G()
get the value of G in the current unit system units
constexpr T mu_0()
get the value of mu_0 in the current unit system units
Functions related to the MPI communicator.
#define ON_RANK_0(x)
Macro to execute code only on rank 0.
Definition worldInfo.hpp:73