Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
NodeBuildTrees.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 "shambase/time.hpp"
19#include "shammath/AABB.hpp"
22
23namespace {
24 template<class Umorton, class TgridVec>
25 void __internal_correct_tree_bb(
29
30 u32 leaf_count = tree.tree_reduced_morton_codes.tree_leaf_count;
31 u32 internal_cell_count = tree.tree_struct.internal_cell_count;
32 u32 tot_count = leaf_count + internal_cell_count;
33
34 sycl::buffer<TgridVec> tmp_min_cell(tot_count);
35 sycl::buffer<TgridVec> tmp_max_cell(tot_count);
36
37 sham::DeviceBuffer<TgridVec> &buf_cell_min = block_min;
38 sham::DeviceBuffer<TgridVec> &buf_cell_max = block_max;
39
40 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
41
42 sham::EventList depends_list;
43 auto acc_bmin = buf_cell_min.get_read_access(depends_list);
44 auto acc_bmax = buf_cell_max.get_read_access(depends_list);
45
46 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
47 shamrock::tree::ObjectIterator cell_looper(tree, cgh);
48
49 u32 leaf_offset = tree.tree_struct.internal_cell_count;
50
51 sycl::accessor comp_min{tmp_min_cell, cgh, sycl::write_only, sycl::no_init};
52 sycl::accessor comp_max{tmp_max_cell, cgh, sycl::write_only, sycl::no_init};
53
56
57 shambase::parallel_for(cgh, leaf_count, "compute leaf boxes", [=](u64 leaf_id) {
58 TgridVec min = imin;
59 TgridVec max = imax;
60
61 cell_looper.iter_object_in_cell(leaf_id + leaf_offset, [&](u32 block_id) {
62 TgridVec bmin = acc_bmin[block_id];
63 TgridVec bmax = acc_bmax[block_id];
64
65 min = sham::min(min, bmin);
66 max = sham::max(max, bmax);
67 });
68
69 comp_min[leaf_offset + leaf_id] = min;
70 comp_max[leaf_offset + leaf_id] = max;
71 });
72 });
73
74 buf_cell_min.complete_event_state(e);
75 buf_cell_max.complete_event_state(e);
76
77 auto ker_reduc_hmax = [&](sycl::handler &cgh) {
78 u32 offset_leaf = internal_cell_count;
79
80 sycl::accessor comp_min{tmp_min_cell, cgh, sycl::read_write};
81 sycl::accessor comp_max{tmp_max_cell, cgh, sycl::read_write};
82
83 sycl::accessor rchild_id{
84 shambase::get_check_ref(tree.tree_struct.buf_rchild_id), cgh, sycl::read_only};
85 sycl::accessor lchild_id{
86 shambase::get_check_ref(tree.tree_struct.buf_lchild_id), cgh, sycl::read_only};
87 sycl::accessor rchild_flag{
88 shambase::get_check_ref(tree.tree_struct.buf_rchild_flag), cgh, sycl::read_only};
89 sycl::accessor lchild_flag{
90 shambase::get_check_ref(tree.tree_struct.buf_lchild_flag), cgh, sycl::read_only};
91
92 shambase::parallel_for(cgh, internal_cell_count, "propagate up", [=](u64 gid) {
93 u32 lid = lchild_id[gid] + offset_leaf * lchild_flag[gid];
94 u32 rid = rchild_id[gid] + offset_leaf * rchild_flag[gid];
95
96 TgridVec bminl = comp_min[lid];
97 TgridVec bminr = comp_min[rid];
98 TgridVec bmaxl = comp_max[lid];
99 TgridVec bmaxr = comp_max[rid];
100
101 TgridVec bmin = sham::min(bminl, bminr);
102 TgridVec bmax = sham::max(bmaxl, bmaxr);
103
104 comp_min[gid] = bmin;
105 comp_max[gid] = bmax;
106 });
107 };
108
109 for (u32 i = 0; i < tree.tree_depth; i++) {
110 shamsys::instance::get_compute_queue().submit(ker_reduc_hmax);
111 }
112
113 sycl::buffer<TgridVec> &tree_bmin
114 = shambase::get_check_ref(tree.tree_cell_ranges.buf_pos_min_cell_flt);
115 sycl::buffer<TgridVec> &tree_bmax
116 = shambase::get_check_ref(tree.tree_cell_ranges.buf_pos_max_cell_flt);
117
118 shamsys::instance::get_compute_queue().submit([&](sycl::handler &cgh) {
119 shamrock::tree::ObjectIterator cell_looper(tree, cgh);
120
121 u32 leaf_offset = tree.tree_struct.internal_cell_count;
122
123 sycl::accessor comp_bmin{tmp_min_cell, cgh, sycl::read_only};
124 sycl::accessor comp_bmax{tmp_max_cell, cgh, sycl::read_only};
125
126 sycl::accessor tree_buf_min{tree_bmin, cgh, sycl::read_write};
127 sycl::accessor tree_buf_max{tree_bmax, cgh, sycl::read_write};
128
129 shambase::parallel_for(cgh, tot_count, "write in tree range", [=](u64 nid) {
130 TgridVec load_min = comp_bmin[nid];
131 TgridVec load_max = comp_bmax[nid];
132
133 // if(
134 // (!shambase::vec_equals(load_min,tree_buf_min[nid]))
135 // || !shambase::vec_equals(load_max,tree_buf_max[nid])
136 // )
137 //{
138 //
139 // sycl::ext::oneapi::experimental::printf(
140 // "%ld : (%ld %ld %ld) -> (%ld %ld %ld) & (%ld %ld %ld) -> (%ld %ld %ld)\n",
141 // nid,
142 // tree_buf_min[nid].x(),tree_buf_min[nid].y(),tree_buf_min[nid].z(),
143 // load_min.x(),load_min.y(),load_min.z(),
144 // tree_buf_max[nid].x(),tree_buf_max[nid].y(),tree_buf_max[nid].z(),
145 // load_max.x(),load_max.y(),load_max.z()
146 // );
147 //
148 //}
149
150 tree_buf_min[nid] = load_min;
151 tree_buf_max[nid] = load_max;
152 });
153 });
154 }
155} // namespace
156
158
159 template<class Umorton, class TgridVec>
161 auto edges = get_edges();
162
163 auto &block_min = edges.block_min;
164 auto &block_max = edges.block_max;
165
166 const shambase::DistributedData<u32> &indexes_dd = edges.sizes.indexes;
167
168 // TODO move the bounding box computation to another node.
169
171
172 bounds = indexes_dd.template map<shammath::AABB<TgridVec>>([&](u64 id, auto &merged) {
173 TgridVec min_bound = block_min.get_field(id).compute_min();
174 TgridVec max_bound = block_max.get_field(id).compute_max();
175
176 // logger::raw_ln("AABB", id, min_bound, max_bound);
177
178 return shammath::AABB<TgridVec>{min_bound, max_bound};
179 });
180
182 = indexes_dd.template map<RTree>([&](u64 id, auto &merged) {
183 shamlog_debug_ln("AMR", "compute tree for merged patch", id);
184
185 auto aabb = bounds.get(id);
186
187 TgridVec bmin = aabb.lower;
188 TgridVec bmax = aabb.upper;
189
190 TgridVec diff = bmax - bmin;
191 diff.x() = shambase::roundup_pow2(diff.x());
192 diff.y() = shambase::roundup_pow2(diff.y());
193 diff.z() = shambase::roundup_pow2(diff.z());
194 bmax = bmin + diff;
195
196 auto &field_pos = block_min.get_field(id);
197
198 RTree tree(
199 shamsys::instance::get_compute_scheduler_ptr(),
200 {bmin, bmax},
201 field_pos.get_buf(),
202 field_pos.get_obj_cnt(),
203 reduction_level);
204
205 return tree;
206 });
207
208 trees.for_each([](u64 id, RTree &tree) {
209 tree.compute_cell_ibounding_box(shamsys::instance::get_compute_queue());
210 });
211
212 trees.for_each([](u64 id, RTree &tree) {
213 tree.convert_bounding_box(shamsys::instance::get_compute_queue());
214 });
215
216 trees.for_each([&](u64 id, RTree &tree) {
217 __internal_correct_tree_bb(
218 tree, block_min.get_field(id).get_buf(), block_max.get_field(id).get_buf());
219 });
220
221 edges.trees.trees = std::move(trees);
222 }
223
224 template<class Umorton, class TgridVec>
226
227 std::string sizes = get_ro_edge_base(0).get_tex_symbol();
228 std::string block_min = get_ro_edge_base(1).get_tex_symbol();
229 std::string block_max = get_ro_edge_base(2).get_tex_symbol();
230 std::string trees = get_rw_edge_base(0).get_tex_symbol();
231
232 std::string tex = R"tex(
233 Build radix trees
234
235 \begin{align}
236 {trees}_{\rm patch} &= RadixTree(\{{block_min}_{\rm patch}\}_{\Omega_i}, \{{block_max}_{\rm patch}\}_{\Omega_i}) \\
237 {\Omega_i} &= [0, {sizes}_{\rm patch} )
238 \end{align}
239 )tex";
240
241 shambase::replace_all(tex, "{sizes}", sizes);
242 shambase::replace_all(tex, "{block_min}", block_min);
243 shambase::replace_all(tex, "{block_max}", block_max);
244 shambase::replace_all(tex, "{trees}", trees);
245
246 return tex;
247 }
248
249} // namespace shammodels::basegodunov::modules
250
sycl::queue & get_compute_queue(u32 id=0)
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
The radix tree.
Definition RadixTree.hpp:50
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
Represents a collection of objects distributed across patches identified by a u64 id.
void for_each(std::function< void(u64, T &)> &&f)
Applies a function to each object in the collection.
T & get(u64 id)
Returns a reference to an object in the collection.
virtual std::string _impl_get_tex() const
get the tex of the node
void replace_all(std::string &inout, std::string_view what, std::string_view with)
replace all occurence of a search string with another
Definition string.hpp:183
constexpr T roundup_pow2(T v) noexcept
round up to the next power of two Source : https://graphics.stanford.edu/~seander/bithacks....
Definition integer.hpp:92
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
namespace for the basegodunov model modules
Axis-Aligned bounding box.
Definition AABB.hpp:99