Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
karras_alg.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#include "shambackends/math.hpp"
19#include <stdexcept>
20
21#define SGN(x) (x == 0) ? 0 : ((x > 0) ? 1 : -1)
22
23template<class u_morton, class kername>
24void __sycl_karras_alg(
25 sycl::queue &queue,
26 u32 internal_cell_count,
27 sycl::buffer<u_morton> &in_morton,
28 sycl::buffer<u32> &out_buf_lchild_id,
29 sycl::buffer<u32> &out_buf_rchild_id,
30 sycl::buffer<u8> &out_buf_lchild_flag,
31 sycl::buffer<u8> &out_buf_rchild_flag,
32 sycl::buffer<u32> &out_buf_endrange) {
33
34 sycl::range<1> range_radix_tree{internal_cell_count};
35
36 queue.submit([&](sycl::handler &cgh) {
37 //@TODO add check if split count above 2G
38 i32 morton_length = (i32) internal_cell_count + 1;
39
40 auto m = in_morton.template get_access<sycl::access::mode::read>(cgh);
41
42 auto lchild_id = out_buf_lchild_id.get_access<sycl::access::mode::discard_write>(cgh);
43 auto rchild_id = out_buf_rchild_id.get_access<sycl::access::mode::discard_write>(cgh);
44 auto lchild_flag = out_buf_lchild_flag.get_access<sycl::access::mode::discard_write>(cgh);
45 auto rchild_flag = out_buf_rchild_flag.get_access<sycl::access::mode::discard_write>(cgh);
46 auto end_range_cell = out_buf_endrange.get_access<sycl::access::mode::discard_write>(cgh);
47
48 cgh.parallel_for<kername>(range_radix_tree, [=](sycl::item<1> item) {
49 int i = (int) item.get_id(0);
50
51 auto DELTA = [=](i32 x, i32 y) {
52 return sham::karras_delta(x, y, morton_length, m);
53 };
54
55 int ddelta = DELTA(i, i + 1) - DELTA(i, i - 1);
56
57 int d = SGN(ddelta);
58
59 // Compute upper bound for the length of the range
60 int delta_min = DELTA(i, i - d);
61 int lmax = 2;
62 while (DELTA(i, i + lmax * d) > delta_min) {
63 lmax *= 2;
64 }
65
66 // Find the other end using
67 int l = 0;
68 int t = lmax / 2;
69 while (t > 0) {
70 if (DELTA(i, i + (l + t) * d) > delta_min) {
71 l = l + t;
72 }
73 t = t / 2;
74 }
75 int j = i + l * d;
76
77 end_range_cell[i] = j;
78
79 // Find the split position using binary search
80 int delta_node = DELTA(i, j);
81 int s = 0;
82
83 //@todo why float
84 float div = 2;
85 t = sycl::ceil(l / div);
86 while (true) {
87 int tmp_ = i + (s + t) * d;
88 if (DELTA(i, tmp_) > delta_node) {
89 s = s + t;
90 }
91 if (t <= 1)
92 break;
93 div *= 2;
94 t = sycl::ceil(l / div);
95 }
96 int gamma = i + s * d + sycl::min(d, 0);
97
98 if (sycl::min(i, j) == gamma) {
99 lchild_id[i] = gamma;
100 lchild_flag[i] = 1; // leaf
101 } else {
102 lchild_id[i] = gamma;
103 lchild_flag[i] = 0; // leaf
104 }
105
106 if (sycl::max(i, j) == gamma + 1) {
107 rchild_id[i] = gamma + 1;
108 rchild_flag[i] = 1; // leaf
109 } else {
110 rchild_id[i] = gamma + 1;
111 rchild_flag[i] = 0; // leaf
112 }
113 });
114 }
115
116 );
117}
118
119class Kernel_Karras_alg_morton32;
120class Kernel_Karras_alg_morton64;
121
122template<>
123void sycl_karras_alg<u32>(
124 sycl::queue &queue,
125 u32 internal_cell_count,
126 sycl::buffer<u32> &in_morton,
127 sycl::buffer<u32> &out_buf_lchild_id,
128 sycl::buffer<u32> &out_buf_rchild_id,
129 sycl::buffer<u8> &out_buf_lchild_flag,
130 sycl::buffer<u8> &out_buf_rchild_flag,
131 sycl::buffer<u32> &out_buf_endrange) {
132 __sycl_karras_alg<u32, Kernel_Karras_alg_morton32>(
133 queue,
134 internal_cell_count,
135 in_morton,
136 out_buf_lchild_id,
137 out_buf_rchild_id,
138 out_buf_lchild_flag,
139 out_buf_rchild_flag,
140 out_buf_endrange);
141}
142
143template<>
144void sycl_karras_alg<u64>(
145 sycl::queue &queue,
146 u32 internal_cell_count,
147 sycl::buffer<u64> &in_morton,
148 sycl::buffer<u32> &out_buf_lchild_id,
149 sycl::buffer<u32> &out_buf_rchild_id,
150 sycl::buffer<u8> &out_buf_lchild_flag,
151 sycl::buffer<u8> &out_buf_rchild_flag,
152 sycl::buffer<u32> &out_buf_endrange) {
153 __sycl_karras_alg<u64, Kernel_Karras_alg_morton64>(
154 queue,
155 internal_cell_count,
156 in_morton,
157 out_buf_lchild_id,
158 out_buf_rchild_id,
159 out_buf_lchild_flag,
160 out_buf_rchild_flag,
161 out_buf_endrange);
162}
#define SGN(x)
Macro to get the sign of a number.
std::uint32_t u32
32 bit unsigned integer
std::int32_t i32
32 bit integer
This header file contains utility functions related to exception handling in the code.
i32 karras_delta(i32 x, i32 y, u32 morton_length, Acc m) noexcept
delta operator defined in Karras 2012
Definition math.hpp:826