Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
UpdateViscosity.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
18#include "shambase/memory.hpp"
23#include <variant>
24
25template<class Tvec, template<class> class SPHKernel>
26void shammodels::sph::modules::UpdateViscosity<Tvec, SPHKernel>::update_artificial_viscosity(
27 Tscal dt) {
28
29 using Cfg_AV = typename Config::AVConfig;
30
31 using None = typename Cfg_AV::None;
32 using Constant = typename Cfg_AV::Constant;
33 using VaryingMM97 = typename Cfg_AV::VaryingMM97;
34 using VaryingCD10 = typename Cfg_AV::VaryingCD10;
35 using ConstantDisc = typename Cfg_AV::ConstantDisc;
36 if (None *v = std::get_if<None>(&solver_config.artif_viscosity.config)) {
37 shamlog_debug_ln("UpdateViscosity", "skipping artif viscosity update (No viscosity mode)");
38 } else if (Constant *v = std::get_if<Constant>(&solver_config.artif_viscosity.config)) {
39 shamlog_debug_ln("UpdateViscosity", "skipping artif viscosity update (Constant mode)");
40 } else if (VaryingMM97 *v = std::get_if<VaryingMM97>(&solver_config.artif_viscosity.config)) {
41 update_artificial_viscosity_mm97(dt, *v);
42 } else if (VaryingCD10 *v = std::get_if<VaryingCD10>(&solver_config.artif_viscosity.config)) {
43 update_artificial_viscosity_cd10(dt, *v);
44 } else if (ConstantDisc *v = std::get_if<ConstantDisc>(&solver_config.artif_viscosity.config)) {
45 shamlog_debug_ln("UpdateViscosity", "skipping artif viscosity update (constant AV)");
46 } else {
48 }
49}
50
51template<class Tvec, template<class> class SPHKernel>
52void shammodels::sph::modules::UpdateViscosity<Tvec, SPHKernel>::update_artificial_viscosity_mm97(
53 Tscal dt, typename Config::AVConfig::VaryingMM97 cfg) {
54 StackEntry stack_loc{};
55 shamlog_debug_ln("UpdateViscosity", "Updating alpha viscosity (Morris & Monaghan 1997)");
56
57 using namespace shamrock::patch;
58 PatchDataLayerLayout &pdl = scheduler().pdl_old();
59 const u32 ialpha_AV = pdl.get_field_idx<Tscal>("alpha_AV");
60 const u32 idivv = pdl.get_field_idx<Tscal>("divv");
61 const u32 isoundspeed = pdl.get_field_idx<Tscal>("soundspeed");
62 const u32 ihpart = pdl.get_field_idx<Tscal>("hpart");
63
64 scheduler().for_each_patchdata_nonempty([&](Patch cur_p, PatchDataLayer &pdat) {
65 sham::DeviceBuffer<Tscal> &buf_divv = pdat.get_field_buf_ref<Tscal>(idivv);
66 sham::DeviceBuffer<Tscal> &buf_cs = pdat.get_field_buf_ref<Tscal>(isoundspeed);
67 sham::DeviceBuffer<Tscal> &buf_h = pdat.get_field_buf_ref<Tscal>(ihpart);
68 sham::DeviceBuffer<Tscal> &buf_alpha_AV = pdat.get_field_buf_ref<Tscal>(ialpha_AV);
69
70 sham::DeviceBuffer<Tscal> &buf_alpha_AV_updated
71 = shambase::get_check_ref(storage.alpha_av_updated)
72 .get_refs()
73 .get(cur_p.id_patch)
74 .get()
75 .get_buf();
76
77 u32 obj_cnt = pdat.get_obj_cnt();
78
79 sham::DeviceQueue &queue = shamsys::instance::get_compute_scheduler().get_queue();
80
81 sham::EventList depends_list;
82
83 auto divv = buf_divv.get_read_access(depends_list);
84 auto cs = buf_cs.get_read_access(depends_list);
85 auto h = buf_h.get_read_access(depends_list);
86 auto alpha_AV = buf_alpha_AV.get_read_access(depends_list);
87 auto alpha_AV_updated = buf_alpha_AV_updated.get_write_access(depends_list);
88
89 auto e = queue.submit(depends_list, [&, dt](sycl::handler &cgh) {
90 Tscal sigma_decay = cfg.sigma_decay;
91 Tscal alpha_min = cfg.alpha_min;
92 Tscal alpha_max = cfg.alpha_max;
93
94 cgh.parallel_for(sycl::range<1>{obj_cnt}, [=](sycl::item<1> item) {
95 Tscal cs_a = cs[item];
96 Tscal h_a = h[item];
97 Tscal alpha_a = alpha_AV[item];
98 Tscal divv_a = divv[item];
99
100 Tscal vsig = cs_a;
101 Tscal inv_tau_a = vsig * sigma_decay / h_a;
102 Tscal fact_t = dt * inv_tau_a;
103 Tscal euler_impl_fact = 1 / (1 + fact_t);
104
105 Tscal source = sham::max<Tscal>(0., -divv_a);
106
107 Tscal new_alpha = (alpha_a + source * dt + fact_t * alpha_min) * euler_impl_fact;
108
109 alpha_AV_updated[item] = sham::min(alpha_max, new_alpha);
110 });
111 });
112
113 buf_divv.complete_event_state(e);
114 buf_cs.complete_event_state(e);
115 buf_h.complete_event_state(e);
116 buf_alpha_AV.complete_event_state(e);
117 buf_alpha_AV_updated.complete_event_state(e);
118 });
119}
120
121template<class Tvec, template<class> class SPHKernel>
122void shammodels::sph::modules::UpdateViscosity<Tvec, SPHKernel>::update_artificial_viscosity_cd10(
123 Tscal dt, typename Config::AVConfig::VaryingCD10 cfg) {
124
125 StackEntry stack_loc{};
126 shamlog_debug_ln("UpdateViscosity", "Updating alpha viscosity (Cullen & Dehnen 2010)");
127
128 using namespace shamrock::patch;
129 PatchDataLayerLayout &pdl = scheduler().pdl_old();
130 const u32 ialpha_AV = pdl.get_field_idx<Tscal>("alpha_AV");
131 const u32 idivv = pdl.get_field_idx<Tscal>("divv");
132 const u32 idtdivv = pdl.get_field_idx<Tscal>("dtdivv");
133 const u32 icurlv = pdl.get_field_idx<Tvec>("curlv");
134 const u32 isoundspeed = pdl.get_field_idx<Tscal>("soundspeed");
135 const u32 ihpart = pdl.get_field_idx<Tscal>("hpart");
136
137 scheduler().for_each_patchdata_nonempty([&](Patch cur_p, PatchDataLayer &pdat) {
138 sham::DeviceBuffer<Tscal> &buf_divv = pdat.get_field_buf_ref<Tscal>(idivv);
139 sham::DeviceBuffer<Tscal> &buf_dtdivv = pdat.get_field_buf_ref<Tscal>(idtdivv);
140 sham::DeviceBuffer<Tvec> &buf_curlv = pdat.get_field_buf_ref<Tvec>(icurlv);
141 sham::DeviceBuffer<Tscal> &buf_cs = pdat.get_field_buf_ref<Tscal>(isoundspeed);
142 sham::DeviceBuffer<Tscal> &buf_h = pdat.get_field_buf_ref<Tscal>(ihpart);
143 sham::DeviceBuffer<Tscal> &buf_alpha_AV = pdat.get_field_buf_ref<Tscal>(ialpha_AV);
144 sham::DeviceBuffer<Tscal> &buf_alpha_AV_updated
145 = shambase::get_check_ref(storage.alpha_av_updated)
146 .get_refs()
147 .get(cur_p.id_patch)
148 .get()
149 .get_buf();
150
151 u32 obj_cnt = pdat.get_obj_cnt();
152
153 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
154
156 q,
157 sham::MultiRef{buf_divv, buf_curlv, buf_dtdivv, buf_cs, buf_h, buf_alpha_AV},
158 sham::MultiRef{buf_alpha_AV_updated},
159 obj_cnt,
160 [sigma_decay = cfg.sigma_decay,
161 alpha_min = cfg.alpha_min,
162 alpha_max = cfg.alpha_max,
163 dt](
164 u32 i,
165 const Tscal *__restrict divv,
166 const Tvec *__restrict curlv,
167 const Tscal *__restrict dtdivv,
168 const Tscal *__restrict cs,
169 const Tscal *__restrict h,
170 const Tscal *__restrict alpha_AV,
171 Tscal *__restrict alpha_AV_updated) {
172 Tscal cs_a = cs[i];
173 Tscal h_a = h[i];
174 Tscal alpha_a = alpha_AV[i];
175 Tscal divv_a = divv[i];
176 Tvec curlv_a = curlv[i];
177 Tscal dtdivv_a = dtdivv[i];
178
179 Tscal vsig = cs_a;
180 Tscal inv_tau_a = vsig * sigma_decay / h_a;
181 Tscal fact_t = dt * inv_tau_a;
182 Tscal euler_impl_fact = 1 / (1 + fact_t);
183
184 // Tscal div_corec = sham::max<Tscal>(-divv_a, 0);
185 // Tscal divv_a_sq = div_corec*div_corec;
187 // Tscal curlv_a_sq = sycl::dot(curlv_a,curlv_a);
188 // Tscal denom = (curlv_a_sq + divv_a_sq);
189 // Tscal balsara_corec = (denom <= 0) ? 1 : divv_a_sq / (curlv_a_sq + divv_a_sq);
190
191 auto xi_lim = [](Tscal divv, Tvec curlv) {
192 auto fac = sham::max(-divv, Tscal{0});
193 fac *= fac;
194 auto traceS = sycl::dot(curlv, curlv);
195 if (fac + traceS > shambase::get_epsilon<Tscal>()) {
196 return fac / (fac + traceS);
197 }
198 return Tscal{1};
199 };
200 Tscal balsara_corec = xi_lim(divv_a, curlv_a);
201
202 Tscal A_a = balsara_corec * sham::max<Tscal>(-dtdivv_a, 0);
203
204 Tscal temp = cs_a * cs_a;
205
206 Tscal alpha_loc_a
207 = sham::min((cs_a > 0) ? 10 * h_a * h_a * A_a / (temp) : alpha_min, alpha_max);
208
209 alpha_loc_a = (temp > shambase::get_epsilon<Tscal>()) ? alpha_loc_a : alpha_min;
210
211 // implicit euler
212 Tscal new_alpha = (alpha_a + alpha_loc_a * fact_t) * euler_impl_fact;
213
214 if (alpha_loc_a > alpha_a) {
215 new_alpha = alpha_loc_a;
216 }
217
218 alpha_AV_updated[i] = new_alpha;
219 });
220 });
221}
222
223using namespace shammath;
227
std::uint32_t u32
32 bit unsigned integer
A buffer allocated in USM (Unified Shared Memory).
void complete_event_state(sycl::event e) const
Complete the event state of the buffer.
const T * get_read_access(sham::EventList &depends_list, SourceLocation src_loc=SourceLocation{}) const
Get a read-only pointer to the buffer's data.
A SYCL queue associated with a device and a context.
sycl::event submit(Fct &&fct)
Submits a kernel to the SYCL queue.
Class to manage a list of SYCL events.
Definition EventList.hpp:31
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 & 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
void throw_unimplemented(SourceLocation loc=SourceLocation{})
Throw a std::runtime_error saying that the function is unimplemented.
namespace for math utility
Definition AABB.hpp:26
file containing formulas for sph forces
sph kernels
shambase::details::BasicStackEntry StackEntry
Alias for shambase::details::BasicStackEntry.
A class that references multiple buffers or similar objects.
Patch object that contain generic patch information.
Definition Patch.hpp:33
u64 id_patch
unique key that identify the patch
Definition Patch.hpp:86