Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
ConservativeCheck.cpp
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
17
19#include "shamcomm/logs.hpp"
24
25template<class Tvec, template<class> class SPHKernel>
27
28 StackEntry stack_loc{};
29
30 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
31 sham::DeviceQueue &q = shambase::get_check_ref(dev_sched).get_queue();
32
33 Tscal gpart_mass = solver_config.gpart_mass;
34
35 using namespace shamrock;
36 using namespace shamrock::patch;
37
38 PatchDataLayerLayout &pdl = scheduler().pdl_old();
39
40 const u32 ixyz = pdl.get_field_idx<Tvec>("xyz");
41 const u32 ivxyz = pdl.get_field_idx<Tvec>("vxyz");
42 const u32 iaxyz = pdl.get_field_idx<Tvec>("axyz");
43 const u32 iaxyz_ext = pdl.get_field_idx<Tvec>("axyz_ext");
44 const u32 iuint = pdl.get_field_idx<Tscal>("uint");
45 const u32 iduint = pdl.get_field_idx<Tscal>("duint");
46 const u32 ihpart = pdl.get_field_idx<Tscal>("hpart");
47
48 bool has_B_field = solver_config.has_field_B_on_rho();
49 const u32 iB_on_rho = (has_B_field) ? pdl.get_field_idx<Tvec>("B/rho") : -1;
50 const u32 idB_on_rho = (has_B_field) ? pdl.get_field_idx<Tvec>("dB/rho") : -1;
51 const u32 idrho_dt = (has_B_field) ? pdl.get_field_idx<Tscal>("drho/dt") : -1;
52
53 std::string cv_checks = "conservation infos :\n";
54
56 // momentum check :
58 Tvec tmpp{0, 0, 0};
59 scheduler().for_each_patchdata_nonempty([&](Patch cur_p, PatchDataLayer &pdat) {
60 PatchDataField<Tvec> &field = pdat.get_field<Tvec>(ivxyz);
61 tmpp += field.compute_sum();
62 });
63 Tvec sum_p = gpart_mass * shamalgs::collective::allreduce_sum(tmpp);
64
65 if (shamcomm::world_rank() == 0) {
66 auto &sync = scheduler().synchronized_data;
67 auto &mass = get_sink_mass<Tvec>(sync);
68 if (!mass.empty()) {
69 auto &vel = get_sink_vel<Tvec>(sync);
70 for (size_t i = 0; i < mass.size(); i++) {
71 sum_p += mass[i] * vel[i];
72 }
73 }
74 cv_checks += shambase::format(" sum v = {}\n", sum_p);
75 }
76
78 // force sum check :
80 Tvec tmpa{0, 0, 0};
81 scheduler().for_each_patchdata_nonempty([&](Patch cur_p, PatchDataLayer &pdat) {
82 PatchDataField<Tvec> &field = pdat.get_field<Tvec>(iaxyz);
83 tmpa += field.compute_sum();
84 });
85 Tvec sum_a = gpart_mass * shamalgs::collective::allreduce_sum(tmpa);
86
87 if (shamcomm::world_rank() == 0) {
88 auto &sync = scheduler().synchronized_data;
89 auto &mass = get_sink_mass<Tvec>(sync);
90 if (!mass.empty()) {
91 auto &acc_sph = get_sink_acc_sph<Tvec>(sync);
92 auto &acc_ext = get_sink_acc_ext<Tvec>(sync);
93 for (size_t i = 0; i < mass.size(); i++) {
94 sum_a += mass[i] * (acc_sph[i] + acc_ext[i]);
95 }
96 }
97 cv_checks += shambase::format(" sum a = {}\n", sum_a);
98 }
99
101 // energy check :
103 Tscal tmpe{0};
104 scheduler().for_each_patchdata_nonempty([&](Patch cur_p, PatchDataLayer &pdat) {
105 PatchDataField<Tscal> &field_u = pdat.get_field<Tscal>(iuint);
106 PatchDataField<Tvec> &field_v = pdat.get_field<Tvec>(ivxyz);
107 tmpe += field_u.compute_sum() + 0.5 * field_v.compute_dot_sum();
108 });
109 Tscal sum_e = gpart_mass * shamalgs::collective::allreduce_sum(tmpe);
110
111 if (shamcomm::world_rank() == 0) {
112 cv_checks += shambase::format(" sum e = {}\n", sum_e);
113 }
114
115 Tscal pmass = gpart_mass;
116 Tscal tmp_de = 0;
117 scheduler().for_each_patchdata_nonempty([&, pmass](Patch cur_p, PatchDataLayer &pdat) {
118 PatchDataField<Tvec> &field_v = pdat.get_field<Tvec>(ivxyz);
119 PatchDataField<Tscal> &field_du = pdat.get_field<Tscal>(iduint);
120 PatchDataField<Tvec> &field_a = pdat.get_field<Tvec>(iaxyz);
121 PatchDataField<Tscal> &field_hpart = pdat.get_field<Tscal>(ihpart);
122
123 sham::DeviceBuffer<Tscal> temp_de(pdat.get_obj_cnt(), dev_sched);
124
125 Tscal const mu_0 = solver_config.get_constant_mu_0();
126
128 q,
129 sham::MultiRef{field_du.get_buf(), field_v.get_buf(), field_a.get_buf()},
130 sham::MultiRef{temp_de},
131 pdat.get_obj_cnt(),
132 [=](u32 item, const Tscal *du, const Tvec *v, const Tvec *a, Tscal *de) {
133 de[item] = pmass * (sycl::dot(v[item], a[item]) + du[item]);
134 });
135
136 if (has_B_field) {
137 PatchDataField<Tvec> &field_B_on_rho = pdat.get_field<Tvec>(iB_on_rho);
138 PatchDataField<Tvec> &field_dB_on_rho = pdat.get_field<Tvec>(idB_on_rho);
139 PatchDataField<Tscal> &field_drho_dt = pdat.get_field<Tscal>(idrho_dt);
140
142 q,
144 field_hpart.get_buf(),
145 field_B_on_rho.get_buf(),
146 field_dB_on_rho.get_buf(),
147 field_drho_dt.get_buf()},
148 sham::MultiRef{temp_de},
149 pdat.get_obj_cnt(),
150 [=](u32 item,
151 const Tscal *hpart,
152 const Tvec *B_on_rho,
153 const Tvec *dB_on_rho,
154 const Tscal *drho_dt,
155 Tscal *de) {
156 using namespace shamrock::sph;
157 Tscal h = hpart[item];
158 Tscal term_B = 0.;
159
160 Tvec B_on_rho_a = B_on_rho[item];
161 Tvec B = B_on_rho_a * shamrock::sph::rho_h(pmass, h, Kernel::hfactd);
162 Tvec dB_on_rho_a = dB_on_rho[item];
163 Tscal drho = drho_dt[item];
164 term_B = 0.5 * (1. / mu_0) * sycl::dot(B_on_rho_a, B_on_rho_a) * drho
165 + (1. / mu_0) * sycl::dot(B, dB_on_rho_a);
166
167 de[item] += pmass * term_B;
168 });
169 }
170
171 Tscal de_p = shamalgs::primitives::sum(dev_sched, temp_de, 0, pdat.get_obj_cnt());
172 tmp_de += de_p;
173 });
174
175 Tscal de = shamalgs::collective::allreduce_sum(tmp_de);
176
177 if (shamcomm::world_rank() == 0) {
178 cv_checks += shambase::format(" sum de = {}", de);
179 }
180
181 if (shamcomm::world_rank() == 0) {
182 logger::info_ln("sph::Model", cv_checks);
183 }
184}
185
186using namespace shammath;
190
std::uint32_t u32
32 bit unsigned integer
A buffer allocated in USM (Unified Shared Memory).
A SYCL queue associated with a device and a context.
Module for checking conservation of physical quantities.
void check_conservation()
Verifies conservation of mass, momentum, and energy.
u32 get_field_idx(const std::string &field_name) const
Get the field id if matching name & type.
PatchDataLayer container class, the layout is described in patchdata_layout.
void kernel_call(sham::DeviceQueue &q, RefIn in, RefOut in_out, u32 n, Functor &&func, SourceLocation &&callsite=SourceLocation{})
Submit a kernel to a SYCL queue.
T sum(const sham::DeviceScheduler_ptr &sched, const sham::DeviceBuffer< T > &buf1, u32 start_id, u32 end_id)
Compute the sum of elements in a device buffer within a specified range.
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:110
i32 world_rank()
Gives the rank of the current process in the MPI communicator.
Definition worldInfo.cpp:40
namespace for math utility
Definition AABB.hpp:26
namespace for the main framework
Definition __init__.py:1
void info_ln(std::string module_name, Types... var2)
Prints a log message with multiple arguments followed by a newline.
Definition logs.hpp:133
Helpers to access SPH sink particles stored as SoA synchronized data edges.
sph kernels
shambase::details::BasicStackEntry StackEntry
Alias for shambase::details::BasicStackEntry.
A class that references multiple buffers or similar objects.
Definition MultiRef.hpp:33
Patch object that contain generic patch information.
Definition Patch.hpp:33