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
18#include "shambase/memory.hpp"
23#include <variant>
24
25template<class Tvec, template<class> class SPHKernel>
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>
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>
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 &queue = shamsys::instance::get_compute_scheduler().get_queue();
154
155 sham::EventList depends_list;
156
157 auto divv = buf_divv.get_read_access(depends_list);
158 auto curlv = buf_curlv.get_read_access(depends_list);
159 auto dtdivv = buf_dtdivv.get_read_access(depends_list);
160 auto cs = buf_cs.get_read_access(depends_list);
161 auto h = buf_h.get_read_access(depends_list);
162 auto alpha_AV = buf_alpha_AV.get_read_access(depends_list);
163 auto alpha_AV_updated = buf_alpha_AV_updated.get_write_access(depends_list);
164
165 auto e = queue.submit(depends_list, [&, dt](sycl::handler &cgh) {
166 Tscal sigma_decay = cfg.sigma_decay;
167 Tscal alpha_min = cfg.alpha_min;
168 Tscal alpha_max = cfg.alpha_max;
169
170 cgh.parallel_for(sycl::range<1>{obj_cnt}, [=](sycl::item<1> item) {
171 Tscal cs_a = cs[item];
172 Tscal h_a = h[item];
173 Tscal alpha_a = alpha_AV[item];
174 Tscal divv_a = divv[item];
175 Tvec curlv_a = curlv[item];
176 Tscal dtdivv_a = dtdivv[item];
177
178 Tscal vsig = cs_a;
179 Tscal inv_tau_a = vsig * sigma_decay / h_a;
180 Tscal fact_t = dt * inv_tau_a;
181 Tscal euler_impl_fact = 1 / (1 + fact_t);
182
183 // Tscal div_corec = sham::max<Tscal>(-divv_a, 0);
184 // Tscal divv_a_sq = div_corec*div_corec;
186 // Tscal curlv_a_sq = sycl::dot(curlv_a,curlv_a);
187 // Tscal denom = (curlv_a_sq + divv_a_sq);
188 // Tscal balsara_corec = (denom <= 0) ? 1 : divv_a_sq / (curlv_a_sq + divv_a_sq);
189
190 auto xi_lim = [](Tscal divv, Tvec curlv) {
191 auto fac = sham::max(-divv, Tscal{0});
192 fac *= fac;
193 auto traceS = sycl::dot(curlv, curlv);
194 if (fac + traceS > shambase::get_epsilon<Tscal>()) {
195 return fac / (fac + traceS);
196 }
197 return Tscal{1};
198 };
199 Tscal balsara_corec = xi_lim(divv_a, curlv_a);
200
201 Tscal A_a = balsara_corec * sham::max<Tscal>(-dtdivv_a, 0);
202
203 Tscal temp = cs_a * cs_a;
204
205 Tscal alpha_loc_a
206 = sham::min((cs_a > 0) ? 10 * h_a * h_a * A_a / (temp) : alpha_min, alpha_max);
207
208 alpha_loc_a = (temp > shambase::get_epsilon<Tscal>()) ? alpha_loc_a : alpha_min;
209
210 // implicit euler
211 Tscal new_alpha = (alpha_a + alpha_loc_a * fact_t) * euler_impl_fact;
212
213 if (alpha_loc_a > alpha_a) {
214 new_alpha = alpha_loc_a;
215 }
216
217 alpha_AV_updated[item] = new_alpha;
218 });
219 });
220
221 buf_divv.complete_event_state(e);
222 buf_curlv.complete_event_state(e);
223 buf_dtdivv.complete_event_state(e);
224 buf_cs.complete_event_state(e);
225 buf_h.complete_event_state(e);
226 buf_alpha_AV.complete_event_state(e);
227 buf_alpha_AV_updated.complete_event_state(e);
228 });
229}
230
231using namespace shammath;
235
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.
DeviceQueue & get_queue(u32 id=0)
Get a reference to a DeviceQueue.
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 throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.
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
Patch object that contain generic patch information.
Definition Patch.hpp:33
u64 id_patch
unique key that identify the patch
Definition Patch.hpp:86