31 template<
class Tvec,
class Tfield,
template<
class>
class SPHKernel>
32 shamrock::solvergraph::Field<Tfield> RenderFieldGetter<Tvec, Tfield, SPHKernel>::build_field(
33 std::string field_name,
34 std::optional<std::function<py::array_t<Tfield>(
size_t, shamrock::PatchDataLazyGetter &)>>
37 if (field_name !=
"custom" && custom_getter.has_value()) {
39 "custom_getter is only supported for the custom field");
42 shambase::DistributedData<u32>
sizes{};
44 using namespace shamrock;
45 using namespace shamrock::patch;
47 scheduler().for_each_patchdata_nonempty([&](
const Patch p, PatchDataLayer &pdat) {
51 auto make_field = [&](
u32 nvar, std::string name, std::string texsymbol) {
52 shamrock::solvergraph::Field<Tfield> ret
53 = shamrock::solvergraph::Field<Tfield>(nvar, name, texsymbol);
58 if constexpr (std::is_same_v<Tfield, f64>) {
59 if (field_name ==
"rho" && std::is_same_v<Tscal, Tfield>) {
61 auto density = make_field(1,
"rho",
"rho");
63 scheduler().for_each_patchdata_nonempty([&](
const Patch p, PatchDataLayer &pdat) {
64 shamlog_debug_ln(
"sph::vtk",
"compute rho field for patch ", p.id_patch);
67 = pdat.get_field<Tscal>(pdat.pdl().get_field_idx<Tscal>(
"hpart")).get_buf();
68 auto &buf_rho =
density.get_buf(p.id_patch);
70 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().
get_queue();
72 sham::EventList depends_list;
74 auto acc_h = buf_h.get_read_access(depends_list);
75 auto acc_rho = buf_rho.get_write_access(depends_list);
77 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
78 const Tscal part_mass = solver_config.gpart_mass;
81 sycl::range<1>{pdat.
get_obj_cnt()}, [=](sycl::item<1> item) {
82 u32 gid = (
u32) item.get_id();
83 using namespace shamrock::sph;
84 Tscal rho_ha = rho_h(part_mass, acc_h[gid], Kernel::hfactd);
85 acc_rho[gid] = rho_ha;
89 buf_h.complete_event_state(e);
90 buf_rho.complete_event_state(e);
94 }
else if (field_name ==
"inv_hpart" && std::is_same_v<Tscal, Tfield>) {
96 auto inv_hpart = make_field(1,
"inv_hpart",
"inv_hpart");
98 scheduler().for_each_patchdata_nonempty([&](
const Patch p, PatchDataLayer &pdat) {
99 shamlog_debug_ln(
"sph::vtk",
"compute inv_hpart field for patch ", p.id_patch);
102 = pdat.get_field<Tscal>(pdat.pdl().get_field_idx<Tscal>(
"hpart")).get_buf();
103 auto &buf_inv_hpart = inv_hpart.get_buf(p.id_patch);
105 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().
get_queue();
107 sham::EventList depends_list;
109 auto acc_h = buf_h.get_read_access(depends_list);
110 auto acc_inv_hpart = buf_inv_hpart.get_write_access(depends_list);
112 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
114 sycl::range<1>{pdat.
get_obj_cnt()}, [=](sycl::item<1> item) {
115 u32 gid = (
u32) item.get_id();
116 using namespace shamrock::sph;
117 acc_inv_hpart[gid] = 1.0 / acc_h[gid];
121 buf_h.complete_event_state(e);
122 buf_inv_hpart.complete_event_state(e);
126 }
else if (field_name ==
"unity" && std::is_same_v<Tscal, Tfield>) {
127 using namespace shamrock;
128 using namespace shamrock::patch;
130 auto unity = make_field(1,
"unity",
"unity");
132 unity.get_buf(id_patch).fill(1);
136 }
else if (field_name ==
"custom" && custom_getter.has_value()) {
137 std::function<py::array_t<Tfield>(
size_t, shamrock::PatchDataLazyGetter &)>
138 &field_source_getter = custom_getter.value();
140 auto custom = make_field(1,
"custom",
"custom");
142 shambase::Timer timer;
145 scheduler().for_each_patchdata_nonempty([&](
const Patch p, PatchDataLayer &pdat) {
146 shamlog_debug_ln(
"sph::vtk",
"compute custom field for patch ", p.id_patch);
148 auto &buf_custom = custom.get_buf(p.id_patch);
150 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().
get_queue();
152 shamrock::PatchDataLazyGetter lazy_getter(pdat);
153 std::vector<Tfield> acc_custom = buf_custom.copy_to_stdvec();
155 py::array_t<Tfield> custom_array
156 = field_source_getter(pdat.
get_obj_cnt(), lazy_getter);
158 if (acc_custom.size() != custom_array.size()) {
160 "custom_array size does not match the number of particles");
163 acc_custom = custom_array.template cast<std::vector<Tfield>>();
165 buf_custom.copy_from_stdvec(acc_custom);
170 f64 worse_time_rank = shamalgs::collective::allreduce_max(timer.
elapsed_sec());
174 "sph::RenderFieldGetter",
175 "compute custom field took : ",
184 auto field_source_getter
185 = [&](
const shamrock::patch::Patch cur_p,
186 shamrock::patch::PatchDataLayer &pdat) ->
const sham::DeviceBuffer<Tfield> & {
187 return pdat.get_field<Tfield>(pdat.pdl().get_field_idx<Tfield>(field_name)).get_buf();
190 FieldDescriptor<Tfield> desc = scheduler().pdl_old().template get_field<Tfield>(field_name);
191 u32 ifield = scheduler().pdl_old().template get_field_idx<Tfield>(field_name);
197 auto ret = make_field(1, desc.
name, desc.
name);
199 scheduler().for_each_patchdata_nonempty([&](
const Patch p, PatchDataLayer &pdat) {
200 sham::DeviceBuffer<Tfield> &buf = ret.get_buf(p.id_patch);
202 pdat.get_field<Tfield>(pdat.pdl().
get_field_idx<Tfield>(field_name)).get_buf());
208 template<
class Tvec,
class Tfield,
template<
class>
class SPHKernel>
209 auto RenderFieldGetter<Tvec, Tfield, SPHKernel>::runner_function(
210 std::string field_name,
212 std::optional<std::function<py::array_t<Tfield>(
size_t, shamrock::PatchDataLazyGetter &)>>
213 custom_getter) -> sham::DeviceBuffer<Tfield> {
215 auto field = build_field(std::move(field_name), std::move(custom_getter));
217 auto field_source_getter
218 = [&](
const shamrock::patch::Patch cur_p,
219 shamrock::patch::PatchDataLayer &pdat) ->
const sham::DeviceBuffer<Tfield> & {
220 return field.get_buf(cur_p.
id_patch);
223 return lambda(field_source_getter);
constexpr const char * density
Density \rho (derived from h).
constexpr const char * sizes
Temporary sizes for h-iteration.
double f64
Alias for double.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
void copy_from(const DeviceBuffer< T, new_target > &other, size_t copy_size)
Copies the content of another buffer to this one.
sycl::event submit(Fct &&fct)
Submits a kernel to the SYCL queue.
DeviceQueue & get_queue(u32 id=0)
Get a reference to a DeviceQueue.
f64 elapsed_sec() const
Converts the stored nanosecond time to a floating point representation in seconds.
void start()
Starts the timer.
void stop()
Stops the timer and stores the elapsed time in nanoseconds.
std::string name
The name of the field.
u32 nvar
The number of variables of the field per object.
u32 get_field_idx(const std::string &field_name) const
Get the field id if matching name & type.
u32 get_obj_cnt() const
get the number of objects (particles) stored in this layer
virtual void ensure_sizes(const shambase::DistributedData< u32 > &sizes)
Ensure that the sizes of the patches in the field match the given sizes (Can resize the underlying fi...
This header file contains utility functions related to exception handling in the code.
ExcptTypes make_except_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Create an exception with a message and a location.
void throw_unimplemented(SourceLocation loc=SourceLocation{})
Throw a std::runtime_error saying that the function is unimplemented.
i32 world_rank()
Gives the rank of the current process in the MPI communicator.
namespace for math utility
namespace for the sph model modules
u64 id_patch
unique key that identify the patch