Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
SlopeLimitedGradientUtilities.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
19
20#include "shamcomm/logs.hpp"
21#include "shammath/riemann.hpp"
25#include <type_traits>
26
27namespace {
29 using Direction = shammodels::basegodunov::modules::Direction;
30
31 template<class T>
32 inline T slope_function_van_leer_f_form(T sL, T sR) {
33 T st = sL + sR;
34
35 auto vanleer = [](T f) {
36 return 4. * f * (1. - f);
37 };
38
39 auto slopelim = [&](T f) {
40 if constexpr (std::is_same_v<T, f64_3>) {
41 f.x() = (f.x() >= 0 && f.x() <= 1) ? f.x() : 0;
42 f.y() = (f.y() >= 0 && f.y() <= 1) ? f.y() : 0;
43 f.z() = (f.z() >= 0 && f.z() <= 1) ? f.z() : 0;
44 } else {
45 f = (f >= 0 && f <= 1) ? f : 0;
46 }
47 return vanleer(f);
48 };
49
50 return slopelim(sL / st) * st * 0.5;
51 }
52
53 template<class T>
54 inline T slope_function_van_leer_symetric(T sL, T sR) {
55
56 if constexpr (std::is_same_v<T, f64_3>) {
57 return {
58 shammath::van_leer_slope_symetric(sL[0], sR[0]),
59 shammath::van_leer_slope_symetric(sL[1], sR[1]),
60 shammath::van_leer_slope_symetric(sL[2], sR[2])};
61 } else {
62 return shammath::van_leer_slope_symetric(sL, sR);
63 }
64 }
65
66 template<class T>
67 inline T slope_function_van_leer_standard(T sL, T sR) {
68
69 if constexpr (std::is_same_v<T, f64_3>) {
70 return {
71 shammath::van_leer_slope(sL[0], sR[0]),
72 shammath::van_leer_slope(sL[1], sR[1]),
73 shammath::van_leer_slope(sL[2], sR[2])};
74 } else {
75 return shammath::van_leer_slope(sL, sR);
76 }
77 }
78
79 template<class T>
80 inline T slope_function_minmod(T sL, T sR) {
81
82 if constexpr (std::is_same_v<T, f64_3>) {
83 return {
84 shammath::minmod(sL[0], sR[0]),
85 shammath::minmod(sL[1], sR[1]),
86 shammath::minmod(sL[2], sR[2])};
87 } else {
88 return shammath::minmod(sL, sR);
89 }
90 }
91
93
94 template<class T, SlopeMode mode>
95 inline T slope_function(T sL, T sR) {
96 if constexpr (mode == SlopeMode::None) {
97 return sham::VectorProperties<T>::get_zero();
98 }
99
100 if constexpr (mode == SlopeMode::VanLeer_f) {
101 return slope_function_van_leer_f_form(sL, sR);
102 }
103
104 if constexpr (mode == SlopeMode::VanLeer_std) {
105 return slope_function_van_leer_standard(sL, sR);
106 }
107
108 if constexpr (mode == SlopeMode::VanLeer_sym) {
109 return slope_function_van_leer_symetric(sL, sR);
110 }
111
112 if constexpr (mode == SlopeMode::Minmod) {
113 return slope_function_minmod(sL, sR);
114 }
115 }
116
135 template<class Tfield, class Tvec, SlopeMode mode, class ACCField>
136 inline std::array<Tfield, 3> get_3d_grad(
137 const f64 *cell_sizes,
138 const u32 block_size,
139 const u32 cell_global_id,
140 const AMRGraphLinkiterator &graph_iter_xp,
141 const AMRGraphLinkiterator &graph_iter_xm,
142 const AMRGraphLinkiterator &graph_iter_yp,
143 const AMRGraphLinkiterator &graph_iter_ym,
144 const AMRGraphLinkiterator &graph_iter_zp,
145 const AMRGraphLinkiterator &graph_iter_zm,
146 ACCField &&field_access) {
147
148 auto cur_cell_block_id = cell_global_id / block_size;
149
150 auto get_gradiant_dir = [&](auto &graph_links, Direction dir) -> Tfield {
151 Tfield acc = shambase::VectorProperties<Tfield>::get_zero();
152 auto cell_center_dist = cell_sizes[cur_cell_block_id];
153 auto fac = 1.;
154 u32 cnt = graph_links.for_each_object_link_cnt(cell_global_id, [&](u32 id_b) {
155 auto neigh_block_id = id_b / block_size;
156
157 int sign = 1 - 2 * (dir % 2);
158 acc += sign * (field_access(id_b) - field_access(cell_global_id));
159
160 if (cell_sizes[neigh_block_id] > cell_sizes[cur_cell_block_id]) {
161 fac = (3. / 2.);
162 }
163 // This logic suppose that the last (4-th) cell at interface have same size with the
164 // other three cells. This is also consitent with 2:1 refinement.
165 // TODO: extended to anisotropic mesh
166 if (cell_sizes[neigh_block_id] < cell_sizes[cur_cell_block_id]) {
167 fac = (3. / 4.);
168 }
169 });
170 return (cnt > 0) ? acc / (cell_center_dist * fac * cnt)
171 : shambase::VectorProperties<Tfield>::get_zero();
172 };
173
174 Tfield delta_xp = get_gradiant_dir(graph_iter_xp, Direction::xp);
175 Tfield delta_xm = get_gradiant_dir(graph_iter_xm, Direction::xm);
176 Tfield delta_yp = get_gradiant_dir(graph_iter_yp, Direction::yp);
177 Tfield delta_ym = get_gradiant_dir(graph_iter_ym, Direction::ym);
178 Tfield delta_zp = get_gradiant_dir(graph_iter_zp, Direction::zp);
179 Tfield delta_zm = get_gradiant_dir(graph_iter_zm, Direction::zm);
180 return {
181 slope_function<Tfield, mode>(
182 get_gradiant_dir(graph_iter_xm, Direction::xm),
183 get_gradiant_dir(graph_iter_xp, Direction::xp)),
184 slope_function<Tfield, mode>(
185 get_gradiant_dir(graph_iter_ym, Direction::ym),
186 get_gradiant_dir(graph_iter_yp, Direction::yp)),
187 slope_function<Tfield, mode>(
188 get_gradiant_dir(graph_iter_zm, Direction::zm),
189 get_gradiant_dir(graph_iter_zp, Direction::zp))};
190 }
191
214 template<class Tvec, SlopeMode mode, class ACCField1, class ACCField2, class ACCField3>
215 inline std::array<shammath::ConsState<Tvec>, 3> get_3d_grad_cons(
216 const u32 cell_global_id,
217 const shambase::VecComponent<Tvec> delta_cell,
218 const AMRGraphLinkiterator &graph_iter_xp,
219 const AMRGraphLinkiterator &graph_iter_xm,
220 const AMRGraphLinkiterator &graph_iter_yp,
221 const AMRGraphLinkiterator &graph_iter_ym,
222 const AMRGraphLinkiterator &graph_iter_zp,
223 const AMRGraphLinkiterator &graph_iter_zm,
224 ACCField1 &&field_access_rho,
225 ACCField2 &&field_access_rho_vel,
226 ACCField3 &&field_access_rhoe) {
227
228 using Tscal = shambase::VecComponent<Tvec>;
229
230 auto get_avg_neigh = [&](auto &graph_links) -> shammath::ConsState<Tvec> {
231 Tscal acc_rho = shambase::VectorProperties<Tscal>::get_zero();
232 Tscal acc_rhoe = shambase::VectorProperties<Tscal>::get_zero();
233 Tvec acc_rho_vel = shambase::VectorProperties<Tvec>::get_zero();
234 u32 cnt = graph_links.for_each_object_link_cnt(cell_global_id, [&](u32 id_b) {
235 acc_rho += field_access_rho(id_b);
236 acc_rho_vel += field_access_rho_vel(id_b);
237 acc_rhoe += field_access_rhoe(id_b);
238 });
239
241 = {shambase::VectorProperties<Tscal>::get_zero(),
242 shambase::VectorProperties<Tscal>::get_zero(),
243
244 {shambase::VectorProperties<Tscal>::get_zero(),
245 shambase::VectorProperties<Tscal>::get_zero(),
246 shambase::VectorProperties<Tscal>::get_zero()}};
247
248 if (cnt > 0) {
249 res = {acc_rho, acc_rhoe, acc_rho_vel};
250 res *= (1. / cnt);
251 }
252
253 return res;
254 };
255
257 = {field_access_rho(cell_global_id),
258 field_access_rhoe(cell_global_id),
259 field_access_rho_vel(cell_global_id)};
260
261 shammath::ConsState<Tvec> W_xp = get_avg_neigh(graph_iter_xp);
262 shammath::ConsState<Tvec> W_xm = get_avg_neigh(graph_iter_xm);
263 shammath::ConsState<Tvec> W_yp = get_avg_neigh(graph_iter_yp);
264 shammath::ConsState<Tvec> W_ym = get_avg_neigh(graph_iter_ym);
265 shammath::ConsState<Tvec> W_zp = get_avg_neigh(graph_iter_zp);
266 shammath::ConsState<Tvec> W_zm = get_avg_neigh(graph_iter_zm);
267
268 shammath::ConsState<Tvec> delta_W_x_p = W_xp - W_i;
269 shammath::ConsState<Tvec> delta_W_y_p = W_yp - W_i;
270 shammath::ConsState<Tvec> delta_W_z_p = W_zp - W_i;
271
272 shammath::ConsState<Tvec> delta_W_x_m = W_i - W_xm;
273 shammath::ConsState<Tvec> delta_W_y_m = W_i - W_ym;
274 shammath::ConsState<Tvec> delta_W_z_m = W_i - W_zm;
275
276 Tscal fact = 1. / delta_cell;
277
278 shammath::ConsState<Tvec> lim_slope_W_x
279 = {slope_function<Tscal, mode>(delta_W_x_m.rho * fact, delta_W_x_p.rho * fact),
280 slope_function<Tscal, mode>(delta_W_x_m.rhoe * fact, delta_W_x_p.rhoe * fact),
281 slope_function<Tvec, mode>(delta_W_x_m.rhovel * fact, delta_W_x_p.rhovel * fact)};
282
283 shammath::ConsState<Tvec> lim_slope_W_y
284 = {slope_function<Tscal, mode>(delta_W_y_m.rho * fact, delta_W_y_p.rho * fact),
285 slope_function<Tscal, mode>(delta_W_y_m.rhoe * fact, delta_W_y_p.rhoe * fact),
286 slope_function<Tvec, mode>(delta_W_y_m.rhovel * fact, delta_W_y_p.rhovel * fact)};
287
288 shammath::ConsState<Tvec> lim_slope_W_z
289 = {slope_function<Tscal, mode>(delta_W_z_m.rho * fact, delta_W_z_p.rho * fact),
290 slope_function<Tscal, mode>(delta_W_z_m.rhoe * fact, delta_W_z_p.rhoe * fact),
291 slope_function<Tvec, mode>(delta_W_z_m.rhovel * fact, delta_W_z_p.rhovel * fact)};
292
293 return {lim_slope_W_x, lim_slope_W_y, lim_slope_W_z};
294 }
295
299 template<class T, class Tvec, class ACCField>
300 inline T get_pseudo_grad(
301 const u32 cell_global_id,
302 const AMRGraphLinkiterator &graph_iter_xp,
303 const AMRGraphLinkiterator &graph_iter_xm,
304 const AMRGraphLinkiterator &graph_iter_yp,
305 const AMRGraphLinkiterator &graph_iter_ym,
306 const AMRGraphLinkiterator &graph_iter_zp,
307 const AMRGraphLinkiterator &graph_iter_zm,
308 ACCField &&field_access)
309
310 {
311
312 using namespace sham;
313 using namespace sham::details;
314
315 auto get_avg_neigh = [&](auto &graph_links, u32 dir) -> T {
316 T acc = shambase::VectorProperties<T>::get_zero();
317 u32 cnt = graph_links.for_each_object_link_cnt(cell_global_id, [&](u32 id_b) {
318 acc += field_access(id_b);
319 });
320
321 return (cnt > 0) ? acc / cnt : shambase::VectorProperties<T>::get_zero();
322 };
323
324 auto epsilon = shambase::get_epsilon<T>();
325 T u_cur = field_access(cell_global_id);
326 T u_xp = get_avg_neigh(graph_iter_xp, 0);
327 T u_xm = get_avg_neigh(graph_iter_xm, 1);
328 T u_yp = get_avg_neigh(graph_iter_yp, 2);
329 T u_ym = get_avg_neigh(graph_iter_ym, 3);
330 T u_zp = get_avg_neigh(graph_iter_zp, 4);
331 T u_zm = get_avg_neigh(graph_iter_zm, 5);
332
333 // RAMSES LIKE
334
335 T x_scal = 2
336 * g_sycl_max(
337 g_sycl_abs((u_cur - u_xm) / (epsilon + u_cur + u_xm)),
338 g_sycl_abs((u_cur - u_xp) / (epsilon + u_cur + u_xp)));
339
340 T y_scal = 2
341 * g_sycl_max(
342 g_sycl_abs((u_cur - u_ym) / (epsilon + u_cur + u_ym)),
343 g_sycl_abs((u_cur - u_yp) / (epsilon + u_cur + u_yp)));
344 T z_scal = 2
345 * g_sycl_max(
346 g_sycl_abs((u_cur - u_zm) / (epsilon + u_cur + u_zm)),
347 g_sycl_abs((u_cur - u_zp) / (epsilon + u_cur + u_zp)));
348
349 T res = g_sycl_max(x_scal, g_sycl_max(y_scal, z_scal));
350 return res;
351 }
352
355 template<class T, class ACCField>
356 inline T baryonic_normalized_slope_criterion(
357 const u32 cell_global_id,
358 const AMRGraphLinkiterator &graph_iter_xp,
359 const AMRGraphLinkiterator &graph_iter_xm,
360 const AMRGraphLinkiterator &graph_iter_yp,
361 const AMRGraphLinkiterator &graph_iter_ym,
362 const AMRGraphLinkiterator &graph_iter_zp,
363 const AMRGraphLinkiterator &graph_iter_zm,
364 ACCField &&field_access)
365
366 {
367
368 using namespace sham;
369 using namespace sham::details;
370
371 auto get_avg_neigh = [&](auto &graph_links, u32 dir) -> T {
372 T acc = shambase::VectorProperties<T>::get_zero();
373 u32 cnt = graph_links.for_each_object_link_cnt(cell_global_id, [&](u32 id_b) {
374 acc += field_access(id_b);
375 });
376
377 return (cnt > 0) ? acc / cnt : shambase::VectorProperties<T>::get_zero();
378 };
379
380 auto epsilon = shambase::get_epsilon<T>();
381 T u_cur = field_access(cell_global_id);
382 T u_xp = get_avg_neigh(graph_iter_xp, 0);
383 T u_xm = get_avg_neigh(graph_iter_xm, 1);
384 T u_yp = get_avg_neigh(graph_iter_yp, 2);
385 T u_ym = get_avg_neigh(graph_iter_ym, 3);
386 T u_zp = get_avg_neigh(graph_iter_zp, 4);
387 T u_zm = get_avg_neigh(graph_iter_zm, 5);
388
389 T norm_slope_x = g_sycl_abs((u_xm - u_xp) / (2 * u_cur + epsilon));
390 T norm_slope_y = g_sycl_abs((u_ym - u_yp) / (2 * u_cur + epsilon));
391 T norm_slope_z = g_sycl_abs((u_zm - u_zp) / (2 * u_cur + epsilon));
392
393 T res = g_sycl_max(norm_slope_x, g_sycl_max(norm_slope_y, norm_slope_z));
394
395 return res;
396 }
397
398 /***
399 * Lohner second order criterion
400 */
401 template<class T, class Tvec, class ACCField>
402 inline T modif_second_derivative(
403 const u32 cell_global_id,
404 const AMRGraphLinkiterator &graph_iter_xp,
405 const AMRGraphLinkiterator &graph_iter_xm,
406 const AMRGraphLinkiterator &graph_iter_yp,
407 const AMRGraphLinkiterator &graph_iter_ym,
408 const AMRGraphLinkiterator &graph_iter_zp,
409 const AMRGraphLinkiterator &graph_iter_zm,
410 ACCField &&field_access) {
411 using namespace sham;
412 using namespace sham::details;
413
414 auto get_avg_neigh = [&](auto &graph_links) -> T {
415 T acc = shambase::VectorProperties<T>::get_zero();
416 u32 cnt = graph_links.for_each_object_link_cnt(cell_global_id, [&](u32 id_b) {
417 acc += field_access(id_b);
418 });
419 return (cnt > 0) ? acc / cnt : shambase::VectorProperties<T>::get_zero();
420 };
421
422 auto eps_ref = 0.01;
423 auto epsilon = shambase::get_epsilon<T>();
424 T u_cur = field_access(cell_global_id);
425 T u_xp = get_avg_neigh(graph_iter_xp);
426 T u_xm = get_avg_neigh(graph_iter_xm);
427 T u_yp = get_avg_neigh(graph_iter_yp);
428 T u_ym = get_avg_neigh(graph_iter_ym);
429 T u_zp = get_avg_neigh(graph_iter_zp);
430 T u_zm = get_avg_neigh(graph_iter_zm);
431
432 T delta_u_xp = u_xp - u_cur;
433 T delta_u_xm = u_xm - u_cur;
434 T delta_u_yp = u_yp - u_cur;
435 T delta_u_ym = u_ym - u_cur;
436 T delta_u_zp = u_zp - u_cur;
437 T delta_u_zm = u_zm - u_cur;
438
439 T scalar_x = g_sycl_abs(u_xp) + g_sycl_abs(u_xm) + 2 * g_sycl_abs(u_cur);
440 T scalar_y = g_sycl_abs(u_yp) + g_sycl_abs(u_ym) + 2 * g_sycl_abs(u_cur);
441 T scalar_z = g_sycl_abs(u_zp) + g_sycl_abs(u_zm) + 2 * g_sycl_abs(u_cur);
442
443 T res_x
444 = g_sycl_abs(delta_u_xm + delta_u_xp)
445 / (g_sycl_abs(delta_u_xm) + g_sycl_abs(delta_u_xp) + eps_ref * scalar_x + epsilon);
446 T res_y
447 = g_sycl_abs(delta_u_ym + delta_u_yp)
448 / (g_sycl_abs(delta_u_ym) + g_sycl_abs(delta_u_yp) + eps_ref * scalar_y + epsilon);
449 T res_z
450 = g_sycl_abs(delta_u_zm + delta_u_zp)
451 / (g_sycl_abs(delta_u_zm) + g_sycl_abs(delta_u_zp) + eps_ref * scalar_z + epsilon);
452
453 return (res_x + res_y + res_z);
454 }
455
459 template<class Tvec, class ACCField>
460 inline shambase::VecComponent<Tvec> normalized_shear(
461 const u32 cell_global_id,
462 const f32 sound_speed,
463 const Tvec delta_cells,
464 const AMRGraphLinkiterator &graph_iter_xp,
465 const AMRGraphLinkiterator &graph_iter_xm,
466 const AMRGraphLinkiterator &graph_iter_yp,
467 const AMRGraphLinkiterator &graph_iter_ym,
468 const AMRGraphLinkiterator &graph_iter_zp,
469 const AMRGraphLinkiterator &graph_iter_zm,
470 ACCField &&field_access)
471
472 {
473
474 using namespace sham;
475 using namespace sham::details;
476
477 auto get_avg_neigh = [&](auto &graph_links, u32 dir) -> Tvec {
478 Tvec acc = shambase::VectorProperties<Tvec>::get_zero();
479 u32 cnt = graph_links.for_each_object_link_cnt(cell_global_id, [&](u32 id_b) {
480 acc += field_access(id_b);
481 });
482
483 return (cnt > 0) ? acc / cnt : shambase::VectorProperties<Tvec>::get_zero();
484 };
485
486 Tvec u_xp = get_avg_neigh(graph_iter_xp, 0);
487 Tvec u_xm = get_avg_neigh(graph_iter_xm, 1);
488 Tvec u_yp = get_avg_neigh(graph_iter_yp, 2);
489 Tvec u_ym = get_avg_neigh(graph_iter_ym, 3);
490 Tvec u_zp = get_avg_neigh(graph_iter_zp, 4);
491 Tvec u_zm = get_avg_neigh(graph_iter_zm, 5);
492
493 auto vgy = 0.25 * (u_xp[1] - u_xm[1]) * (u_xp[1] - u_xm[1]);
494 auto vgx = 0.25 * (u_yp[0] - u_ym[0]) * (u_yp[0] - u_ym[0]);
495
496 return vgy + vgx;
497
501 // auto dv_xdir = 0.5 * sycl::abs(u_xp - u_xm);
502 // auto dv_ydir = 0.5 * sycl::abs(u_yp - u_ym);
503 // auto dv_zdir = 0.5 * sycl::abs(u_zp - u_zm) ;
504 // auto shear_1 = (dv_ydir[0] + dv_xdir[1])*(dv_ydir[0] + dv_xdir[1]);
505 // auto shear_2 = (dv_ydir[2] + dv_zdir[1]) * (dv_ydir[2] + dv_zdir[1]);
506 // auto shear_3 = (dv_zdir[0] + dv_xdir[2]) * (dv_zdir[0] + dv_xdir[2]);
507 // return (shear_1 + shear_2 + shear_3) * (delta_cells.x() * delta_cells.x())/(sound_speed
508 // * sound_speed);
509 }
510
511} // namespace
double f64
Alias for double.
float f32
Alias for float.
std::uint32_t u32
32 bit unsigned integer
namespace for backends this one is named only sham since shambackends is too long to write
namespace for basic c++ utilities
T van_leer_slope(T f, T g)
Van leer slope limiter.
SlopeMode
Slope limiter modes.
From original version by Thomas Guillet (T.A.Guillet@exeter.ac.uk).
Math header to compute slope limiters.