Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
BasicSPHGhosts.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
21#include "shambackends/vec.hpp"
34#include <utility>
35#include <variant>
36
37namespace shammodels::sph {
38
39 template<class vec>
41
42 using Tscal = shambase::VecComponent<vec>;
43
44 struct Free {};
45 struct Periodic {};
47 i32_3 shear_base;
48 i32_3 shear_dir;
49 Tscal shear_value;
50 Tscal shear_speed;
51 };
52
53 using Variant = std::variant<Free, Periodic, ShearingPeriodic>;
54 };
55
56 template<class vec>
58
60 using Config = typename CfgClass::Variant;
61
62 PatchScheduler &sched;
63 Config ghost_config;
64
65 public:
66 using flt = shambase::VecComponent<vec>;
68 using per_index = sycl::vec<i32, dim>;
69
71 vec offset;
72 vec offset_speed;
73 per_index periodicity_index;
75 flt volume_ratio;
76 };
77
79 InterfaceBuildInfos build_infos;
80 sham::DeviceBuffer<u32> ids_interf;
81 f64 part_cnt_ratio;
82 };
83
85
86 std::shared_ptr<shamrock::patch::PatchDataLayerLayout> &xyzh_ghost_layout;
87
88 std::shared_ptr<shamrock::solvergraph::RankGetter> patch_rank_owner;
89
91 PatchScheduler &sched,
92 Config ghost_config,
93 std::shared_ptr<shamrock::solvergraph::RankGetter> patch_rank_owner,
94 std::shared_ptr<shamrock::patch::PatchDataLayerLayout> &xyzh_ghost_layout)
95 : sched(sched), ghost_config(ghost_config),
96 patch_rank_owner(std::move(patch_rank_owner)), xyzh_ghost_layout(xyzh_ghost_layout) {}
97
106 GeneratorMap find_interfaces(
107 SerialPatchTree<vec> &sptree,
108 shamrock::patch::PatchtreeField<flt> &int_range_max_tree,
109 shamrock::patch::PatchField<flt> &int_range_max);
110
118 GeneratorMap &&gen);
119
120 void gen_debug_patch_ghost(shambase::DistributedDataShared<InterfaceIdTable> &interf_info);
121
123
133 SerialPatchTree<vec> &sptree,
134 shamrock::patch::PatchtreeField<flt> &int_range_max_tree,
135 shamrock::patch::PatchField<flt> &int_range_max) {
136 StackEntry stack_loc{};
137
139 find_interfaces(sptree, int_range_max_tree, int_range_max));
140 }
141
158 template<class T>
161 std::function<T(u64, u64, InterfaceBuildInfos, sham::DeviceBuffer<u32> &, u32)> fct) {
162 StackEntry stack_loc{};
163
164 // clang-format off
165 return builder.template map<T>([&](u64 sender, u64 receiver, InterfaceIdTable &build_table) {
166 if (build_table.ids_interf.get_size() == 0) {
167 throw shambase::make_except_with_loc<std::runtime_error>(
168 "their is an empty id table in the interface, it should have been removed");
169 }
170
171 return fct(
172 sender,
173 receiver,
174 build_table.build_infos,
175 build_table.ids_interf,
176 build_table.ids_interf.get_size());
177
178 });
179 // clang-format on
180 }
181
182 template<class T>
183 void modify_interface_native(
186 std::function<void(u64, u64, InterfaceBuildInfos, sham::DeviceBuffer<u32> &, u32, T &)>
187 fct) {
188 StackEntry stack_loc{};
189
190 struct Args {
191 u64 sender;
192 u64 receiver;
193 InterfaceIdTable &build_table;
194 };
195
196 std::vector<Args> vecarg;
197
198 // clang-format off
199 builder.for_each([&](u64 sender, u64 receiver, InterfaceIdTable &build_table) {
200 if (build_table.ids_interf.get_size() == 0) {
201 throw shambase::make_except_with_loc<std::runtime_error>(
202 "their is an empty id table in the interface, it should have been removed");
203 }
204
205 vecarg.push_back({sender,receiver,build_table});
206 });
207 // clang-format on
208
209 u32 i = 0;
210 mod.for_each([&](u64 sender, u64 receiver, T &ref) {
211 InterfaceIdTable &build_table = vecarg[i].build_table;
212
213 fct(sender,
214 receiver,
215 build_table.build_infos,
216 build_table.ids_interf,
217 build_table.ids_interf.get_size(),
218 ref);
219
220 i++;
221 });
222 }
223
236 template<class T>
239 std::function<T(u64, u64, InterfaceBuildInfos, sycl::buffer<u32> &, u32)> gen_1,
240 std::function<void(u64, u64, InterfaceBuildInfos, sycl::buffer<u32> &, u32, T &)>
241 modif) {
242
243 StackEntry stack_loc{};
244
245 struct Args {
246 u64 sender;
247 u64 receiver;
248 InterfaceIdTable &build_table;
249 };
250
251 std::vector<Args> vecarg;
252
253 shambase::DistributedDataShared<T> ret = builder.template map<
254 T>([&](u64 sender, u64 receiver, InterfaceIdTable &build_table) {
255 if (!bool(build_table.ids_interf)) {
257 "their is an empty id table in the interface, it should have been removed");
258 }
259
260 vecarg.push_back({sender, receiver, build_table});
261
262 return gen_1(
263 sender,
264 receiver,
265 build_table.build_infos,
266 *build_table.ids_interf,
267 build_table.ids_interf->size());
268 });
269
270 u32 i = 0;
271 ret.for_each([&](u64 sender, u64 receiver, T &ref) {
272 InterfaceIdTable &build_table = vecarg[i].build_table;
273
274 modif(
275 sender,
276 receiver,
277 build_table.build_infos,
278 *build_table.ids_interf,
279 build_table.ids_interf->size(),
280 ref);
281
282 i++;
283 });
284
285 return ret;
286 }
287
289 // interface generation/communication utility //////////////////////////////////////////////
291
293 build_position_interf_field(shambase::DistributedDataShared<InterfaceIdTable> &builder) {
294 StackEntry stack_loc{};
295
296 const u32 ihpart = sched.pdl_old().template get_field_idx<flt>("hpart");
297
298 return build_interface_native<shamrock::patch::PatchDataLayer>(
299 builder,
300 [&](u64 sender,
301 u64 /*receiver*/,
302 InterfaceBuildInfos binfo,
304 u32 cnt) {
305 using namespace shamrock::patch;
306
307 PatchDataLayer &sender_pdat = sched.patch_data.get_pdat(sender);
308
309 shamrock::patch::PatchDataLayer ret(xyzh_ghost_layout);
310
311 sender_pdat.get_field<vec>(0).append_subset_to(
312 buf_idx, cnt, ret.get_field<vec>(0));
313 sender_pdat.get_field<flt>(ihpart).append_subset_to(
314 buf_idx, cnt, ret.get_field<flt>(1));
315
316 ret.get_field<vec>(0).apply_offset(binfo.offset);
317
318 return ret;
319 });
320 }
321
323 const std::shared_ptr<shamrock::patch::PatchDataLayerLayout> &pdl_ptr,
325 std::shared_ptr<shamrock::solvergraph::ExchangeGhostLayer> exchange_gz_node,
326 bool show_debug_infos) {
327 StackEntry stack_loc{};
328
329 // ----------------------------------------------------------------------------------------
330 // temporary wrapper to slowly migrate to the new solvergraph
331 std::shared_ptr<shamrock::solvergraph::PatchDataLayerDDShared> exchange_gz_edge
332 = std::make_shared<shamrock::solvergraph::PatchDataLayerDDShared>("", "");
333
334 exchange_gz_edge->patchdatas
335 = std::forward<shambase::DistributedDataShared<shamrock::patch::PatchDataLayer>>(
336 interf);
337
338 if (show_debug_infos) {
339 std::shared_ptr<shamrock::solvergraph::ScalarsEdge<u64>> object_counts
340 = std::make_shared<shamrock::solvergraph::ScalarsEdge<u64>>(
341 "object_counts", "object_counts");
342 sched.for_each_patchdata_nonempty(
344 object_counts->values.add_obj(p.id_patch, pdat.get_obj_cnt());
345 });
346 auto exchange_gz_node_debug
347 = std::make_shared<shamrock::solvergraph::ExchangeGhostLayerDebugDotGraph>();
348 exchange_gz_node_debug->set_edges(object_counts, exchange_gz_edge);
349 exchange_gz_node_debug->evaluate();
350 }
351
352 exchange_gz_node->set_edges(this->patch_rank_owner, exchange_gz_edge);
353
354 exchange_gz_node->evaluate();
355
356 // ----------------------------------------------------------------------------------------
357
359
360#if false
361 shamalgs::collective::serialize_sparse_comm<shamrock::patch::PatchDataLayer>(
362 shamsys::instance::get_compute_scheduler_ptr(),
364 interf),
365 recv_dat,
366 [&](u64 id) {
367 return sched.get_patch_rank_owner(id);
368 },
370 shamalgs::SerializeHelper ser(shamsys::instance::get_compute_scheduler_ptr());
371 ser.allocate(pdat.serialize_buf_byte_size());
372 pdat.serialize_buf(ser);
373 return ser.finalize();
374 },
375 [&](sham::DeviceBuffer<u8> &&buf) {
376 // exchange the buffer held by the distrib data and give it to the serializer
378 shamsys::instance::get_compute_scheduler_ptr(),
379 std::forward<sham::DeviceBuffer<u8>>(buf));
380 return shamrock::patch::PatchDataLayer::deserialize_buf(ser, pdl_ptr);
381 });
382#else
383 recv_dat = std::move(exchange_gz_edge->patchdatas);
384#endif
385
386 return recv_dat;
387 }
388
389 template<class T>
390 inline shambase::DistributedDataShared<PatchDataField<T>> communicate_pdatfield(
392 u32 nvar,
393 std::shared_ptr<shamrock::solvergraph::ExchangeGhostField<T>> exchange_gz_node) {
394 StackEntry stack_loc{};
395
396 // ----------------------------------------------------------------------------------------
397 // temporary wrapper to slowly migrate to the new solvergraph
398 std::shared_ptr<shamrock::solvergraph::PatchDataFieldDDShared<T>> exchange_gz_edge
399 = std::make_shared<shamrock::solvergraph::PatchDataFieldDDShared<T>>("", "");
400
401 exchange_gz_edge->patchdata_fields
402 = std::forward<shambase::DistributedDataShared<PatchDataField<T>>>(interf);
403
404 exchange_gz_node->set_edges(this->patch_rank_owner, exchange_gz_edge);
405
406 exchange_gz_node->evaluate();
407
408 // ----------------------------------------------------------------------------------------
409
411
412#if false
413 shamalgs::collective::serialize_sparse_comm<PatchDataField<T>>(
414 shamsys::instance::get_compute_scheduler_ptr(),
415 std::forward<shambase::DistributedDataShared<PatchDataField<T>>>(interf),
416 recv_dat,
417 [&](u64 id) {
418 return sched.get_patch_rank_owner(id);
419 },
420 [](PatchDataField<T> &pdat) {
421 shamalgs::SerializeHelper ser(shamsys::instance::get_compute_scheduler_ptr());
422 ser.allocate(pdat.serialize_full_byte_size());
423 pdat.serialize_full(ser);
424 return ser.finalize();
425 },
426 [&](sham::DeviceBuffer<u8> &&buf) {
427 // exchange the buffer held by the distrib data and give it to the serializer
429 shamsys::instance::get_compute_scheduler_ptr(),
430 std::forward<sham::DeviceBuffer<u8>>(buf));
432 });
433#else
434 recv_dat = std::move(exchange_gz_edge->patchdata_fields);
435#endif
436
437 return recv_dat;
438 }
439
441 build_communicate_positions(
443 std::shared_ptr<shamrock::solvergraph::ExchangeGhostLayer> &exchange_gz_positions,
444 bool show_debug_infos) {
445 auto pos_interf = build_position_interf_field(builder);
446 return communicate_pdat(
447 xyzh_ghost_layout, std::move(pos_interf), exchange_gz_positions, show_debug_infos);
448 }
449
450 template<class T, class Tmerged>
451 inline shambase::DistributedData<Tmerged> merge_native(
453 std::function<
455 std::function<void(Tmerged &, T &)> appender) {
456
457 StackEntry stack_loc{};
458
460
461 sched.for_each_patchdata_nonempty(
463 Tmerged tmp_merge = init(p, pdat);
464
465 interfs.for_each([&](u64 sender, u64 receiver, T &interface) {
466 if (receiver == p.id_patch) {
467 appender(tmp_merge, interface);
468 }
469 });
470
471 merge_f.add_obj(p.id_patch, std::move(tmp_merge));
472 });
473
474 return merge_f;
475 }
476
479 StackEntry stack_loc{};
480
481 const u32 ihpart = sched.pdl_old().template get_field_idx<flt>("hpart");
482
483 return merge_native<shamrock::patch::PatchDataLayer, shamrock::patch::PatchDataLayer>(
485 positioninterfs),
487 PatchDataField<vec> &pos = pdat.get_field<vec>(0);
488 PatchDataField<flt> &hpart = pdat.get_field<flt>(ihpart);
489
490 shamrock::patch::PatchDataLayer ret(xyzh_ghost_layout);
491
492 ret.get_field<vec>(0).insert(pos);
493 ret.get_field<flt>(1).insert(hpart);
494 ret.check_field_obj_cnt_match();
495
496 return ret;
497 },
499 merged.insert_elements(pint);
500
502 });
503 }
504
506 build_comm_merge_positions(
508 std::shared_ptr<shamrock::solvergraph::ExchangeGhostLayer> &exchange_gz_positions,
509 bool show_debug_infos) {
510 auto pos_interf = build_position_interf_field(builder);
511 return merge_position_buf(communicate_pdat(
512 xyzh_ghost_layout, std::move(pos_interf), exchange_gz_positions, show_debug_infos));
513 }
514 };
515
516} // namespace shammodels::sph
Solver graph node for exchanging ghost field data between distributed processes.
Solver graph node for exchanging ghost layer data between distributed processes.
Solver graph node for exchanging ghost layer data between distributed processes.
constexpr const char * hpart
Smoothing length field.
Header file describing a Node Instance.
Shared distributed data layer for patch data management in solver graphs.
MPI scheduler.
double f64
Alias for double.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
static PatchDataField deserialize_full(shamalgs::SerializeHelper &serializer)
deserialize a field inverse of serialize_full
The MPI scheduler.
SchedulerPatchData patch_data
handle the data of the patches of the scheduler
A buffer allocated in USM (Unified Shared Memory)
size_t get_size() const
Gets the number of elements in the buffer.
void for_each(std::function< void(u64, u64, T &)> &&f)
Apply a function to all stored objects.
Represents a collection of objects distributed across patches identified by a u64 id.
iterator add_obj(u64 id, T &&obj)
Adds a new object to the collection.
shambase::DistributedDataShared< T > build_interface_native_stagged(shambase::DistributedDataShared< InterfaceIdTable > &builder, std::function< T(u64, u64, InterfaceBuildInfos, sycl::buffer< u32 > &, u32)> gen_1, std::function< void(u64, u64, InterfaceBuildInfos, sycl::buffer< u32 > &, u32, T &)> modif)
native handle to generate interfaces generate interfaces of type T (template arg) based on the provid...
CacheMap make_interface_cache(SerialPatchTree< vec > &sptree, shamrock::patch::PatchtreeField< flt > &int_range_max_tree, shamrock::patch::PatchField< flt > &int_range_max)
utility to generate both the metadata and index tables
shambase::DistributedDataShared< InterfaceIdTable > gen_id_table_interfaces(GeneratorMap &&gen)
precompute interfaces members and cache result in the return
shambase::DistributedDataShared< T > build_interface_native(shambase::DistributedDataShared< InterfaceIdTable > &builder, std::function< T(u64, u64, InterfaceBuildInfos, sham::DeviceBuffer< u32 > &, u32)> fct)
native handle to generate interfaces generate interfaces of type T (template arg) based on the provid...
GeneratorMap find_interfaces(SerialPatchTree< vec > &sptree, shamrock::patch::PatchtreeField< flt > &int_range_max_tree, shamrock::patch::PatchField< flt > &int_range_max)
Find interfaces and their metadata.
PatchDataLayer container class, the layout is described in patchdata_layout.
void check_field_obj_cnt_match()
check that all contained field have the same obj cnt
Solver graph node for distributed ghost field data exchange.
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
STL namespace.
This file contains the definition for the stacktrace related functionality.
Patch object that contain generic patch information.
Definition Patch.hpp:33