Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
PatchDataLayer.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
19
21#include "shambase/memory.hpp"
23#include "Patch.hpp"
24#include "PatchDataField.hpp"
28#include <variant>
29#include <vector>
30
31namespace shamrock::patch {
35 class PatchDataLayer {
36
37 void init_fields();
38
39 using var_t = FieldVariant<PatchDataField>;
40
41 std::vector<var_t> fields;
42 std::shared_ptr<PatchDataLayerLayout> pdl_ptr;
43
44 inline var_t &get_field_variant(u32 idx) {
45 if (idx >= fields.size()) {
47 "the requested field index is out of bounds\n"
48 " current map is : \n"
49 + pdl().get_description_str()
50 + "\n"
51 " arg : idx = "
52 + std::to_string(idx));
53 }
54 return fields[idx];
55 }
56
57 inline const var_t &get_field_variant(u32 idx) const {
58 if (idx >= fields.size()) {
60 "the requested field index is out of bounds\n"
61 " current map is : \n"
62 + pdl().get_description_str()
63 + "\n"
64 " arg : idx = "
65 + std::to_string(idx));
66 }
67 return fields[idx];
68 }
69
70 public:
71 using field_variant_t = var_t;
72
73 inline PatchDataLayerLayout &pdl() { return shambase::get_check_ref(pdl_ptr); }
74 inline const PatchDataLayerLayout &pdl() const { return shambase::get_check_ref(pdl_ptr); }
75
76 inline std::shared_ptr<PatchDataLayerLayout> get_layout_ptr() const { return pdl_ptr; }
77
78 inline PatchDataLayer(const std::shared_ptr<PatchDataLayerLayout> &pdl) : pdl_ptr(pdl) {
79 init_fields();
80 }
81
90 PatchDataLayer(const PatchDataLayer &other);
91
97 inline PatchDataLayer(PatchDataLayer &&other) noexcept
98 : fields(std::move(other.fields)), pdl_ptr(std::move(other.pdl_ptr)) {}
99
105 inline PatchDataLayer &operator=(PatchDataLayer &&other) noexcept {
106 fields = std::move(other.fields);
107 pdl_ptr = std::move(other.pdl_ptr);
108 return *this;
109 }
110
111 PatchDataLayer &operator=(const PatchDataLayer &other) = delete;
112
113 static PatchDataLayer mock_patchdata(
114 u64 seed, u32 obj_cnt, const std::shared_ptr<PatchDataLayerLayout> &pdl);
115
116 template<class Functor>
117 inline void for_each_field_any(Functor &&func) {
118 for (auto &f : fields) {
119 f.visit([&](auto &arg) {
120 func(arg);
121 });
122 }
123 }
124
125 template<class Functor>
126 inline void for_each_field_any(Functor &&func) const {
127 for (auto &f : fields) {
128 f.visit([&](const auto &arg) {
129 func(arg);
130 });
131 }
132 }
133
134 template<class Func>
135 inline PatchDataLayer(const std::shared_ptr<PatchDataLayerLayout> &pdl, Func &&fct_init)
136 : pdl_ptr(pdl) {
137
138 u32 cnt = 0;
139
140 fct_init(fields);
141 }
142
143 inline PatchDataLayer duplicate() {
144 const PatchDataLayer &current = *this;
145 return PatchDataLayer(current);
146 }
147
148 inline std::unique_ptr<PatchDataLayer> duplicate_to_ptr() {
149 const PatchDataLayer &current = *this;
150 return std::make_unique<PatchDataLayer>(current);
151 }
152
159 void extract_element(u32 pidx, PatchDataLayer &out_pdat);
160
161 void extract_elements(const sham::DeviceBuffer<u32> &idxs, PatchDataLayer &out_pdat);
162
163 void keep_ids(sycl::buffer<u32> &index_map, u32 len);
164
165 void insert_elements(const PatchDataLayer &pdat);
166
175 template<class T>
176 void insert_elements_in_range(PatchDataLayer &pdat, T bmin, T bmax);
177
178 void resize(u32 new_obj_cnt);
179
180 void reserve(u32 new_obj_cnt);
181
182 void expand(u32 obj_cnt);
183
192 void index_remap(sycl::buffer<u32> &index_map, u32 len);
193
202 void index_remap_resize(sycl::buffer<u32> &index_map, u32 len);
203
205 void index_remap_resize(sham::DeviceBuffer<u32> &index_map, u32 len);
206
208 void keep_ids(sham::DeviceBuffer<u32> &index_map, u32 len);
209
211 void remove_ids(const sham::DeviceBuffer<u32> &indexes, u32 len);
212
213 // template<class Tvecbox>
214 // void split_patchdata(PatchDataLayer & pd0,PatchDataLayer & pd1,PatchDataLayer &
215 // pd2,PatchDataLayer & pd3,PatchDataLayer & pd4,PatchDataLayer & pd5,PatchDataLayer &
216 // pd6,PatchDataLayer & pd7,
217 // Tvecbox bmin_p0,Tvecbox bmin_p1,Tvecbox bmin_p2,Tvecbox bmin_p3,Tvecbox
218 // bmin_p4,Tvecbox bmin_p5,Tvecbox bmin_p6,Tvecbox bmin_p7, Tvecbox bmax_p0,Tvecbox
219 // bmax_p1,Tvecbox bmax_p2,Tvecbox bmax_p3,Tvecbox bmax_p4,Tvecbox bmax_p5,Tvecbox
220 // bmax_p6,Tvecbox bmax_p7);
221
222 template<class Tvecbox>
223 void split_patchdata(
224 std::array<std::reference_wrapper<PatchDataLayer>, 8> pdats,
225 std::array<Tvecbox, 8> min_box,
226 std::array<Tvecbox, 8> max_box);
227
228 void append_subset_to(const std::vector<u32> &idxs, PatchDataLayer &pdat);
229 void append_subset_to(sycl::buffer<u32> &idxs_buf, u32 sz, PatchDataLayer &pdat);
230 void append_subset_to(
231 const sham::DeviceBuffer<u32> &idxs_buf, u32 sz, PatchDataLayer &pdat) const;
232
238 u32 get_obj_cnt() const;
239
245 u64 memsize();
246
247 inline bool is_empty() { return get_obj_cnt() == 0; }
248
250 void synchronize_buf();
251
252 void overwrite(PatchDataLayer &pdat, u32 obj_cnt);
253
254 template<class T>
255 bool check_field_type(u32 idx) {
256 var_t &tmp = get_field_variant(idx);
257
258 PatchDataField<T> *pval = std::get_if<PatchDataField<T>>(&tmp.value);
259
260 if (pval) {
261 return true;
262 } else {
263 return false;
264 }
265 }
266
267 template<class T>
268 PatchDataField<T> &get_field(u32 idx) {
269
270 var_t &tmp = get_field_variant(idx);
271
272 PatchDataField<T> *pval = std::get_if<PatchDataField<T>>(&tmp.value);
273
274 if (pval) {
275 return *pval;
276 }
277
279 "the request id is not of correct type\n"
280 " current map is : \n"
281 + pdl().get_description_str()
282 + "\n"
283 " arg : idx = "
284 + std::to_string(idx));
285 }
286
287 template<class T>
288 const PatchDataField<T> &get_field(u32 idx) const {
289
290 const var_t &tmp = get_field_variant(idx);
291
292 const PatchDataField<T> *pval = std::get_if<PatchDataField<T>>(&tmp.value);
293
294 if (pval) {
295 return *pval;
296 }
297
299 "the request id is not of correct type\n"
300 " current map is : \n"
301 + pdl().get_description_str()
302 + "\n"
303 " arg : idx = "
304 + std::to_string(idx));
305 }
306
307 template<class T>
308 PatchDataField<T> &get_field(const std::string &field_name) {
309 return get_field<T>(pdl().get_field_idx<T>(field_name));
310 }
311
312 template<class T>
313 const PatchDataField<T> &get_field(const std::string &field_name) const {
314 return get_field<T>(pdl().get_field_idx<T>(field_name));
315 }
316
317 template<class T>
318 sham::DeviceBuffer<T> &get_field_buf_ref(u32 idx) {
319
320 var_t &tmp = get_field_variant(idx);
321
322 PatchDataField<T> *pval = std::get_if<PatchDataField<T>>(&tmp.value);
323
324 if (pval) {
325 return pval->get_buf();
326 }
327
329 "the request id is not of correct type\n"
330 " current map is : \n"
331 + pdl().get_description_str()
332 + "\n"
333 " arg : idx = "
334 + std::to_string(idx));
335 }
336
343 template<class T, u32 nvar>
345 return get_field<T>(idx).template get_span<nvar>();
346 }
347
355 template<class T>
357 return get_field<T>(idx).get_span_nvar_dynamic();
358 }
359
360 template<class T>
362 get_field_pointer_span(u32 idx) {
363 return get_field<T>(idx).get_pointer_span();
364 }
365
371
372 // template<class T> inline std::vector<PatchDataField<T> & > get_field_list(){
373 // std::vector<PatchDataField<T> & > ret;
374 //
375 //
376 //}
377
378 template<class T, class Functor>
379 inline void for_each_field(Functor &&func) {
380 for (auto &f : fields) {
381 PatchDataField<T> *pval = std::get_if<PatchDataField<T>>(&f.value);
382
383 if (pval) {
384 func(*pval);
385 }
386 }
387 }
388
390 friend bool operator==(PatchDataLayer &p1, PatchDataLayer &p2);
391
392 void serialize_buf(shamalgs::SerializeHelper &serializer);
393
394 shamalgs::SerializeSize serialize_buf_byte_size();
395
396 static PatchDataLayer deserialize_buf(
397 shamalgs::SerializeHelper &serializer,
398 const std::shared_ptr<PatchDataLayerLayout> &pdl);
399
400 void fields_raz();
401
407 bool has_nan();
408
414 bool has_inf();
415
421 bool has_nan_or_inf();
422
431 template<class T>
432 void override_patch_field(std::string field_name, std::vector<T> &vec) {
433 u32 len = vec.size();
434 PatchDataField<T> &f = get_field<T>(pdl().get_field_idx<T>(field_name));
435 sycl::buffer<T> buf(vec.data(), len);
436 f.override(buf, len);
437 }
438
449 template<class T>
450 inline std::vector<T> fetch_data(std::string key) {
451
452 std::vector<T> vec;
453
454 auto appender = [&](auto &field) {
455 if (field.get_name() == key) {
456
457 shamlog_debug_ln("PyShamrockCTX", "appending field", key);
458
459 if (!field.is_empty()) {
460 auto acc = field.get_buf().copy_to_stdvec();
461 u32 len = field.get_val_cnt();
462
463 for (u32 i = 0; i < len; i++) {
464 vec.push_back(acc[i]);
465 }
466 }
467 }
468 };
469
470 for_each_field<T>([&](auto &field) {
471 appender(field);
472 });
473
474 return vec;
475 }
476 };
477
481 bool operator==(PatchDataLayer &p1, PatchDataLayer &p2);
482
483 template<class T>
484 inline void PatchDataLayer::insert_elements_in_range(PatchDataLayer &pdat, T bmin, T bmax) {
485
486 StackEntry stack_loc{};
487
488 if (!pdl().check_main_field_type<T>()) {
489
491 "the chosen type for the main field does not match the required template type");
492 }
493
494 PatchDataField<T> &main_field = pdat.get_field<T>(0);
495
496 // Note that using get_ids_vec_where here is safe since nvar for main_field is equal to 1
497 // hence the Lambda cd_true will be applied to each block on the patch. e.g : i * nvar = i
498 auto get_vec_idx = [&](T vmin, T vmax) -> std::vector<u32> {
499 return main_field.get_ids_vec_where(
500 [&](const auto &acc, u32 idx, T vmin, T vmax) {
501 if (shambase::VectorProperties<T>::dimension == 3) {
502 T val = acc[idx];
503 return shammath::is_in_half_open(val, vmin, vmax);
504 } else {
506 "dimension != 3 is not handled");
507 }
508 },
509 vmin,
510 vmax);
511 };
512
513 // auto get_vec_idx = [&](T vmin, T vmax) -> std::vector<u32> {
514 // return main_field.get_elements_with_range(
515 // [&](T val, T vmin, T vmax) {
516 // if (shambase::VectorProperties<T>::dimension == 3) {
517 // return shammath::is_in_half_open(val, vmin, vmax);
518 // } else {
519 // throw shambase::make_except_with_loc<std::runtime_error>(
520 // "dimension != 3 is not handled");
521 // }
522 // },
523 // vmin,
524 // vmax);
525 // };
526
527 std::vector<u32> idx_lst = get_vec_idx(bmin, bmax);
528
529 shamlog_debug_sycl_ln("PatchDataLayer", "inserting element cnt =", idx_lst.size());
530
531 pdat.append_subset_to(idx_lst, *this);
532 }
533
534} // namespace shamrock::patch
Header file for the patch struct and related function.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
std::vector< u32 > get_ids_vec_where(Lambdacd &&cd_true, Args &&...args)
Same function as.
Represents a span of data within a PatchDataField.
PatchDataLayer container class, the layout is described in patchdata_layout.
void override_patch_field(std::string field_name, std::vector< T > &vec)
void index_remap(sycl::buffer< u32 > &index_map, u32 len)
this function remaps the patchdatafield like so val[id] = val[index_map[id]] This function can be use...
bool has_inf()
check whether any field contains an infinite value
friend bool operator==(PatchDataLayer &p1, PatchDataLayer &p2)
Compare two layers field by field (defined in PatchDataLayer.cpp).
PatchDataLayer & operator=(PatchDataLayer &&other) noexcept
PatchDataLayer move assignment.
void check_field_obj_cnt_match()
check that all contained field have the same obj cnt
PatchDataFieldSpan< T, shamrock::dynamic_nvar > get_field_span_nvar_dynamic(u32 idx)
returns a PatchDataFieldSpan of the field at index idx, with a dynamic number of variables
PatchDataLayer(PatchDataLayer &&other) noexcept
PatchDataLayer move constructor.
u32 get_obj_cnt() const
get the number of objects (particles) stored in this layer
void synchronize_buf()
synchronize the host/device buffers of all fields
std::vector< T > fetch_data(std::string key)
Fetch data of a patchdata field into a std::vector.
void index_remap_resize(sycl::buffer< u32 > &index_map, u32 len)
this function remaps the patchdatafield like so val[id] = val[index_map[id]] This function can be use...
void remove_ids(const sham::DeviceBuffer< u32 > &indexes, u32 len)
remove some particles ids
bool has_nan()
check whether any field contains a NaN value
void extract_element(u32 pidx, PatchDataLayer &out_pdat)
extract particle at index pidx and insert it in the provided vectors
bool has_nan_or_inf()
check whether any field contains a NaN or infinite value
PatchDataFieldSpan< T, nvar > get_field_span(u32 idx)
returns a PatchDataFieldSpan of the field at index idx, with the given nvar value
void insert_elements_in_range(PatchDataLayer &pdat, T bmin, T bmax)
insert elements of pdat only if they are within the range
u64 memsize()
get the memory size in bytes used by all fields
This header file contains utility functions related to exception handling in the code.
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
ExcptTypes make_except_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Create an exception with a message and a location.
bool is_in_half_open(T val, T min, T max)
return true if val is in [min,max[
Definition intervals.hpp:36
This file contains the definition for the stacktrace related functionality.
shambase::details::BasicStackEntry StackEntry
Alias for shambase::details::BasicStackEntry.