Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
RenderFieldGetter.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
17
27#include <string>
28
30
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 &)>>
35 custom_getter) {
36
37 if (field_name != "custom" && custom_getter.has_value()) {
39 "custom_getter is only supported for the custom field");
40 }
41
42 shambase::DistributedData<u32> sizes{};
43
44 using namespace shamrock;
45 using namespace shamrock::patch;
46
47 scheduler().for_each_patchdata_nonempty([&](const Patch p, PatchDataLayer &pdat) {
48 sizes.add_obj(p.id_patch, pdat.get_obj_cnt());
49 });
50
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);
54 ret.ensure_sizes(sizes);
55 return ret;
56 };
57
58 if constexpr (std::is_same_v<Tfield, f64>) {
59 if (field_name == "rho" && std::is_same_v<Tscal, Tfield>) {
60
61 auto density = make_field(1, "rho", "rho");
62
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);
65
66 auto &buf_h
67 = pdat.get_field<Tscal>(pdat.pdl().get_field_idx<Tscal>("hpart")).get_buf();
68 auto &buf_rho = density.get_buf(p.id_patch);
69
70 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
71
72 sham::EventList depends_list;
73
74 auto acc_h = buf_h.get_read_access(depends_list);
75 auto acc_rho = buf_rho.get_write_access(depends_list);
76
77 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
78 const Tscal part_mass = solver_config.gpart_mass;
79
80 cgh.parallel_for(
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;
86 });
87 });
88
89 buf_h.complete_event_state(e);
90 buf_rho.complete_event_state(e);
91 });
92
93 return density;
94 } else if (field_name == "inv_hpart" && std::is_same_v<Tscal, Tfield>) {
95
96 auto inv_hpart = make_field(1, "inv_hpart", "inv_hpart");
97
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);
100
101 auto &buf_h
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);
104
105 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
106
107 sham::EventList depends_list;
108
109 auto acc_h = buf_h.get_read_access(depends_list);
110 auto acc_inv_hpart = buf_inv_hpart.get_write_access(depends_list);
111
112 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
113 cgh.parallel_for(
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];
118 });
119 });
120
121 buf_h.complete_event_state(e);
122 buf_inv_hpart.complete_event_state(e);
123 });
124
125 return inv_hpart;
126 } else if (field_name == "unity" && std::is_same_v<Tscal, Tfield>) {
127 using namespace shamrock;
128 using namespace shamrock::patch;
129
130 auto unity = make_field(1, "unity", "unity");
131 sizes.for_each([&](u64 id_patch, u32 size) {
132 unity.get_buf(id_patch).fill(1);
133 });
134
135 return unity;
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();
139
140 auto custom = make_field(1, "custom", "custom");
141
142 shambase::Timer timer;
143 timer.start();
144
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);
147
148 auto &buf_custom = custom.get_buf(p.id_patch);
149
150 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
151
152 shamrock::PatchDataLazyGetter lazy_getter(pdat);
153 std::vector<Tfield> acc_custom = buf_custom.copy_to_stdvec();
154
155 py::array_t<Tfield> custom_array
156 = field_source_getter(pdat.get_obj_cnt(), lazy_getter);
157
158 if (acc_custom.size() != custom_array.size()) {
160 "custom_array size does not match the number of particles");
161 }
162
163 acc_custom = custom_array.template cast<std::vector<Tfield>>();
164
165 buf_custom.copy_from_stdvec(acc_custom);
166 });
167
168 timer.stop();
169
170 f64 worse_time_rank = shamalgs::collective::allreduce_max(timer.elapsed_sec());
171
172 if (shamcomm::world_rank() == 0) {
173 logger::raw_ln(
174 "sph::RenderFieldGetter",
175 "compute custom field took : ",
176 worse_time_rank,
177 "s");
178 }
179
180 return custom;
181 }
182 }
183
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();
188 };
189
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);
192
193 if (desc.nvar > 1) {
194 shambase::throw_unimplemented("this cannot handle cases with nvar > 1, yet ...");
195 }
196
197 auto ret = make_field(1, desc.name, desc.name);
198
199 scheduler().for_each_patchdata_nonempty([&](const Patch p, PatchDataLayer &pdat) {
200 sham::DeviceBuffer<Tfield> &buf = ret.get_buf(p.id_patch);
201 buf.copy_from(
202 pdat.get_field<Tfield>(pdat.pdl().get_field_idx<Tfield>(field_name)).get_buf());
203 });
204
205 return ret;
206 }
207
208 template<class Tvec, class Tfield, template<class> class SPHKernel>
209 auto RenderFieldGetter<Tvec, Tfield, SPHKernel>::runner_function(
210 std::string field_name,
211 lamda_runner lambda,
212 std::optional<std::function<py::array_t<Tfield>(size_t, shamrock::PatchDataLazyGetter &)>>
213 custom_getter) -> sham::DeviceBuffer<Tfield> {
214
215 auto field = build_field(std::move(field_name), std::move(custom_getter));
216
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);
221 };
222
223 return lambda(field_source_getter);
224 }
225} // namespace shammodels::sph::modules
226
227using namespace shammath;
231
235
239
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.
Definition Timer.hpp:88
void start()
Starts the timer.
Definition Timer.hpp:51
void stop()
Stops the timer and stores the elapsed time in nanoseconds.
Definition Timer.hpp:65
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...
Definition Field.hpp:92
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.
Definition worldInfo.cpp:41
namespace for math utility
Definition AABB.hpp:26
namespace for the sph model modules
u64 id_patch
unique key that identify the patch
Definition Patch.hpp:86