Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
TreeStructureWalker.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
18#include "TreeStructure.hpp"
19
20namespace shamrock::tree {
21
22 enum WalkPolicy { Recompute, Cache };
23
24 namespace details {
25 template<WalkPolicy policy, class u_morton, class InteractCrit>
27 } // namespace details
28
29 template<WalkPolicy policy, class u_morton, class InteractCrit>
31 public:
33
34 using AccessedWalker =
36
37 TreeStructureWalker(TreeStructure<u_morton> &str, u32 walker_count, InteractCrit &&crit)
38 : walker(str, walker_count, std::forward<InteractCrit>(crit)) {}
39
40 inline void generate() { walker.generate(); }
41
42 inline AccessedWalker get_access(sycl::handler &device_handle) {
43 return walker.get_access(device_handle);
44 }
45 };
46
47 template<WalkPolicy policy, class u_morton, class InteractCrit>
49 TreeStructure<u_morton> &str, u32 walker_count, InteractCrit &&crit) {
51 str, walker_count, std::forward<InteractCrit>(crit));
52 walk.generate();
53 return walk;
54 }
55
56} // namespace shamrock::tree
57
58namespace shamrock::tree::details {
59
60 template<class u_morton, class InteractCrit>
61 class TreeStructureWalkerPolicy<Recompute, u_morton, InteractCrit> {
62 public:
63 TreeStructure<u_morton> &tree_struct;
64 InteractCrit crit;
65 u32 walker_count;
66
67 class Accessed {
68
69 public:
70 using IntCritAcc = typename InteractCrit::Access;
71 using IntCritVals = typename IntCritAcc::ObjectValues;
72
73 private:
74 sycl::range<1> walkers_range;
75
76 u32 leaf_offset;
77
78 sycl::accessor<u32, 1, sycl::access::mode::read, sycl::target::device> rchild_id;
79 sycl::accessor<u32, 1, sycl::access::mode::read, sycl::target::device> lchild_id;
80 sycl::accessor<u8, 1, sycl::access::mode::read, sycl::target::device> rchild_flag;
81 sycl::accessor<u8, 1, sycl::access::mode::read, sycl::target::device> lchild_flag;
82
83 IntCritAcc criterion_acc;
84
85 static constexpr auto get_tree_depth = []() -> u32 {
86 if constexpr (std::is_same<u_morton, u32>::value) {
87 return 32;
88 }
89 if constexpr (std::is_same<u_morton, u64>::value) {
90 return 64;
91 }
92 return 0;
93 };
94
95 static constexpr u32 tree_depth = get_tree_depth();
96 static constexpr u32 _nindex = 4294967295;
97
98 bool one_cell_mode;
99
100 public:
101 Accessed(
102 TreeStructure<u_morton> &tree_struct,
103 u32 walker_count,
104 sycl::handler &device_handle,
105 InteractCrit crit)
106 : rchild_id{*tree_struct.buf_rchild_id, device_handle, sycl::read_only},
107 lchild_id{*tree_struct.buf_lchild_id, device_handle, sycl::read_only},
108 rchild_flag{*tree_struct.buf_rchild_flag, device_handle, sycl::read_only},
109 lchild_flag{*tree_struct.buf_lchild_flag, device_handle, sycl::read_only},
110 criterion_acc(crit, device_handle), walkers_range{walker_count},
111 leaf_offset(tree_struct.internal_cell_count),
112 one_cell_mode(tree_struct.one_cell_mode) {}
113
114 inline sycl::range<1> get_sycl_range() { return walkers_range; }
115
116 inline IntCritAcc criterion() const { return criterion_acc; }
117
118 template<class FuncNodeFound, class FuncNodeReject>
119 inline void for_each_node(
120 sycl::item<1> id,
121 IntCritVals int_values,
122 FuncNodeFound &&found_case,
123 FuncNodeReject &&reject_case) const;
124 };
125
126 inline void generate() {}
127
129 TreeStructure<u_morton> &str, u32 walker_count, InteractCrit &&crit)
130 : tree_struct(str), walker_count(walker_count), crit(crit) {}
131
132 inline Accessed get_access(sycl::handler &device_handle) {
133 return Accessed(tree_struct, walker_count, device_handle, crit);
134 }
135 };
136} // namespace shamrock::tree::details
137
138template<class u_morton, class InteractCrit>
139template<class FuncNodeFound, class FuncNodeReject>
140inline void shamrock::tree::details::
141 TreeStructureWalkerPolicy<shamrock::tree::Recompute, u_morton, InteractCrit>::Accessed::
142 for_each_node(
143 sycl::item<1> id,
144 IntCritVals int_values,
145 FuncNodeFound &&found_case,
146 FuncNodeReject &&reject_case) const {
147
148 u32 stack_cursor = tree_depth - 1;
149 std::array<u32, tree_depth> id_stack;
150
151 // Should be unrequired considering the change made to the tree building
152 // if (one_cell_mode) {
153 //
154 // bool valid_root = InteractCrit::criterion(0, criterion_tree_f_acc, int_values);
155 //
156 // if (valid_root) {
157 // found_case(leaf_offset, 0);
158 // } else {
159 // reject_case(0);
160 // }
161 //
162 // return;
163 // }
164
165 id_stack[stack_cursor] = 0;
166
167 while (stack_cursor < tree_depth) {
168
169 u32 current_node_id = id_stack[stack_cursor];
170 id_stack[stack_cursor] = _nindex;
171 stack_cursor++;
172
173 bool cur_id_valid = InteractCrit::criterion(current_node_id, criterion_acc, int_values);
174
175 if (cur_id_valid) {
176
177 // leaf and cell can interact
178 if (current_node_id >= leaf_offset) {
179
180 found_case(current_node_id, current_node_id - leaf_offset);
181
182 // can interact not leaf => stack
183 } else {
184
185 u32 lid = lchild_id[current_node_id] + leaf_offset * lchild_flag[current_node_id];
186 u32 rid = rchild_id[current_node_id] + leaf_offset * rchild_flag[current_node_id];
187
188 id_stack[stack_cursor - 1] = rid;
189 stack_cursor--;
190
191 id_stack[stack_cursor - 1] = lid;
192 stack_cursor--;
193 }
194 } else {
195 // grav
196 reject_case(current_node_id);
197 }
198 }
199}
std::uint32_t u32
32 bit unsigned integer
Namespace for internal details of the logs module.