Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
Solver.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 "SolverConfig.hpp"
31#include "shambackends/vec.hpp"
43#include <algorithm>
44#include <memory>
45#include <stdexcept>
46#include <variant>
47
48namespace shammodels::gsph {
49
50 struct TimestepLog {
51 i32 rank;
52 f64 rate;
53 u64 npart;
54 f64 tcompute;
55
56 inline f64 rate_sum() { return shamalgs::collective::allreduce_sum(rate); }
57 inline u64 npart_sum() { return shamalgs::collective::allreduce_sum(npart); }
58 inline f64 tcompute_max() { return shamalgs::collective::allreduce_max(tcompute); }
59 };
60
70 template<class Tvec, template<class> class SPHKernel>
71 class Solver {
72 public:
73 using Tscal = shambase::VecComponent<Tvec>;
74 static constexpr u32 dim = shambase::VectorProperties<Tvec>::dimension;
75 using Kernel = SPHKernel<Tscal>;
76
77 using Config = SolverConfig<Tvec, SPHKernel>;
78
79 using u_morton = u32;
80
81 static constexpr Tscal Rkern = Kernel::Rkern;
82
83 ShamrockCtx &context;
84 inline PatchScheduler &scheduler() { return shambase::get_check_ref(context.sched); }
85
87
88 Config solver_config;
89 SolverLog solve_logs;
90
92 inline Tscal &time_edge_value() {
93 return scheduler()
94 .synchronized_data
95 .template get_edge_ref<shamrock::solvergraph::IDataEdgeSerializable<Tscal>>("time")
96 .data;
97 }
98
100 inline Tscal &dt_edge_value() {
101 return scheduler()
102 .synchronized_data
103 .template get_edge_ref<shamrock::solvergraph::IDataEdgeSerializable<Tscal>>("dt")
104 .data;
105 }
106
107 inline Tscal get_time() { return time_edge_value(); }
108 inline void set_time(Tscal t) { time_edge_value() = t; }
109 inline Tscal get_dt() { return dt_edge_value(); }
110 inline void set_next_dt(Tscal dt) { dt_edge_value() = dt; }
111
114 auto &sync = scheduler().synchronized_data;
115 auto names = sync.get_edge_names();
116 auto has_edge = [&](const std::string &name) {
117 return std::find(names.begin(), names.end(), name) != names.end();
118 };
119
120 if (!has_edge("time")) {
121 auto edge = sync.register_edge(
123 edge->data = 0;
124 }
125 if (!has_edge("dt")) {
126 auto edge = sync.register_edge(
128 edge->data = 0;
129 }
130 }
131
132 inline void init_required_fields() { solver_config.set_layout(context.get_pdl_write()); }
133
134 // Serial patch tree control
135 void gen_serial_patch_tree();
136 inline void reset_serial_patch_tree() { storage.serial_patch_tree.reset(); }
137
138 // Ghost handling - use GSPH ghost handler with Newtonian field names
139 using GhostHandle = GSPHGhostHandler<Tvec>;
140 using GhostHandleCache = typename GhostHandle::CacheMap;
141
142 void gen_ghost_handler(Tscal time_val);
143 inline void reset_ghost_handler() {
144 shambase::get_check_ref(storage.ghost_handler).free_alloc();
145 }
146
147 void build_ghost_cache();
148 void clear_ghost_cache();
149
150 void merge_position_ghost();
151
152 // Tree operations
153 using RTree = typename Config::RTree;
154 void build_merged_pos_trees();
155 void clear_merged_pos_trees();
156
157 void compute_presteps_rint();
158 void reset_presteps_rint();
159
160 void start_neighbors_cache();
161 void reset_neighbors_cache();
162
163 void gsph_prestep(Tscal time_val, Tscal dt);
164
165 void apply_position_boundary(Tscal time_val);
166
167 void do_predictor_leapfrog(Tscal dt);
168
169 void init_ghost_layout();
170
171 void communicate_merge_ghosts_fields();
172 void reset_merge_ghosts_fields();
173
174 void compute_eos_fields();
175 void reset_eos_fields();
176
185
197 void compute_density();
198
208 void compute_gradients();
209
210 void prepare_corrector();
211
219 void update_derivs();
220
230 Tscal compute_dt_cfl();
231
232 bool apply_corrector(Tscal dt, u64 Npart_all);
233
234 void update_sync_load_values();
235
236 Solver(ShamrockCtx &context) : context(context) {}
237
238 void init_solver_graph();
239
240 void vtk_do_dump(std::string filename, bool add_patch_world_id);
241
242 inline void print_timestep_logs() {
243 if (shamcomm::world_rank() == 0) {
244 logger::info_ln(
245 "GSPH", "iteration since start :", solve_logs.get_iteration_count());
246 logger::info_ln(
247 "GSPH", "time since start :", shambase::details::get_wtime(), "(s)");
248 }
249 }
250
251 TimestepLog evolve_once();
252
253 Tscal evolve_once_time_expl(Tscal t_current, Tscal dt_input) {
254 set_time(t_current);
255 set_next_dt(dt_input);
256 evolve_once();
257 return get_dt();
258 }
259
260 inline bool evolve_until(Tscal target_time, i32 niter_max = -1) {
261 auto step = [&]() {
262 Tscal dt = get_dt();
263 Tscal t = get_time();
264
265 if (t > target_time) {
267 "the target time is higher than the current time");
268 }
269
270 if (t + dt > target_time) {
271 set_next_dt(target_time - t);
272 }
273 evolve_once();
274 };
275
276 i32 iter_count = 0;
277
278 while (get_time() < target_time) {
279 step();
280 iter_count++;
281
282 if ((iter_count >= niter_max) && (niter_max != -1)) {
283 logger::info_ln("GSPH", "stopping evolve until because of niter =", iter_count);
284 return false;
285 }
286 }
287
288 print_timestep_logs();
289
290 return true;
291 }
292 };
293
294} // namespace shammodels::gsph
GSPH-specific ghost handler using Newtonian physics field names.
double f64
Alias for double.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
std::int32_t i32
32 bit integer
The MPI scheduler.
void compute_density()
Compute SPH-summation density for GSPH.
Definition Solver.cpp:543
Tscal & time_edge_value()
Access synchronized simulation time (scheduler edge "time").
Definition Solver.hpp:92
void copy_eos_to_patchdata()
Copy EOS fields from solvergraph to patchdata for persistence.
Definition Solver.cpp:1311
void compute_gradients()
Compute gradients for MUSCL reconstruction.
Definition Solver.cpp:1373
void ensure_time_state_edges()
Register time/dt synchronized edges if missing (idempotent).
Definition Solver.hpp:113
TimestepLog evolve_once()
Definition Solver.cpp:1807
void update_derivs()
Update derivatives using GSPH Riemann solver.
Definition Solver.cpp:1621
Tscal & dt_edge_value()
Access synchronized next dt (scheduler edge "dt").
Definition Solver.hpp:100
Tscal compute_dt_cfl()
Compute CFL timestep constraint.
Definition Solver.cpp:1629
This header file contains utility functions related to exception handling in the code.
Configuration for the Godunov SPH (GSPH) solver.
Storage for GSPH solver runtime data.
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...
Definition memory.hpp:112
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.
Definition worldInfo.cpp:41
Class holding the logs of the solver /todo add a variable to keep only a definite number of steps in ...
Definition SolverLog.hpp:34
The configuration for a GSPH solver.
Runtime storage for GSPH solver.
Component< SerialPatchTree< Tvec > > serial_patch_tree
Serial patch tree for load balancing.
std::shared_ptr< solvergraph::GhostHandlerEdge< Tvec > > ghost_handler
Ghost handler for boundary particles.