Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
SinkParticlesAccreteQuantities.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
16
23#include "shamcomm/logs.hpp"
27#include <shambackends/sycl.hpp>
28#include <string>
29
31
32 template<class Tvec>
34
36
37 auto edges = get_edges();
38
39 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
40 auto &q = shambase::get_check_ref(dev_sched).get_queue();
41
42 Tscal gpart_mass = edges.gpart_mass.data;
43 Tscal dt = edges.dt.data;
44
45 sham::DeviceBuffer<u32> acc_flag(0, dev_sched);
46
47 bool had_accretion = false;
48 std::string log = "sink accretion :";
49
50 auto &sink_positions = edges.sink_positions.data;
51 auto &sink_velocities = edges.sink_velocities.data;
52 auto &sink_accelerations = edges.sink_accelerations.data;
53 auto &sink_angmom = edges.sink_angmom.data;
54 auto &sink_mass = edges.sink_mass.data;
55
56 u32 sink_count = shambase::narrow_or_throw<u32>(sink_positions.size());
57 for (u32 i_sink = 0; i_sink < sink_count; i_sink++) {
58
59 Tvec r_sink = sink_positions[i_sink];
60 Tvec v_sink = sink_velocities[i_sink];
61
62 // compute the accreted mass, position moment and linear momentum
63 Tscal s_acc_mass = 0;
64 Tvec s_acc_mxyz = {0, 0, 0};
65 Tvec s_acc_pxyz = {0, 0, 0};
66 Tvec s_acc_maxyz = {0, 0, 0};
67 Tvec s_acc_lxyz = {0, 0, 0};
68
69 edges.part_counts.indexes.for_each([&](u64 id_patch, u32 Nobj) {
70 acc_flag.resize(Nobj);
71
72 auto &acc_table = edges.sink_accretion_table.get_spans().get(id_patch);
73
75 q,
76 sham::MultiRef{acc_table},
77 sham::MultiRef{acc_flag},
78 Nobj,
79 [i_sink](u32 id_a, const u32 *__restrict acc_table, u32 *__restrict acc_flag) {
80 acc_flag[id_a] = (acc_table[id_a] == i_sink) ? 1 : 0;
81 });
82
83 auto id_list_accrete = shamalgs::stream_compact(dev_sched, acc_flag, Nobj);
84
85 auto &pos_data = edges.positions.get_spans().get(id_patch);
86 auto &vel_data = edges.velocities.get_spans().get(id_patch);
87 auto &acc_data = edges.accelerations.get_spans().get(id_patch);
88
89 // sum accreted values onto sink
90 if (id_list_accrete.get_size() > 0) {
91 u32 Naccrete = shambase::narrow_or_throw<u32>(id_list_accrete.get_size());
92
93 Tscal acc_mass = gpart_mass * Naccrete;
94
95 sham::DeviceBuffer<Tvec> pxyz_acc(Naccrete, dev_sched);
96 sham::DeviceBuffer<Tvec> maxyz_acc(Naccrete, dev_sched);
97 sham::DeviceBuffer<Tvec> mxyz_acc(Naccrete, dev_sched);
98 sham::DeviceBuffer<Tvec> lxyz_acc(Naccrete, dev_sched);
99
101 q,
102 sham::MultiRef{pos_data, vel_data, acc_data, id_list_accrete},
103 sham::MultiRef{pxyz_acc, mxyz_acc, maxyz_acc, lxyz_acc},
104 Naccrete,
105 [r_sink, v_sink, gpart_mass, dt](
106 u32 id_a,
107 const Tvec *__restrict xyz,
108 const Tvec *__restrict vxyz,
109 const Tvec *__restrict axyz,
110 const u32 *__restrict id_acc,
111 Tvec *__restrict accretion_p,
112 Tvec *__restrict accretion_mr,
113 Tvec *__restrict accretion_ma,
114 Tvec *__restrict accretion_l) {
115 u32 i_a = id_acc[id_a];
116 Tvec r = xyz[i_a];
117 Tvec v = vxyz[i_a];
118 Tvec a = axyz[i_a];
119 accretion_p[id_a] = gpart_mass * v;
120 accretion_mr[id_a] = gpart_mass * r;
121 accretion_ma[id_a] = gpart_mass * a;
122
123 // dirty trick to account for the residual acceleration in the spin.
124 // This allows us to maitain a much better angular momentum
125 // conservation.
126 v += a * dt / 2;
127 accretion_l[id_a] = gpart_mass * sycl::cross(r - r_sink, v - v_sink);
128 });
129
130 Tvec acc_pxyz = shamalgs::primitives::sum(dev_sched, pxyz_acc, 0, Naccrete);
131 Tvec acc_mxyz = shamalgs::primitives::sum(dev_sched, mxyz_acc, 0, Naccrete);
132 Tvec acc_maxyz = shamalgs::primitives::sum(dev_sched, maxyz_acc, 0, Naccrete);
133 Tvec acc_lxyz = shamalgs::primitives::sum(dev_sched, lxyz_acc, 0, Naccrete);
134
135 s_acc_mass += acc_mass;
136 s_acc_pxyz += acc_pxyz;
137 s_acc_mxyz += acc_mxyz;
138 s_acc_maxyz += acc_maxyz;
139 s_acc_lxyz += acc_lxyz;
140 }
141 });
142
143 Tscal sum_acc_mass = shamalgs::collective::allreduce_sum(s_acc_mass);
144
145 // if there is accretion continue otherwise skip that part
146 if (sum_acc_mass <= 0) {
147 continue;
148 }
149
150 Tvec sum_acc_pxyz = shamalgs::collective::allreduce_sum(s_acc_pxyz);
151 Tvec sum_acc_mxyz = shamalgs::collective::allreduce_sum(s_acc_mxyz);
152 Tvec sum_acc_maxyz = shamalgs::collective::allreduce_sum(s_acc_maxyz);
153 Tvec sum_acc_lxyz = shamalgs::collective::allreduce_sum(s_acc_lxyz);
154
155 Tscal old_mass = sink_mass[i_sink];
156 Tvec old_pos = sink_positions[i_sink];
157 Tvec old_vel = sink_velocities[i_sink];
158 Tvec old_acc = sink_accelerations[i_sink];
159 Tvec old_ang = sink_angmom[i_sink];
160
161 // compute the new sink values
162 Tscal new_mass = old_mass + sum_acc_mass;
163 Tvec new_pos = (sum_acc_mxyz + old_pos * old_mass) / (old_mass + sum_acc_mass);
164 Tvec new_vel = (sum_acc_pxyz + old_vel * old_mass) / (old_mass + sum_acc_mass);
165 Tvec new_acc = (sum_acc_maxyz + old_acc * old_mass) / (old_mass + sum_acc_mass);
166 Tvec new_ang_mom = old_ang + sum_acc_lxyz
167 - new_mass * sycl::cross(new_pos - old_pos, new_vel - old_vel);
168
169 // write back the update sink state
170 sink_mass[i_sink] = new_mass;
171 sink_positions[i_sink] = new_pos;
172 sink_velocities[i_sink] = new_vel;
173 sink_angmom[i_sink] = new_ang_mom;
174 sink_accelerations[i_sink] = new_acc;
175
176 had_accretion = true;
177 log += sham::format(
178 "\n id {} deltas : mass={} r={} v={} l={}",
179 i_sink,
180 new_mass - old_mass,
181 new_pos - old_pos,
182 new_vel - old_vel,
183 new_ang_mom - old_ang);
184 }
185
186 if (shamcomm::world_rank() == 0 && had_accretion) {
187 logger::info_ln("sph::Sink", log);
188 }
189 }
190
191 template<class Tvec>
193 return "TODO";
194 }
195
196} // namespace shammodels::sph::modules
197
Header file describing a Node Instance.
Accrete flagged SPH particles onto sinks (mass, CoM, spin, etc.).
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 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.
virtual std::string _impl_get_tex() const
get the tex of the node
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.
std::tuple< std::optional< sycl::buffer< u32 > >, u32 > stream_compact(sycl::queue &q, sycl::buffer< u32 > &buf_flags, u32 len)
Stream compaction algorithm.
Definition numeric.cpp:84
T sum(const sham::DeviceScheduler_ptr &sched, const sham::DeviceBuffer< T > &buf1, u32 start_id, u32 end_id)
Compute the sum of elements in a device buffer within a specified range.
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:112
i32 world_rank()
Gives the rank of the current process in the MPI communicator.
Definition worldInfo.cpp:41
namespace for the sph model modules
Utilities for safe type narrowing conversions.
void info_ln(std::string module_name, Types... var2)
Prints a log message with multiple arguments followed by a newline.
Definition logs.hpp:132
#define __shamrock_stack_entry()
Macro to create a stack entry.
A class that references multiple buffers or similar objects.
Definition MultiRef.hpp:33
Functions related to the MPI communicator.