Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
SGMMPlummer.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
19#include "shamcomm/logs.hpp"
20#include "shammath/AABB.hpp"
29
31
32 template<class Tvec, u32 mm_order>
35
36 using Umorton = u32;
38
39 auto edges = get_edges();
40
41 edges.field_axyz_ext.ensure_sizes(edges.sizes.indexes);
42
43 if (edges.sizes.indexes.get_ids().size() != 1) {
45 "Self gravity MM mode only supports one patch so far, current number "
46 "of patches is : "
47 + std::to_string(edges.sizes.indexes.get_ids().size()));
48 }
49
50 Tscal G = edges.constant_G.data;
51 Tscal gpart_mass = edges.gpart_mass.data;
52
53 Tscal gravitational_softening = epsilon * epsilon;
54
55 using MassMoments = shammath::SymTensorCollection<Tscal, 0, mm_order - 1>;
56 static constexpr u32 mass_moment_terms = MassMoments::num_component;
57
58 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
59 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
60
61 edges.sizes.indexes
62 .for_each(
63 [&](u64 id, const u64 &n) {
64 PatchDataField<Tvec> &xyz = edges.field_xyz.get_field(id);
65 PatchDataField<Tvec> &axyz_ext = edges.field_axyz_ext.get_field(id);
66
67 Tvec bmax = xyz.compute_max();
68 Tvec bmin = xyz.compute_min();
69 shammath::AABB<Tvec> aabb(bmin, bmax);
70
71 // build the tree
72 auto bvh = RTree::make_empty(dev_sched);
73 bvh.rebuild_from_positions(
74 xyz.get_buf(), xyz.get_obj_cnt(), aabb, reduction_level);
75
76 // compute moments in leaves
77 auto mass_moments_tree = compute_tree_mass_moments<Tvec, Umorton, mm_order - 1>(
78 bvh, xyz.get_buf(), gpart_mass);
79
80 // compute the force on the particles
81 auto obj_it = bvh.get_object_iterator();
83 q,
84 sham::MultiRef{xyz.get_buf(), obj_it, mass_moments_tree.buf_field},
85 sham::MultiRef{axyz_ext.get_buf()},
86 n,
87 [theta_crit = theta_crit, gravitational_softening, gpart_mass, G](
88 u32 i,
89 const Tvec *xyz,
90 auto particle_looper,
91 const Tscal *mass_moments_scal,
92 Tvec *axyz_ext) {
93 Tvec xyz_i = xyz[i];
94
95 Tvec f_i{0.0f};
96
97 auto &tree_traverser = particle_looper.tree_traverser;
98 auto &cell_iterator = particle_looper.cell_iterator;
99
100 tree_traverser
101 .traverse_tree_base(
102 [&](u32 node_id) -> bool {
103 // mac
104
106 tree_traverser.aabb_min[node_id],
107 tree_traverser.aabb_max[node_id]};
108
109 Tvec s_B = node_aabb.get_center();
110
111 Tvec delta_B = node_aabb.delt();
112
113 Tscal sz_B = sham::max_component(delta_B) / 2;
114
115 Tvec r = s_B - xyz_i;
116 Tscal r_sq = r.x() * r.x() + r.y() * r.y() + r.z() * r.z();
117
118 Tscal theta = (r_sq == 0) ? theta_crit * 2
119 : sz_B * sycl::rsqrt(r_sq);
120
121 return theta > theta_crit;
122 },
123 [&](u32 node_id) { // p2p case
124 u32 leaf_id
125 = node_id - tree_traverser.tree_traverser.offset_leaf;
126 cell_iterator.for_each_in_leaf_cell(leaf_id, [&](u32 j) {
127 Tvec R = xyz[j] - xyz_i;
128 const Tscal r_inv = sycl::rsqrt(
129 R.x() * R.x() + R.y() * R.y() + R.z() * R.z()
130 + gravitational_softening);
131 f_i += gpart_mass * r_inv * r_inv * r_inv * R;
132 });
133 },
134 [&](u32 node_id) {
135 // multipole case
136 Tvec s_B = shammath::AABB<Tvec>{tree_traverser.aabb_min[node_id], tree_traverser.aabb_max[node_id]}.get_center();
137
138 Tvec r_fmm = s_B - xyz_i;
139
140 MassMoments Q_n_B = MassMoments::load(
141 mass_moments_scal
142 + node_id * MassMoments::num_component,
143 0);
144 auto D_n
146 get_der_tensors(r_fmm);
147
148 f_i -= shamphys::
149 contract_grav_moment_to_force<Tscal, mm_order>(
150 Q_n_B, D_n);
151 });
152
153 axyz_ext[i] += f_i * G;
154 });
155 });
156 }
157} // namespace shammodels::sph::modules
158
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
A SYCL queue associated with a device and a context.
DeviceQueue & get_queue(u32 id=0)
Get a reference to a DeviceQueue.
void _impl_evaluate_internal() override
evaluate the node
Utility to get the derivatives of the Green function for gravity in Cartesian coordinates.
A Compressed Leaf Bounding Volume Hierarchy (CLBVH) for neighborhood queries.
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.
void throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.
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 delt() const
Returns the delta of the AABB.
Definition AABB.hpp:152
T get_center() const noexcept
Returns the center of the AABB.
Definition AABB.hpp:174