168 sycl::vec<T, 3> shift;
169 sycl::vec<T, 3> shift_speed;
173using ShearPeriodicInfo =
178 i32_3 ioff, ShearPeriodicInfo<T> shear, sycl::vec<T, 3> bsize) {
180 i32 dx = ioff.x() * shear.shear_base.x();
181 i32 dy = ioff.y() * shear.shear_base.y();
182 i32 dz = ioff.z() * shear.shear_base.z();
184 i32 d = dx + dy + dz;
186 sycl::vec<T, 3> shift
187 = {(d * shear.shear_dir.x()) * shear.shear_value + bsize.x() * ioff.x(),
188 (d * shear.shear_dir.y()) * shear.shear_value + bsize.y() * ioff.y(),
189 (d * shear.shear_dir.z()) * shear.shear_value + bsize.z() * ioff.z()};
190 sycl::vec<T, 3> shift_speed
191 = {(d * shear.shear_dir.x()) * shear.shear_speed,
192 (d * shear.shear_dir.y()) * shear.shear_speed,
193 (d * shear.shear_dir.z()) * shear.shear_speed};
195 return {shift, shift_speed};
199inline void for_each_patch_shift(
200 ShearPeriodicInfo<T> shearinfo,
201 sycl::vec<T, 3> bsize,
204 i32_3 loop_offset = {0, 0, 0};
206 std::vector<i32_3> list_possible;
212 i32 repetition_x = 1 + sham::abs(shearinfo.shear_dir.x());
213 i32 repetition_y = 1 + sham::abs(shearinfo.shear_dir.y());
214 i32 repetition_z = 1 + sham::abs(shearinfo.shear_dir.z());
216 T sz = bsize.x() * shearinfo.shear_dir.x() + bsize.y() * shearinfo.shear_dir.y()
217 + bsize.z() * shearinfo.shear_dir.z();
219 for (
i32 xoff = -repetition_x; xoff <= repetition_x; xoff++) {
220 for (
i32 yoff = -repetition_y; yoff <= repetition_y; yoff++) {
221 for (
i32 zoff = -repetition_z; zoff <= repetition_z; zoff++) {
223 i32 dx = xoff * shearinfo.shear_base.x();
224 i32 dy = yoff * shearinfo.shear_base.y();
225 i32 dz = zoff * shearinfo.shear_base.z();
227 i32 d = dx + dy + dz;
229 i32 df = -int(d * shearinfo.shear_value / sz);
232 = {shearinfo.shear_dir.x() * df,
233 shearinfo.shear_dir.y() * df,
234 shearinfo.shear_dir.z() * df};
242 list_possible.resize(list_possible.size() + 1);
243 list_possible[list_possible.size() - 1]
244 = i32_3{xoff + off_d.x(), yoff + off_d.y(), zoff + off_d.z()};
251 for (i32_3 off : list_possible) {
253 auto shift = compute_shift_infos(off, shearinfo, bsize);
271 using namespace shamrock::patch;
274 i32 repetition_x = 1;
275 i32 repetition_y = 1;
276 i32 repetition_z = 1;
283 GeneratorMap interf_map;
286 using BCConfig =
typename CfgClass::Variant;
295 if (BCPeriodic *cfg = std::get_if<BCPeriodic>(&ghost_config)) {
296 sycl::host_accessor acc_tf{
299 for (
i32 xoff = -repetition_x; xoff <= repetition_x; xoff++) {
300 for (
i32 yoff = -repetition_y; yoff <= repetition_y; yoff++) {
301 for (
i32 zoff = -repetition_z; zoff <= repetition_z; zoff++) {
304 vec periodic_offset =
vec{xoff * bsize.x(), yoff * bsize.y(), zoff * bsize.z()};
306 sycl::host_accessor tree{
308 sycl::host_accessor lpid{
311#pragma omp parallel for
312 for (
u32 i = 0; i < sched.patch_list.local.size(); i++) {
315 CoordRange<vec> sender_bsize = patch_coord_transf.to_obj_coord(psender);
317 = sender_bsize.add_offset(periodic_offset);
319 flt sender_volume = sender_bsize.get_volume();
321 flt sender_h_max = int_range_max.get(psender.
id_patch);
323 using PtNode =
typename SerialPatchTree<vec>::PtNode;
325 sptree.host_for_each_leafs_internal(
326 [&](
u64 tree_id, PtNode n) {
327 flt receiv_h_max = acc_tf[tree_id];
329 n.box_min - receiv_h_max, n.box_max + receiv_h_max};
331 return receiv_exp.get_intersect(sender_bsize_off)
334 [&](
u64 id_found, PtNode n) {
335 if ((id_found == psender.
id_patch) && (xoff == 0) && (yoff == 0)
342 int_range_max.get(id_found));
345 receiv_exp.add_offset(-periodic_offset));
355 interf_volume.get_volume() / sender_volume});
364 }
else if (BCShearingPeriodic *cfg = std::get_if<BCShearingPeriodic>(&ghost_config)) {
365 sycl::host_accessor acc_tf{
368 for_each_patch_shift<flt>(*cfg, bsize, [&](i32_3 ioff,
ShiftInfo<flt> shift) {
373 vec offset = shift.shift;
375 sycl::host_accessor tree{
377 sycl::host_accessor lpid{
380#pragma omp parallel for
381 for (
u32 i = 0; i < sched.patch_list.local.size(); i++) {
385 CoordRange<vec> sender_bsize = patch_coord_transf.to_obj_coord(psender);
388 flt sender_volume = sender_bsize.get_volume();
390 flt sender_h_max = int_range_max.get(psender.
id_patch);
392 using PtNode =
typename SerialPatchTree<vec>::PtNode;
394 sptree.host_for_each_leafs_internal(
395 [&](
u64 tree_id, PtNode n) {
396 flt receiv_h_max = acc_tf[tree_id];
398 n.box_min - receiv_h_max, n.box_max + receiv_h_max};
400 return receiv_exp.get_intersect(sender_bsize_off).is_not_empty();
402 [&](
u64 id_found, PtNode n) {
403 if ((id_found == psender.
id_patch) && (xoff == 0) && (yoff == 0)
410 int_range_max.get(id_found));
413 = sender_bsize.get_intersect(receiv_exp.add_offset(-offset));
423 interf_volume.get_volume() / sender_volume});
435 sycl::host_accessor acc_tf{
438 vec periodic_offset =
vec{0, 0, 0};
441 sycl::host_accessor lpid{
444#pragma omp parallel for
445 for (
u32 i = 0; i < sched.patch_list.local.size(); i++) {
448 CoordRange<vec> sender_bsize = patch_coord_transf.to_obj_coord(psender);
449 CoordRange<vec> sender_bsize_off = sender_bsize.add_offset(periodic_offset);
451 flt sender_volume = sender_bsize.get_volume();
453 flt sender_h_max = int_range_max.get(psender.
id_patch);
455 using PtNode =
typename SerialPatchTree<vec>::PtNode;
457 sptree.host_for_each_leafs_internal(
458 [&](
u64 tree_id, PtNode n) {
459 flt receiv_h_max = acc_tf[tree_id];
461 n.box_min - receiv_h_max, n.box_max + receiv_h_max};
463 return receiv_exp.get_intersect(sender_bsize_off).is_not_empty();
465 [&](
u64 id_found, PtNode n) {
472 int_range_max.get(id_found));
475 = sender_bsize.get_intersect(receiv_exp.add_offset(-periodic_offset));
485 interf_volume.get_volume() / sender_volume});
518 using namespace shamrock::patch;
522 auto positions = std::make_shared<shamrock::solvergraph::FieldRefs<vec>>(
"",
"");
525 positions_refs.add_obj(p.id_patch, std::ref(pdat.get_field<
vec>(0)));
527 positions->set_refs(positions_refs);
530 = std::make_shared<shamrock::solvergraph::DDSharedScalar<InterfaceBuildInfos>>(
"",
"");
531 interface_infos->values = std::forward<GeneratorMap>(gen);
533 auto interface_id_table
534 = std::make_shared<shamrock::solvergraph::DDSharedScalar<InterfaceIdTable>>(
"",
"");
537 node.set_edges(positions, interface_infos, interface_id_table);
541 return std::move(interface_id_table->values);
545void BasicSPHGhostHandler<vec>::gen_debug_patch_ghost(
549 static u32 cnt_dump_debug = 0;
551 std::string loc_graph =
"";
552 interf_info.
for_each([&loc_graph](
u64 send,
u64 recv, InterfaceIdTable &info) {
553 loc_graph += sham::format(
" p{} -> p{}\n", send, recv);
556 sched.for_each_patch_data(
559 loc_graph += sham::format(
560 " p{} [label= \"id={} N={}\"]\n",
id,
id, pdat.
get_obj_cnt());
564 std::string dot_graph =
"";
567 dot_graph =
"strict digraph {\n" + dot_graph +
"}";
570 std::string fname = sham::format(
"ghost_graph_{}.dot", cnt_dump_debug);
Solvergraph node selecting the ids of the particles sent through each ghost interface.
shambase::DistributedData< PatchDataFieldRef< T > > DDPatchDataFieldRef
Alias for a DistributedData of PatchDataFieldRefs.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
std::int32_t i32
32 bit integer
Container for objects shared between two distributed data elements.
void for_each(std::function< void(u64, u64, T &)> &&f)
Apply a function to all stored objects.
Class Timer measures the time elapsed since the timer was started.
void start()
Starts the timer.
Vector class based on std::array storage and mdspan.
shambase::DistributedDataShared< InterfaceIdTable > gen_id_table_interfaces(GeneratorMap &&gen)
precompute interfaces members and cache result in the return
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.
Build the id table of every ghost interface.
PatchDataLayer container class, the layout is described in patchdata_layout.
u32 get_obj_cnt() const
get the number of objects (particles) stored in this layer
Store the information related to the size of the simulation box to convert patch integer coordinates ...
T get_bounding_box_size() const
Get the size of the stored bounding box of the domain.
PatchCoordTransform< T > get_patch_transform() const
Get a PatchCoordTransform object that describes the conversion between patch coordinates and domain c...
void evaluate()
Evaluate the node.
This header file contains utility functions related to exception handling in the code.
MPI string gather / allgather helpers (declarations; implementations in shamalgs/src/collective/gathe...
void gather_str(const std::string &send_vec, std::string &recv_vec)
Gathers a string from all nodes and store the result in a std::string.
void write_string_to_file(std::string filename, std::string s)
dump a string to a file
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...
i32 world_rank()
Gives the rank of the current process in the MPI communicator.
namespace for math utility
namespace for the sph model
void info_ln(std::string module_name, Types... var2)
Prints a log message with multiple arguments followed by a newline.
shambase::details::BasicStackEntry StackEntry
Alias for shambase::details::BasicStackEntry.
Boundary conditions configuration.
Patch object that contain generic patch information.
bool is_err_mode() const
check if a patch is in error mode
u64 id_patch
unique key that identify the patch
Functions related to the MPI communicator.