Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
KarrasRadixTreeAABB.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
19namespace shamtree {
20 template<class Tvec>
22 const KarrasRadixTree &tree, KarrasRadixTreeAABB<Tvec> &&recycled_tree_aabb) {
23
24 KarrasRadixTreeAABB<Tvec> ret = std::forward<KarrasRadixTreeAABB<Tvec>>(recycled_tree_aabb);
25
26 ret.buf_aabb_min.resize(tree.get_total_cell_count());
27 ret.buf_aabb_max.resize(tree.get_total_cell_count());
28
29 return ret;
30 }
31
32 template<class Tvec>
34
35 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
36
37 u32 int_cell_count = tree.get_internal_cell_count();
38
39 if (int_cell_count == 0) {
40 return;
41 }
42
43 auto step = [&]() {
44 auto traverser = tree.get_structure_traverser();
45
47 q,
48 sham::MultiRef{traverser},
49 sham::MultiRef{tree_aabb.buf_aabb_min, tree_aabb.buf_aabb_max},
50 int_cell_count,
51 [=](u32 gid,
52 auto tree_traverser,
53 Tvec *__restrict cell_min,
54 Tvec *__restrict cell_max) {
55 u32 left_child = tree_traverser.get_left_child(gid);
56 u32 right_child = tree_traverser.get_right_child(gid);
57
58 Tvec bminl = cell_min[left_child];
59 Tvec bminr = cell_min[right_child];
60 Tvec bmaxl = cell_max[left_child];
61 Tvec bmaxr = cell_max[right_child];
62
63 Tvec bmin = sham::min(bminl, bminr);
64 Tvec bmax = sham::max(bmaxl, bmaxr);
65
66 cell_min[gid] = bmin;
67 cell_max[gid] = bmax;
68 });
69 };
70
71 for (u32 i = 0; i < tree.tree_depth; i++) {
72 step();
73 }
74 }
75
76 template<class Tvec>
78 const KarrasRadixTree &tree,
79 KarrasRadixTreeAABB<Tvec> &&recycled_tree_aabb,
80 const std::function<void(KarrasRadixTreeAABB<Tvec> &, u32)> &fct_fill_leaf) {
81
83 tree, std::forward<KarrasRadixTreeAABB<Tvec>>(recycled_tree_aabb));
84
85 fct_fill_leaf(aabbs, tree.get_internal_cell_count());
86
87 propagate_aabb_up(aabbs, tree);
88
89 return aabbs;
90 }
91
92 template<class Tvec>
94 const KarrasRadixTree &tree,
95 const LeafCellIterator &cell_it,
96 KarrasRadixTreeAABB<Tvec> &&recycled_tree_aabb,
97 sham::DeviceBuffer<Tvec> &positions) {
99
100 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
101
102 auto fill_leafs = [&](KarrasRadixTreeAABB<Tvec> &tree_aabb, u32 leaf_offset) {
104 q,
105 sham::MultiRef{positions, cell_it},
106 sham::MultiRef{tree_aabb.buf_aabb_min, tree_aabb.buf_aabb_max},
107 tree.get_leaf_count(),
108 [leaf_offset](
109 u32 i, const Tvec *pos, auto cell_iter, Tvec *comp_min, Tvec *comp_max) {
110 // how to lose a f****ing afternoon :
111 // 1 - code a nice algorithm that should optimize the code
112 // 2 - pass all the tests
113 // 3 - benchmark it and discover big loss in perf for no reasons
114 // 4 - change a parameter and discover a segfault (on GPU to have more fun ....)
115 // 5 - find that actually the core algorithm of the code create a bug in the new
116 // thing 6 - discover that every value in everything is wrong 7 - spent the
117 // whole night on it 8 - start putting prints everywhere 9 - isolate a bugged id
118 // 10 - try to understand why a f***ing leaf is as big as the root of the tree
119 // 11 - **** a few hours latter 12 - the goddam c++ standard define
120 // std::numeric_limits<float>::min() to be epsilon instead of -max 13 - road
121 // rage 14
122 // - open a bier alt f4 the ide
125
126 cell_iter.for_each_in_leaf_cell(i, [&](u32 obj_id) {
127 Tvec r = pos[obj_id];
128
129 min = sham::min(min, r);
130 max = sham::max(max, r);
131 });
132
133 comp_min[leaf_offset + i] = min;
134 comp_max[leaf_offset + i] = max;
135 });
136 };
137
138 return compute_tree_aabb<Tvec>(
139 tree, std::forward<KarrasRadixTreeAABB<Tvec>>(recycled_tree_aabb), fill_leafs);
140 }
141
142 template<class Tvec>
144 const KarrasRadixTree &tree,
145 const LeafCellIterator &cell_it,
146 KarrasRadixTreeAABB<Tvec> &&recycled_tree_aabb,
150 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
151
152 auto fill_leafs = [&](KarrasRadixTreeAABB<Tvec> &tree_aabb, u32 leaf_offset) {
154 q,
155 sham::MultiRef{min, max, cell_it},
156 sham::MultiRef{tree_aabb.buf_aabb_min, tree_aabb.buf_aabb_max},
157 tree.get_leaf_count(),
158 [leaf_offset](
159 u32 i,
160 const Tvec *min_pos,
161 const Tvec *max_pos,
162 auto cell_iter,
163 Tvec *comp_min,
164 Tvec *comp_max) {
167
168 cell_iter.for_each_in_leaf_cell(i, [&](u32 obj_id) {
169 Tvec r_min = min_pos[obj_id];
170 Tvec r_max = max_pos[obj_id];
171
172 min = sham::min(min, r_min);
173 max = sham::max(max, r_max);
174 });
175
176 comp_min[leaf_offset + i] = min;
177 comp_max[leaf_offset + i] = max;
178 });
179 };
180
181 return compute_tree_aabb<Tvec>(
182 tree, std::forward<KarrasRadixTreeAABB<Tvec>>(recycled_tree_aabb), fill_leafs);
183 }
184
185} // namespace shamtree
186
187#ifndef DOXYGEN
188template shamtree::KarrasRadixTreeAABB<f64_3> shamtree::prepare_karras_radix_tree_aabb<f64_3>(
189 const KarrasRadixTree &tree, shamtree::KarrasRadixTreeAABB<f64_3> &&recycled_tree_aabb);
190
191template void shamtree::propagate_aabb_up<f64_3>(
192 shamtree::KarrasRadixTreeAABB<f64_3> &tree_aabb, const KarrasRadixTree &tree);
193
194template shamtree::KarrasRadixTreeAABB<f64_3> shamtree::compute_tree_aabb<f64_3>(
195 const KarrasRadixTree &tree,
196 shamtree::KarrasRadixTreeAABB<f64_3> &&recycled_tree_aabb,
197 const std::function<void(shamtree::KarrasRadixTreeAABB<f64_3> &, u32)> &fct_fill_leaf);
198
199template shamtree::KarrasRadixTreeAABB<f64_3> shamtree::compute_tree_aabb_from_positions<f64_3>(
200 const KarrasRadixTree &tree,
201 const LeafCellIterator &cell_it,
202 shamtree::KarrasRadixTreeAABB<f64_3> &&recycled_tree_aabb,
203 sham::DeviceBuffer<f64_3> &positions);
204
206 f64_3>(
207 const KarrasRadixTree &tree,
208 const LeafCellIterator &cell_it,
209 shamtree::KarrasRadixTreeAABB<f64_3> &&recycled_tree_aabb,
212#endif
void propagate_aabb_up(KarrasRadixTreeAABB< Tvec > &tree_aabb, const KarrasRadixTree &tree)
Propagates the axis-aligned bounding boxes (AABBs) upwards in the tree.
KarrasRadixTreeAABB< Tvec > compute_tree_aabb(const KarrasRadixTree &tree, KarrasRadixTreeAABB< Tvec > &&recycled_tree_aabb, const std::function< void(KarrasRadixTreeAABB< Tvec > &, u32)> &fct_fill_leaf)
Compute the AABB of all cells in the tree.
KarrasRadixTreeAABB< Tvec > compute_tree_aabb_from_position_ranges(const KarrasRadixTree &tree, const LeafCellIterator &cell_it, KarrasRadixTreeAABB< Tvec > &&recycled_tree_aabb, sham::DeviceBuffer< Tvec > &min, sham::DeviceBuffer< Tvec > &max)
same but for position ranges
KarrasRadixTreeAABB< Tvec > compute_tree_aabb_from_positions(const KarrasRadixTree &tree, const LeafCellIterator &cell_it, KarrasRadixTreeAABB< Tvec > &&recycled_tree_aabb, sham::DeviceBuffer< Tvec > &positions)
Compute the AABB of all cells in the tree from positions.
KarrasRadixTreeAABB< Tvec > prepare_karras_radix_tree_aabb(const KarrasRadixTree &tree, KarrasRadixTreeAABB< Tvec > &&recycled_tree_aabb)
Prepare a KarrasRadixTreeAABB from a KarrasRadixTree.
std::uint32_t u32
32 bit unsigned integer
A buffer allocated in USM (Unified Shared Memory)
void resize(size_t new_size, bool keep_data=true)
Resizes the buffer to a given size.
A SYCL queue associated with a device and a context.
DeviceQueue & get_queue(u32 id=0)
Get a reference to a DeviceQueue.
sham::DeviceBuffer< Tvec > buf_aabb_max
right child id (size = internal_count)
sham::DeviceBuffer< Tvec > buf_aabb_min
left child id (size = internal_count)
A data structure representing a Karras Radix Tree.
u32 get_leaf_count() const
Get leaf count.
u32 get_internal_cell_count() const
Get internal cell count.
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.
This file contains the definition for the stacktrace related functionality.
#define __shamrock_stack_entry()
Macro to create a stack entry.
A class that references multiple buffers or similar objects.