Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
integrators.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
20#include <algorithm>
21
22namespace integ = shamrock::integrators;
23namespace util = shamrock::utilities;
24
28
29template<class flt, class T>
31 sham::DeviceQueue &queue,
32 sham::DeviceBuffer<T> &buf_val,
33 sham::DeviceBuffer<T> &buf_der,
34 sycl::range<1> elem_range,
35 flt dt) {
36
37 sham::EventList depends_list;
38
39 auto acc_u = buf_val.get_write_access(depends_list);
40 auto acc_du = buf_der.get_read_access(depends_list);
41
42 auto e = queue.submit(depends_list, [&](sycl::handler &cgh) {
43 cgh.parallel_for(elem_range, [=](sycl::item<1> item) {
44 u32 gid = (u32) item.get_id();
45 acc_u[item] = acc_u[item] + (dt) *acc_du[item];
46 });
47 });
48
49 buf_val.complete_event_state(e);
50 buf_der.complete_event_state(e);
51}
52
53#ifndef DOXYGEN
54template void integ::forward_euler(
55 sham::DeviceQueue &queue,
58 sycl::range<1> elem_range,
59 f32 dt);
60
61template void integ::forward_euler(
62 sham::DeviceQueue &queue,
65 sycl::range<1> elem_range,
66 f32 dt);
67
68template void integ::forward_euler(
69 sham::DeviceQueue &queue,
72 sycl::range<1> elem_range,
73 f64 dt);
74
75template void integ::forward_euler(
76 sham::DeviceQueue &queue,
79 sycl::range<1> elem_range,
80 f64 dt);
81#endif
85
86template<class flt, class T>
88 sham::DeviceQueue &queue,
89 sham::DeviceBuffer<T> &buf_val,
90 sham::DeviceBuffer<T> &buf_der,
91 sham::DeviceBuffer<T> &buf_der_old,
92 sham::DeviceBuffer<flt> &buf_eps_sq,
93 sycl::range<1> elem_range,
94 flt hdt) {
95
96 sham::EventList depends_list;
97
98 auto acc_u = buf_val.get_write_access(depends_list);
99 auto acc_du = buf_der.get_read_access(depends_list);
100 auto acc_du_old = buf_der_old.get_read_access(depends_list);
101 auto acc_epsilon_sq = buf_eps_sq.get_write_access(depends_list);
102
103 auto e = queue.submit(depends_list, [&](sycl::handler &cgh) {
104 cgh.parallel_for(elem_range, [=](sycl::item<1> item) {
105 u32 gid = (u32) item.get_id();
106
107 T incr = (hdt) * (acc_du[item] - acc_du_old[item]);
108
109 acc_u[item] = acc_u[item] + incr;
110 acc_epsilon_sq[item] = sycl::dot(incr, incr);
111 });
112 });
113
114 buf_val.complete_event_state(e);
115 buf_der.complete_event_state(e);
116 buf_der_old.complete_event_state(e);
117 buf_eps_sq.complete_event_state(e);
118}
119
120#ifndef DOXYGEN
121template void integ::leapfrog_corrector(
122 sham::DeviceQueue &queue,
125 sham::DeviceBuffer<f32_3> &buf_der_old,
126 sham::DeviceBuffer<f32> &buf_eps_sq,
127 sycl::range<1> elem_range,
128 f32 hdt);
129
130template void integ::leapfrog_corrector(
131 sham::DeviceQueue &queue,
134 sham::DeviceBuffer<f32> &buf_der_old,
135 sham::DeviceBuffer<f32> &buf_eps_sq,
136 sycl::range<1> elem_range,
137 f32 hdt);
138
139template void integ::leapfrog_corrector(
140 sham::DeviceQueue &queue,
143 sham::DeviceBuffer<f64_3> &buf_der_old,
144 sham::DeviceBuffer<f64> &buf_eps_sq,
145 sycl::range<1> elem_range,
146 f64 hdt);
147
148template void integ::leapfrog_corrector(
149 sham::DeviceQueue &queue,
152 sham::DeviceBuffer<f64> &buf_der_old,
153 sham::DeviceBuffer<f64> &buf_eps_sq,
154 sycl::range<1> elem_range,
155 f64 hdt);
156#endif
160
161template<class T>
163 sham::DeviceQueue &queue,
164 sham::DeviceBuffer<T> &buf_xyz,
165 sycl::range<1> elem_range,
166 std::pair<T, T> box) {
167
168 sham::EventList depends_list;
169 auto xyz = buf_xyz.get_write_access(depends_list);
170
171 auto e = queue.submit(depends_list, [&](sycl::handler &cgh) {
172 T box_min = std::get<0>(box);
173 T box_max = std::get<1>(box);
174 T delt = box_max - box_min;
175
176 cgh.parallel_for(elem_range, [=](sycl::item<1> item) {
177 u32 gid = (u32) item.get_id();
178
179 T r = xyz[gid] - box_min;
180
181 r = sycl::fmod(r, delt);
182 r += delt;
183 r = sycl::fmod(r, delt);
184 r += box_min;
185
186 xyz[gid] = r;
187 });
188 });
189
190 buf_xyz.complete_event_state(e);
191}
192
193#ifndef DOXYGEN
194template void util::sycl_position_modulo(
195 sham::DeviceQueue &queue,
197 sycl::range<1> elem_range,
198 std::pair<f32_3, f32_3> box);
199
200template void util::sycl_position_modulo(
201 sham::DeviceQueue &queue,
203 sycl::range<1> elem_range,
204 std::pair<f64_3, f64_3> box);
205#endif
209
210template<class T>
212 sham::DeviceQueue &queue,
213 sham::DeviceBuffer<T> &buf_xyz,
214 sham::DeviceBuffer<T> &buf_vxyz,
215 sycl::range<1> elem_range,
216 std::pair<T, T> box,
217 i32_3 shear_base,
218 i32_3 shear_dir,
219 shambase::VecComponent<T> shear_value,
220 shambase::VecComponent<T> shear_speed) {
221
222 sham::EventList depends_list;
223 auto xyz = buf_xyz.get_write_access(depends_list);
224 auto vxyz = buf_vxyz.get_write_access(depends_list);
225
226 auto e
227 = queue.submit(depends_list, [&, shear_base, shear_value, shear_speed](sycl::handler &cgh) {
228 T box_min = std::get<0>(box);
229 T box_max = std::get<1>(box);
230 T delt = box_max - box_min;
231
232 cgh.parallel_for(elem_range, [=](sycl::item<1> item) {
233 u32 gid = (u32) item.get_id();
234
235 T r = xyz[gid] - box_min;
236
237 T roff = r / delt;
238
239 // T dn = sycl::trunc(roff);
240
241 // auto d = sycl::dot(dn,shear_base.convert<shambase::VecComponent<T>>());
242
243 //*
244 auto cnt_per = [](shambase::VecComponent<T> v) -> int {
245 return (v >= 0) ? int(v) : (int(v) - 1);
246 };
247
248 i32 xoff = cnt_per(roff.x());
249 i32 yoff = cnt_per(roff.y());
250 i32 zoff = cnt_per(roff.z());
251
252 i32 dx = xoff * shear_base.x();
253 i32 dy = yoff * shear_base.y();
254 i32 dz = zoff * shear_base.z();
255
256 i32 d = dx + dy + dz;
257 //*/
258
259 T shift
260 = {(d * shear_dir.x()) * shear_value,
261 (d * shear_dir.y()) * shear_value,
262 (d * shear_dir.z()) * shear_value};
263
264 T shift_speed
265 = {(d * shear_dir.x()) * shear_speed,
266 (d * shear_dir.y()) * shear_speed,
267 (d * shear_dir.z()) * shear_speed};
268
269 vxyz[gid] -= shift_speed;
270 r -= shift;
271
272 r = sycl::fmod(r, delt);
273 r += delt;
274 r = sycl::fmod(r, delt);
275 r += box_min;
276
277 xyz[gid] = r;
278 });
279 });
280
281 buf_xyz.complete_event_state(e);
282 buf_vxyz.complete_event_state(e);
283}
284
285#ifndef DOXYGEN
286template void util::sycl_position_sheared_modulo(
287 sham::DeviceQueue &queue,
290 sycl::range<1> elem_range,
291 std::pair<f32_3, f32_3> box,
292 i32_3 shear_base,
293 i32_3 shear_dir,
294 f32 shear_value,
295 f32 shear_speed);
296
297template void util::sycl_position_sheared_modulo(
298 sham::DeviceQueue &queue,
301 sycl::range<1> elem_range,
302 std::pair<f64_3, f64_3> box,
303 i32_3 shear_base,
304 i32_3 shear_dir,
305 f64 shear_value,
306 f64 shear_speed);
307#endif
311
312template<class T>
315
316 sham::EventList depends_list;
317 auto acc1 = b1.get_write_access(depends_list);
318 auto acc2 = b2.get_write_access(depends_list);
319
320 auto e = queue.submit(depends_list, [&](sycl::handler &cgh) {
321 cgh.parallel_for(sycl::range<1>{cnt}, [=](sycl::item<1> item) {
322 T v1 = acc1[item];
323 T v2 = acc2[item];
324
325 acc1[item] = v2;
326 acc2[item] = v1;
327 });
328 });
329
332}
333
334#ifndef DOXYGEN
335template void util::swap_fields(
336 sham::DeviceQueue &queue,
339 u32 cnt);
340
341template void util::swap_fields(
343
344template void util::swap_fields(
345 sham::DeviceQueue &queue,
348 u32 cnt);
349
350template void util::swap_fields(
352#endif
double f64
Alias for double.
float f32
Alias for float.
std::uint32_t u32
32 bit unsigned integer
std::int32_t i32
32 bit integer
A buffer allocated in USM (Unified Shared Memory)
void complete_event_state(sycl::event e) const
Complete the event state of the buffer.
T * get_write_access(sham::EventList &depends_list, SourceLocation src_loc=SourceLocation{})
Get a read-write pointer to the buffer's data.
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.
Class to manage a list of SYCL events.
Definition EventList.hpp:31
This header file contains utility functions related to exception handling in the code.
void forward_euler(sham::DeviceQueue &queue, sham::DeviceBuffer< T > &buf_val, sham::DeviceBuffer< T > &buf_der, sycl::range< 1 > elem_range, flt dt)
Perform forward Euler integration step.
void sycl_position_sheared_modulo(sham::DeviceQueue &queue, sham::DeviceBuffer< T > &buf_xyz, sham::DeviceBuffer< T > &buf_vxyz, sycl::range< 1 > elem_range, std::pair< T, T > box, i32_3 shear_base, i32_3 shear_dir, shambase::VecComponent< T > shear_value, shambase::VecComponent< T > shear_speed)
Apply periodic boundary conditions with shearing.
void sycl_position_modulo(sham::DeviceQueue &queue, sham::DeviceBuffer< T > &buf_xyz, sycl::range< 1 > elem_range, std::pair< T, T > box)
Apply periodic boundary conditions to positions.
void leapfrog_corrector(sham::DeviceQueue &queue, sham::DeviceBuffer< T > &buf_val, sham::DeviceBuffer< T > &buf_der, sham::DeviceBuffer< T > &buf_der_old, sham::DeviceBuffer< flt > &buf_eps_sq, sycl::range< 1 > elem_range, flt hdt)
Perform leapfrog corrector step with adaptive softening.
void swap_fields(sham::DeviceQueue &queue, sham::DeviceBuffer< T > &b1, sham::DeviceBuffer< T > &b2, u32 cnt)
Swap contents of two buffers.