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
30#include "shambackends/math.hpp"
33#include "shambackends/vec.hpp"
40#include "shammodels/sph/config/BCConfig.hpp" // Reuse boundary conditions from SPH
49#include <nlohmann/json.hpp>
52#include <variant>
53#include <vector>
54
55namespace shammodels::gsph {
56
63 template<class Tvec, template<class> class SPHKernel>
64 struct SolverConfig;
65
71 template<class Tvec>
72 struct SolverStatusVar;
73
79 template<class Tscal>
80 struct CFLConfig {
81 Tscal cfl_cour = 0.3;
82 Tscal cfl_force = 0.25;
83 };
84
85} // namespace shammodels::gsph
86
87template<class Tvec>
89 using Tscal = shambase::VecComponent<Tvec>;
90
91 Tscal time = 0;
92 Tscal dt = 0;
93};
94
95template<class Tvec, template<class> class SPHKernel>
97
98 using Tscal = shambase::VecComponent<Tvec>;
100 using Kernel = SPHKernel<Tscal>;
101 using u_morton = u32;
102
104
105 static constexpr Tscal Rkern = Kernel::Rkern;
106
107 Tscal gpart_mass{0};
108
110
111 PatchSchedulerConfig scheduler_conf = {};
112
114 // Units Config
116
117 std::optional<shamunits::UnitSystem<Tscal>> unit_sys = {};
118
119 inline void set_units(shamunits::UnitSystem<Tscal> new_sys) { unit_sys = new_sys; }
120
121 inline Tscal get_constant_G() const {
122 if (!unit_sys) {
123 ON_RANK_0(logger::warn_ln("gsph::Config", "the unit system is not set"));
125 return ctes.G();
126 } else {
127 return shamunits::Constants<Tscal>{*unit_sys}.G();
128 }
129 }
130
132 // Units Config (END)
134
136 // Solver status variables
138
139 using SolverStatusVar = SolverStatusVar<Tvec>;
140 SolverStatusVar time_state;
141
142 inline void set_time(Tscal t) { time_state.time = t; }
143 inline void set_next_dt(Tscal dt) { time_state.dt = dt; }
144 inline Tscal get_time() const { return time_state.time; }
145 inline Tscal get_dt() const { return time_state.dt; }
146
148 // Solver status variables (END)
150
152 // Riemann Solver Config
154
155 using RiemannConfig = RiemannConfig<Tvec>;
156 RiemannConfig riemann_config;
157
158 inline void set_riemann_iterative(Tscal tol = Tscal{1e-6}, u32 max_iter = 20) {
159 riemann_config.set_iterative(tol, max_iter);
160 }
161
162 inline void set_riemann_hllc() { riemann_config.set_hllc(); }
163
165 // Riemann Solver Config (END)
167
169 // Reconstruction Config
171
172 using ReconstructConfig = ReconstructConfig<Tvec>;
173 ReconstructConfig reconstruct_config;
174
175 inline void set_reconstruct_piecewise_constant() {
176 reconstruct_config.set_piecewise_constant();
177 }
178
179 inline void set_reconstruct_muscl(
181 reconstruct_config.set_muscl(limiter);
182 }
183
184 inline bool requires_gradients() const { return reconstruct_config.requires_gradients(); }
185
187 // Reconstruction Config (END)
189
191 // EOS Config
193
194 using EOSConfig = shammodels::EOSConfig<Tvec>;
195 EOSConfig eos_config;
196
197 inline bool is_eos_adiabatic() const {
198 using T = typename EOSConfig::Adiabatic;
199 return bool(std::get_if<T>(&eos_config.config));
200 }
201
202 inline bool is_eos_isothermal() const {
203 using T = typename EOSConfig::Isothermal;
204 return bool(std::get_if<T>(&eos_config.config));
205 }
206
212 inline Tscal get_eos_gamma() const {
213 using Adiabatic = typename EOSConfig::Adiabatic;
214 using Polytropic = typename EOSConfig::Polytropic;
215 if (const auto *eos = std::get_if<Adiabatic>(&eos_config.config)) {
216 return eos->gamma;
217 } else if (const auto *eos = std::get_if<Polytropic>(&eos_config.config)) {
218 return eos->gamma;
219 }
220 return Tscal{1.4}; // Default for non-gamma EOS types
221 }
222
223 inline void set_eos_adiabatic(Tscal gamma) { eos_config.set_adiabatic(gamma); }
224
225 inline void set_eos_isothermal(Tscal cs) { eos_config.set_isothermal(cs); }
226
228 // EOS Config (END)
230
232 // Boundary Config
234
235 using BCConfig = shammodels::sph::BCConfig<Tvec>; // Reuse from SPH
236 BCConfig boundary_config;
237
238 inline void set_boundary_free() { boundary_config.set_free(); }
239 inline void set_boundary_periodic() { boundary_config.set_periodic(); }
240
251 inline void set_boundary_shearing_periodic(i32_3 shear_base, i32_3 shear_dir, Tscal speed) {
252 boundary_config.set_shearing_periodic(shear_base, shear_dir, speed);
253 }
254
256 // Boundary Config (END)
258
260 // External Force Config
262
264 ExtForceConfig ext_force_config{};
265
266 inline void add_ext_force_point_mass(Tscal central_mass, Tscal Racc) {
267 ext_force_config.add_point_mass(central_mass, Racc);
268 }
269
271 // External Force Config (END)
273
275 // Tree config
277
278 u32 tree_reduction_level = 3;
279 bool use_two_stage_search = true;
280
281 inline void set_tree_reduction_level(u32 level) { tree_reduction_level = level; }
282 inline void set_two_stage_search(bool enable) { use_two_stage_search = enable; }
283
285 // Tree config (END)
287
289 // Solver behavior config
291
293 Tscal htol_up_fine_cycle = 1.1;
294 Tscal epsilon_h = 1e-6;
297
299 // Solver behavior config (END)
301
302 inline bool has_field_uint() const { return is_eos_adiabatic(); }
303
304 inline void print_status() {
305 if (shamcomm::world_rank() != 0) {
306 return;
307 }
308 logger::raw_ln("----- GSPH Solver configuration -----");
309 logger::raw_ln("gpart_mass =", gpart_mass);
310 riemann_config.print_status();
311 reconstruct_config.print_status();
312 eos_config.print_status();
313 logger::raw_ln("--------------------------------------");
314 }
315
316 inline void check_config() const {
317 // Validate configuration (gpart_mass checked later at runtime)
318 // Only check gamma for adiabatic EOS types
319 if (is_eos_adiabatic() && get_eos_gamma() <= 1) {
320 shambase::throw_with_loc<std::runtime_error>("gamma must be > 1 for adiabatic gas");
321 }
322 }
323
324 inline void check_config_runtime() const {
325 // Validate configuration for runtime (called before simulation starts)
326 if (gpart_mass <= 0) {
328 "gpart_mass must be positive. Call set_particle_mass() before evolving.");
329 }
330 check_config();
331 }
332
333 void set_layout(shamrock::patch::PatchDataLayerLayout &pdl);
334 void set_ghost_layout(shamrock::patch::PatchDataLayerLayout &ghost_layout);
335};
336
337namespace shammodels::gsph {
338
339 template<class Tscal>
340 inline void to_json(nlohmann::json &j, const CFLConfig<Tscal> &p) {
341 j = nlohmann::json{
342 {"cfl_cour", p.cfl_cour},
343 {"cfl_force", p.cfl_force},
344 };
345 }
346
347 template<class Tscal>
348 inline void from_json(const nlohmann::json &j, CFLConfig<Tscal> &p) {
349 j.at("cfl_cour").get_to(p.cfl_cour);
350 j.at("cfl_force").get_to(p.cfl_force);
351 }
352
353 template<class Tvec>
354 inline void to_json(nlohmann::json &j, const SolverStatusVar<Tvec> &p) {
355 j = nlohmann::json{
356 {"time", p.time},
357 {"dt", p.dt},
358 };
359 }
360
361 template<class Tvec>
362 inline void from_json(const nlohmann::json &j, SolverStatusVar<Tvec> &p) {
363 using Tscal = typename SolverStatusVar<Tvec>::Tscal;
364 j.at("time").get_to<Tscal>(p.time);
365 j.at("dt").get_to<Tscal>(p.dt);
366 }
367
368 template<class Tvec, template<class> class SPHKernel>
369 inline void to_json(nlohmann::json &j, const SolverConfig<Tvec, SPHKernel> &p) {
370 using T = SolverConfig<Tvec, SPHKernel>;
371 using Tkernel = typename T::Kernel;
372
373 std::string kernel_id = shambase::get_type_name<Tkernel>();
374 std::string type_id = shambase::get_type_name<Tvec>();
375
376 j = nlohmann::json{
377 {"solver_type", "gsph"},
378 {"kernel_id", kernel_id},
379 {"type_id", type_id},
380 {"scheduler_config", p.scheduler_conf},
381 {"gpart_mass", p.gpart_mass},
382 {"cfl_config", p.cfl_config},
383 {"unit_sys", p.unit_sys},
384 {"time_state", p.time_state},
385 {"riemann_config", p.riemann_config},
386 {"reconstruct_config", p.reconstruct_config},
387 {"eos_config", p.eos_config},
388 {"boundary_config", p.boundary_config},
389 {"tree_reduction_level", p.tree_reduction_level},
390 {"use_two_stage_search", p.use_two_stage_search},
391 {"htol_up_coarse_cycle", p.htol_up_coarse_cycle},
392 {"htol_up_fine_cycle", p.htol_up_fine_cycle},
393 {"epsilon_h", p.epsilon_h},
394 {"h_iter_per_subcycles", p.h_iter_per_subcycles},
395 {"h_max_subcycles_count", p.h_max_subcycles_count},
396 };
397 }
398
399 template<class Tvec, template<class> class SPHKernel>
400 inline void from_json(const nlohmann::json &j, SolverConfig<Tvec, SPHKernel> &p) {
401 using T = SolverConfig<Tvec, SPHKernel>;
402 using Tkernel = typename T::Kernel;
403
404 std::string kernel_id = j.at("kernel_id").get<std::string>();
405 if (kernel_id != shambase::get_type_name<Tkernel>()) {
407 "Invalid kernel type: expected " + shambase::get_type_name<Tkernel>() + " but got "
408 + kernel_id);
409 }
410
411 std::string type_id = j.at("type_id").get<std::string>();
412 if (type_id != shambase::get_type_name<Tvec>()) {
414 "Invalid vector type: expected " + shambase::get_type_name<Tvec>() + " but got "
415 + type_id);
416 }
417
418 bool has_used_defaults = false;
419 bool has_updated_config = false;
420
421 auto _get_to_if_contains = [&](const std::string &key, auto &value) {
422 shamrock::get_to_if_contains(j, key, value, has_used_defaults);
423 };
424
425 _get_to_if_contains("scheduler_config", p.scheduler_conf);
426 _get_to_if_contains("gpart_mass", p.gpart_mass);
427 _get_to_if_contains("cfl_config", p.cfl_config);
428 _get_to_if_contains("unit_sys", p.unit_sys);
429 _get_to_if_contains("time_state", p.time_state);
430 _get_to_if_contains("riemann_config", p.riemann_config);
431 _get_to_if_contains("reconstruct_config", p.reconstruct_config);
432 _get_to_if_contains("eos_config", p.eos_config);
433 _get_to_if_contains("boundary_config", p.boundary_config);
434 _get_to_if_contains("tree_reduction_level", p.tree_reduction_level);
435 _get_to_if_contains("use_two_stage_search", p.use_two_stage_search);
436 _get_to_if_contains("htol_up_coarse_cycle", p.htol_up_coarse_cycle);
437 _get_to_if_contains("htol_up_fine_cycle", p.htol_up_fine_cycle);
438 _get_to_if_contains("epsilon_h", p.epsilon_h);
439 _get_to_if_contains("h_iter_per_subcycles", p.h_iter_per_subcycles);
440 _get_to_if_contains("h_max_subcycles_count", p.h_max_subcycles_count);
441
442 if (has_used_defaults || has_updated_config) {
443 if (shamcomm::world_rank() == 0) {
444 logger::info_ln(
445 "GSPH::SolverConfig",
446 shamrock::log_json_changes(p, j, has_used_defaults, has_updated_config));
447 }
448 }
449 }
450
451} // namespace shammodels::gsph
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 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)
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.
sph kernels
Configuration struct for the equation of state used in the hydrodynamic models.
Definition EOSConfig.hpp:42
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.
Solver status variables for GSPH.
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