Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
compute_tree_mass_moments.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 "shammath/AABB.hpp"
23
25
26 template<class Tvec, class Umorton, u32 moment_order>
28 compute_tree_mass_moments(
30 const sham::DeviceBuffer<Tvec> &xyz,
31 shambase::VecComponent<Tvec> gpart_mass) {
32
34
35 using Tscal = shambase::VecComponent<Tvec>;
37 static constexpr u32 mass_moment_terms = MassMoments::num_component;
38
39 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
40 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
41
42 // compute moments in leaves
43 auto mass_moments_tree = shamtree::prepare_karras_radix_tree_field_multi_var<Tscal>(
44 bvh.structure,
45 shamtree::new_empty_karras_radix_tree_field_multi_var<Tscal>(mass_moment_terms));
46
47 // fill the leaves with the mass moments
48 auto cell_it = bvh.reduced_morton_set.get_leaf_cell_iterator();
49 auto fill_leafs
50 = [&](shamtree::KarrasRadixTreeFieldMultiVar<Tscal> &tree_field, u32 leaf_offset) {
52 q,
53 sham::MultiRef{xyz, cell_it, bvh.aabbs.buf_aabb_min, bvh.aabbs.buf_aabb_max},
54 sham::MultiRef{tree_field.buf_field},
56 [leaf_offset, gpart_mass](
57 u32 i,
58 const Tvec *xyz,
59 auto cell_iter,
60 const Tvec *aabb_min,
61 const Tvec *aabb_max,
62 Tscal *mass_moments_scal) {
63 // Init with the min value of the type
64 MassMoments Q_n_B = MassMoments::zeros();
65
66 u32 cell_id = i + leaf_offset;
67 shammath::AABB<Tvec> cell_aabb
68 = shammath::AABB<Tvec>{aabb_min[cell_id], aabb_max[cell_id]};
69
70 Tvec s_B = cell_aabb.get_center();
71
72 cell_iter.for_each_in_leaf_cell(i, [&](u32 j) {
73 Q_n_B += MassMoments::from_vec(xyz[j] - s_B);
74 });
75
76 Q_n_B *= gpart_mass;
77
78 Tscal *ptr_store
79 = mass_moments_scal + (i + leaf_offset) * MassMoments::num_component;
80 Q_n_B.store(ptr_store, 0);
81 });
82 };
83
84 fill_leafs(mass_moments_tree, bvh.structure.get_internal_cell_count());
85
86 // propagate the moments upward
87 u32 int_cell_count = bvh.structure.get_internal_cell_count();
88
89 if (int_cell_count == 0) {
90 return mass_moments_tree;
91 }
92
93 auto step = [&]() {
94 auto traverser = bvh.structure.get_structure_traverser();
95
97 q,
98 sham::MultiRef{traverser, bvh.aabbs.buf_aabb_min, bvh.aabbs.buf_aabb_max},
99 sham::MultiRef{mass_moments_tree.buf_field},
100 int_cell_count,
101 [=](u32 gid,
102 auto tree_traverser,
103 const Tvec *aabb_min,
104 const Tvec *aabb_max,
105 Tscal *__restrict moments) {
106 u32 left_child = tree_traverser.get_left_child(gid);
107 u32 right_child = tree_traverser.get_right_child(gid);
108
109 Tscal *ptr_left = moments + left_child * MassMoments::num_component;
110 Tscal *ptr_right = moments + right_child * MassMoments::num_component;
111
112 Tvec left_center
113 = shammath::AABB<Tvec>{aabb_min[left_child], aabb_max[left_child]}
114 .get_center();
115 Tvec right_center
116 = shammath::AABB<Tvec>{aabb_min[right_child], aabb_max[right_child]}
117 .get_center();
118 Tvec new_center
119 = shammath::AABB<Tvec>{aabb_min[gid], aabb_max[gid]}.get_center();
120
121 MassMoments Q_n_B_left = MassMoments::load(ptr_left, 0);
122 MassMoments Q_n_B_right = MassMoments::load(ptr_right, 0);
123
124 // offset the moments and add them
125 MassMoments Q_n_B_combined = MassMoments::zeros();
126 Q_n_B_combined
127 += shamphys::offset_multipole(Q_n_B_left, left_center, new_center);
128 Q_n_B_combined
129 += shamphys::offset_multipole(Q_n_B_right, right_center, new_center);
130
131 Tscal *ptr_store = moments + gid * MassMoments::num_component;
132 Q_n_B_combined.store(ptr_store, 0);
133 });
134 };
135
136 for (u32 i = 0; i < bvh.structure.tree_depth; i++) {
137 step();
138 }
139
140 return mass_moments_tree;
141 }
142} // namespace shammodels::sph::modules
constexpr const char * xyz
Position field (3D coordinates)
std::uint32_t u32
32 bit unsigned integer
A buffer allocated in USM (Unified Shared Memory)
A SYCL queue associated with a device and a context.
DeviceQueue & get_queue(u32 id=0)
Get a reference to a DeviceQueue.
A Compressed Leaf Bounding Volume Hierarchy (CLBVH) for neighborhood queries.
KarrasRadixTreeAABB< Tvec > aabbs
The bounding box of the tree cells.
MortonReducedSet< Tmorton, Tvec, dim > reduced_morton_set
The reduced set of Morton codes.
KarrasRadixTree structure
The tree structure.
A data structure representing a field with multiple variables per cell for a Karras Radix Tree.
sham::DeviceBuffer< T > buf_field
field data (size = total_cell_count * nvar)
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.
namespace for the sph model modules
#define __shamrock_stack_entry()
Macro to create a stack entry.
A class that references multiple buffers or similar objects.
Axis-Aligned bounding box.
Definition AABB.hpp:99
T get_center() const noexcept
Returns the center of the AABB.
Definition AABB.hpp:174