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
28
30#include "shambackends/math.hpp"
33#include "shambackends/vec.hpp"
41#include "shammodels/sph/config/BCConfig.hpp" // Reuse boundary conditions from SPH
50#include <nlohmann/json.hpp>
53#include <variant>
54#include <vector>
55
56namespace shammodels::gsph {
57
64 template<class Tvec, template<class> class SPHKernel>
65 struct SolverConfig;
66
72 template<class Tscal>
73 struct CFLConfig {
74 Tscal cfl_cour = 0.3;
75 Tscal cfl_force = 0.25;
76 };
77
78} // namespace shammodels::gsph
79
80template<class Tvec, template<class> class SPHKernel>
82
83 using Tscal = shambase::VecComponent<Tvec>;
84 static constexpr u32 dim = shambase::VectorProperties<Tvec>::dimension;
85 using Kernel = SPHKernel<Tscal>;
86 using u_morton = u32;
87
89
90 static constexpr Tscal Rkern = Kernel::Rkern;
91
92 Tscal gpart_mass{0};
93
95
96 PatchSchedulerConfig scheduler_conf = {};
97
99 // Units Config
101
102 std::optional<shamunits::UnitSystem<Tscal>> unit_sys = {};
103
104 inline void set_units(shamunits::UnitSystem<Tscal> new_sys) { unit_sys = new_sys; }
105
106 inline Tscal get_constant_G() const {
107 if (!unit_sys) {
108 ON_RANK_0(logger::warn_ln("gsph::Config", "the unit system is not set"));
110 return ctes.G();
111 } else {
112 return shamunits::Constants<Tscal>{*unit_sys}.G();
113 }
114 }
115
117 // Units Config (END)
119
121 // Riemann Solver Config
123
124 using RiemannConfig = RiemannConfig<Tvec>;
125 RiemannConfig riemann_config;
126
127 inline void set_riemann_iterative(Tscal tol = Tscal{1e-6}, u32 max_iter = 20) {
128 riemann_config.set_iterative(tol, max_iter);
129 }
130
131 inline void set_riemann_hllc() { riemann_config.set_hllc(); }
132
133 inline void set_riemann_exact(Tscal tol = Tscal{1e-8}, u32 max_iter = 100) {
134 riemann_config.set_exact(tol, max_iter);
135 }
136
138 // Riemann Solver Config (END)
140
142 // Reconstruction Config
144
145 using ReconstructConfig = ReconstructConfig<Tvec>;
146 ReconstructConfig reconstruct_config;
147
148 inline void set_reconstruct_piecewise_constant() {
149 reconstruct_config.set_piecewise_constant();
150 }
151
152 inline void set_reconstruct_muscl(
154 reconstruct_config.set_muscl(limiter);
155 }
156
157 inline bool requires_gradients() const { return reconstruct_config.requires_gradients(); }
158
160 // Reconstruction Config (END)
162
164 // Force Formulation Config
166
167 using ForceFormulationConfig = ForceFormulationConfig<Tvec>;
168 ForceFormulationConfig force_formulation_config;
169
170 inline void set_force_cha_whitworth() { force_formulation_config.set_cha_whitworth(); }
171
172 inline void set_force_inutsuka_v2() { force_formulation_config.set_inutsuka_v2(); }
173
174 inline bool is_force_inutsuka_v2() const { return force_formulation_config.is_inutsuka_v2(); }
175
177 // Force Formulation Config (END)
179
181 // EOS Config
183
184 using EOSConfig = shammodels::EOSConfig<Tvec>;
185 EOSConfig eos_config;
186
187 inline bool is_eos_adiabatic() const {
188 using T = typename EOSConfig::Adiabatic;
189 return bool(std::get_if<T>(&eos_config.config));
190 }
191
192 inline bool is_eos_isothermal() const {
193 using T = typename EOSConfig::Isothermal;
194 return bool(std::get_if<T>(&eos_config.config));
195 }
196
202 inline Tscal get_eos_gamma() const {
203 using Adiabatic = typename EOSConfig::Adiabatic;
204 using Polytropic = typename EOSConfig::Polytropic;
205 if (const auto *eos = std::get_if<Adiabatic>(&eos_config.config)) {
206 return eos->gamma;
207 } else if (const auto *eos = std::get_if<Polytropic>(&eos_config.config)) {
208 return eos->gamma;
209 }
210 return Tscal{1.4}; // Default for non-gamma EOS types
211 }
212
213 inline void set_eos_adiabatic(Tscal gamma) { eos_config.set_adiabatic(gamma); }
214
215 inline void set_eos_isothermal(Tscal cs) { eos_config.set_isothermal(cs); }
216
218 // EOS Config (END)
220
222 // Boundary Config
224
225 using BCConfig = shammodels::sph::BCConfig<Tvec>; // Reuse from SPH
226 BCConfig boundary_config;
227
228 inline void set_boundary_free() { boundary_config.set_free(); }
229 inline void set_boundary_periodic() { boundary_config.set_periodic(); }
230
241 inline void set_boundary_shearing_periodic(i32_3 shear_base, i32_3 shear_dir, Tscal speed) {
242 boundary_config.set_shearing_periodic(shear_base, shear_dir, speed);
243 }
244
246 // Boundary Config (END)
248
250 // External Force Config
252
254 ExtForceConfig ext_force_config{};
255
256 inline void add_ext_force_point_mass(Tscal central_mass, Tscal Racc) {
257 ext_force_config.add_point_mass(central_mass, Racc);
258 }
259
261 // External Force Config (END)
263
265 // Tree config
267
268 u32 tree_reduction_level = 3;
269 bool use_two_stage_search = true;
270
271 inline void set_tree_reduction_level(u32 level) { tree_reduction_level = level; }
272 inline void set_two_stage_search(bool enable) { use_two_stage_search = enable; }
273
275 // Tree config (END)
277
279 // Solver behavior config
281
283 Tscal htol_up_fine_cycle = 1.1;
284 Tscal epsilon_h = 1e-6;
287
289 // Solver behavior config (END)
291
292 inline bool has_field_uint() const { return is_eos_adiabatic(); }
293
294 inline void print_status() {
295 if (shamcomm::world_rank() != 0) {
296 return;
297 }
298 logger::raw_ln("----- GSPH Solver configuration -----");
299 logger::raw_ln("gpart_mass =", gpart_mass);
300 riemann_config.print_status();
301 reconstruct_config.print_status();
302 force_formulation_config.print_status();
303 eos_config.print_status();
304 logger::raw_ln("--------------------------------------");
305 }
306
307 inline void check_config() const {
308 // Validate configuration (gpart_mass checked later at runtime)
309 // Only check gamma for adiabatic EOS types
310 if (is_eos_adiabatic() && get_eos_gamma() <= 1) {
311 shambase::throw_with_loc<std::runtime_error>("gamma must be > 1 for adiabatic gas");
312 }
313
314 // InutsukaV2 is only wired into update_derivs_iterative()/update_derivs_exact();
315 // update_derivs_hllc() would silently fall back to ChaWhitworth otherwise.
316 if (force_formulation_config.is_inutsuka_v2() && riemann_config.is_hllc()) {
318 "InutsukaV2 force formulation is not yet supported with the HLLC Riemann "
319 "solver. Use set_riemann_iterative() or set_riemann_exact() instead.");
320 }
321 }
322
323 inline void check_config_runtime() const {
324 // Validate configuration for runtime (called before simulation starts)
325 if (gpart_mass <= 0) {
327 "gpart_mass must be positive. Call set_particle_mass() before evolving.");
328 }
329 check_config();
330 }
331
332 void set_layout(shamrock::patch::PatchDataLayerLayout &pdl);
333 void set_ghost_layout(shamrock::patch::PatchDataLayerLayout &ghost_layout);
334};
335
336namespace shammodels::gsph {
337
338 template<class Tscal>
339 inline void to_json(nlohmann::json &j, const CFLConfig<Tscal> &p) {
340 j = nlohmann::json{
341 {"cfl_cour", p.cfl_cour},
342 {"cfl_force", p.cfl_force},
343 };
344 }
345
346 template<class Tscal>
347 inline void from_json(const nlohmann::json &j, CFLConfig<Tscal> &p) {
348 j.at("cfl_cour").get_to(p.cfl_cour);
349 j.at("cfl_force").get_to(p.cfl_force);
350 }
351
352 template<class Tvec, template<class> class SPHKernel>
353 inline void to_json(nlohmann::json &j, const SolverConfig<Tvec, SPHKernel> &p) {
355 using Tkernel = typename T::Kernel;
356
357 std::string kernel_id = shambase::get_type_name<Tkernel>();
358 std::string type_id = shambase::get_type_name<Tvec>();
359
360 j = nlohmann::json{
361 {"solver_type", "gsph"},
362 {"kernel_id", kernel_id},
363 {"type_id", type_id},
364 {"scheduler_config", p.scheduler_conf},
365 {"gpart_mass", p.gpart_mass},
366 {"cfl_config", p.cfl_config},
367 {"unit_sys", p.unit_sys},
368 {"riemann_config", p.riemann_config},
369 {"reconstruct_config", p.reconstruct_config},
370 {"force_formulation_config", p.force_formulation_config},
371 {"eos_config", p.eos_config},
372 {"boundary_config", p.boundary_config},
373 {"tree_reduction_level", p.tree_reduction_level},
374 {"use_two_stage_search", p.use_two_stage_search},
375 {"htol_up_coarse_cycle", p.htol_up_coarse_cycle},
376 {"htol_up_fine_cycle", p.htol_up_fine_cycle},
377 {"epsilon_h", p.epsilon_h},
378 {"h_iter_per_subcycles", p.h_iter_per_subcycles},
379 {"h_max_subcycles_count", p.h_max_subcycles_count},
380 };
381 }
382
383 template<class Tvec, template<class> class SPHKernel>
384 inline void from_json(const nlohmann::json &j, SolverConfig<Tvec, SPHKernel> &p) {
386 using Tkernel = typename T::Kernel;
387
388 std::string kernel_id = j.at("kernel_id").get<std::string>();
389 if (kernel_id != shambase::get_type_name<Tkernel>()) {
391 "Invalid kernel type: expected " + shambase::get_type_name<Tkernel>() + " but got "
392 + kernel_id);
393 }
394
395 std::string type_id = j.at("type_id").get<std::string>();
396 if (type_id != shambase::get_type_name<Tvec>()) {
398 "Invalid vector type: expected " + shambase::get_type_name<Tvec>() + " but got "
399 + type_id);
400 }
401
402 bool has_used_defaults = false;
403 bool has_updated_config = false;
404
405 auto _get_to_if_contains = [&](const std::string &key, auto &value) {
406 shamrock::get_to_if_contains(j, key, value, has_used_defaults);
407 };
408
409 _get_to_if_contains("scheduler_config", p.scheduler_conf);
410 _get_to_if_contains("gpart_mass", p.gpart_mass);
411 _get_to_if_contains("cfl_config", p.cfl_config);
412 _get_to_if_contains("unit_sys", p.unit_sys);
413 _get_to_if_contains("riemann_config", p.riemann_config);
414 _get_to_if_contains("reconstruct_config", p.reconstruct_config);
415 _get_to_if_contains("force_formulation_config", p.force_formulation_config);
416 _get_to_if_contains("eos_config", p.eos_config);
417 _get_to_if_contains("boundary_config", p.boundary_config);
418 _get_to_if_contains("tree_reduction_level", p.tree_reduction_level);
419 _get_to_if_contains("use_two_stage_search", p.use_two_stage_search);
420 _get_to_if_contains("htol_up_coarse_cycle", p.htol_up_coarse_cycle);
421 _get_to_if_contains("htol_up_fine_cycle", p.htol_up_fine_cycle);
422 _get_to_if_contains("epsilon_h", p.epsilon_h);
423 _get_to_if_contains("h_iter_per_subcycles", p.h_iter_per_subcycles);
424 _get_to_if_contains("h_max_subcycles_count", p.h_max_subcycles_count);
425
426 if (has_used_defaults || has_updated_config) {
427 if (shamcomm::world_rank() == 0) {
428 logger::info_ln(
429 "GSPH::SolverConfig",
430 shamrock::log_json_changes(p, j, has_used_defaults, has_updated_config));
431 }
432 }
433 }
434
435} // namespace shammodels::gsph
Configuration for the GSPH momentum equation formulation.
Header file describing a Node Instance.
MPI scheduler.
Configuration for reconstruction methods in GSPH.
Configuration for Riemann solvers in GSPH.
std::uint32_t u32
32 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.
i32 world_rank()
Gives the rank of the current process in the MPI communicator.
Definition worldInfo.cpp:40
void get_to_if_contains(const nlohmann::json &j, const std::string &key, T &value, bool &has_used_defaults)
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.
Contains traits and utilities for backend related types.
void raw_ln(Types... var2)
Prints a log message with multiple arguments followed by a newline.
Definition logs.hpp:90
void warn_ln(std::string module_name, Types... var2)
Prints a log message with multiple arguments followed by a newline.
Definition logs.hpp:133
sph kernels
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
shamphys::EOS_Config_Adiabatic< Tscal > Adiabatic
Adiabatic equation of state configuration.
Definition EOSConfig.hpp:52
The configuration for the CFL condition in GSPH.
Tscal cfl_force
CFL condition for the force.
Tscal cfl_cour
CFL condition for the courant factor.
Limiter
Slope limiter types for MUSCL reconstruction.
The configuration for a GSPH solver.
u32 h_iter_per_subcycles
Max iterations per subcycle.
void set_boundary_shearing_periodic(i32_3 shear_base, i32_3 shear_dir, Tscal speed)
Set shearing periodic boundary conditions.
Tscal get_eos_gamma() const
Get the adiabatic index (gamma) from the EOS config.
Tscal htol_up_coarse_cycle
Factor for neighbors search.
Tscal gpart_mass
The mass of each gas particle (must be set before use).
u32 h_max_subcycles_count
Max subcycles before crash.
Tscal htol_up_fine_cycle
Max smoothing length evolution per subcycle.
CFLConfig< Tscal > cfl_config
CFL configuration.
Tscal epsilon_h
Convergence criteria for smoothing length.
Boundary conditions configuration.
Definition BCConfig.hpp:40
void set_free()
Set the boundary condition to free boundaries.
Definition BCConfig.hpp:98
Physical constants.
constexpr T G()
get the value of G 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