26#define ZVEC shambase::VectorProperties<Tvec>::get_zero()
28template<
class Tvec,
template<
class>
class SPHKernel>
30 bool also_do_div_curl_v) {
34 shamlog_debug_ln(
"SPH",
"Updating dt divv");
36 Tscal gpart_mass = solver_config.gpart_mass;
39 using namespace shamrock::patch;
44 sph::BasicSPHGhostHandler<Tvec> &ghost_handle = storage.ghost_handler.get();
48 auto &merged_xyzh = storage.merged_xyzh.get();
67 = merged_xyzh.get(cur_p.
id_patch).template get_field_buf_ref<Tvec>(0);
79 sycl::range range_npart{pdat.get_obj_cnt()};
86 if (!also_do_div_curl_v) {
95 auto axyz = buf_axyz.get_read_access(depends_list);
96 auto hpart = buf_hpart.get_read_access(depends_list);
97 auto omega = buf_omega.get_read_access(depends_list);
98 auto dtdivv = buf_dtdivv.get_write_access(depends_list);
99 auto ploop_ptrs = pcache.get_read_access(depends_list);
101 auto e = queue.
submit(depends_list, [&](sycl::handler &cgh) {
102 const Tscal pmass = gpart_mass;
106 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
108 shambase::parallel_for(cgh, pdat.get_obj_cnt(),
"compute dtdivv", [=](
i32 id_a) {
109 using namespace shamrock::sph;
111 Tvec sum_axyz = ZVEC;
113 Tscal h_a = hpart[id_a];
114 Tvec xyz_a = xyz[id_a];
115 Tvec vxyz_a = vxyz[id_a];
116 Tvec axyz_a = axyz[id_a];
117 Tscal omega_a = omega[id_a];
119 Tscal rho_a = rho_h(pmass, h_a, Kernel::hfactd);
122 Tscal inv_rho_omega_a = 1. / (omega_a * rho_a);
124 Tscal sum_nabla_a = 0;
126 std::array<Tvec, dim> Rij_a{ZVEC, ZVEC, ZVEC};
128 std::array<Tvec, dim> Rij_a_dvk_dxj{ZVEC, ZVEC, ZVEC};
129 std::array<Tvec, dim> Rij_a_dak_dxj{ZVEC, ZVEC, ZVEC};
131 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
133 Tvec r_ab = xyz_a -
xyz[id_b];
134 Tscal rab2 = sycl::dot(r_ab, r_ab);
135 Tscal h_b =
hpart[id_b];
137 if (rab2 > h_a * h_a * Rker2 && rab2 > h_b * h_b * Rker2) {
141 Tscal rab = sycl::sqrt(rab2);
142 Tvec vxyz_b =
vxyz[id_b];
143 Tvec axyz_b =
axyz[id_b];
144 Tvec v_ab = vxyz_a - vxyz_b;
145 Tvec a_ab = axyz_a - axyz_b;
147 Tvec r_ab_unit = r_ab / rab;
150 r_ab_unit = {0, 0, 0};
153 Tvec dWab_a = Kernel::dW_3d(rab, h_a) * r_ab_unit;
155 Tvec mdWab_b = dWab_a * pmass;
157 static_assert(dim == 3,
"this is only implemented for dim 3");
158 Rij_a[0] -= r_ab.x() * mdWab_b;
159 Rij_a[1] -= r_ab.y() * mdWab_b;
160 Rij_a[2] -= r_ab.z() * mdWab_b;
162 Rij_a_dvk_dxj[0] -= v_ab * mdWab_b.x();
163 Rij_a_dvk_dxj[1] -= v_ab * mdWab_b.y();
164 Rij_a_dvk_dxj[2] -= v_ab * mdWab_b.z();
166 Rij_a_dak_dxj[0] -= a_ab * mdWab_b.x();
167 Rij_a_dak_dxj[1] -= a_ab * mdWab_b.y();
168 Rij_a_dak_dxj[2] -= a_ab * mdWab_b.z();
173 std::array<Tvec, 3> invRij = shammath::compute_inv_33(Rij_a);
175 std::array<Tvec, 3> dvi_dxk = shammath::mat_prod_33(invRij, Rij_a_dvk_dxj);
176 std::array<Tvec, 3> dai_dxk = shammath::mat_prod_33(invRij, Rij_a_dak_dxj);
178 Tscal div_ai = dai_dxk[0].x() + dai_dxk[1].y() + dai_dxk[2].z();
179 Tscal div_vi = dvi_dxk[0].x() + dvi_dxk[1].y() + dvi_dxk[2].z();
181 = {dvi_dxk[1].z() - dvi_dxk[2].y(),
182 dvi_dxk[2].x() - dvi_dxk[0].z(),
183 dvi_dxk[0].y() - dvi_dxk[1].x()};
186 = dvi_dxk[0].x() * dvi_dxk[0].x() + dvi_dxk[1].x() * dvi_dxk[0].y()
187 + dvi_dxk[2].x() * dvi_dxk[0].z() + dvi_dxk[0].y() * dvi_dxk[1].x()
188 + dvi_dxk[1].y() * dvi_dxk[1].y() + dvi_dxk[2].y() * dvi_dxk[1].z()
189 + dvi_dxk[0].z() * dvi_dxk[2].x() + dvi_dxk[1].z() * dvi_dxk[2].y()
190 + dvi_dxk[2].z() * dvi_dxk[2].z();
194 dtdivv[id_a] = div_ai - tens_nablav;
200 buf_axyz.complete_event_state(e);
201 buf_hpart.complete_event_state(e);
202 buf_omega.complete_event_state(e);
203 buf_dtdivv.complete_event_state(e);
206 pcache.complete_event_state(resulting_events);
218 auto axyz = buf_axyz.get_read_access(depends_list);
219 auto hpart = buf_hpart.get_read_access(depends_list);
220 auto omega = buf_omega.get_read_access(depends_list);
221 auto divv = buf_divv.get_write_access(depends_list);
222 auto curlv = buf_curlv.get_write_access(depends_list);
223 auto dtdivv = buf_dtdivv.get_write_access(depends_list);
224 auto ploop_ptrs = pcache.get_read_access(depends_list);
226 auto e = queue.
submit(depends_list, [&](sycl::handler &cgh) {
227 const Tscal pmass = gpart_mass;
231 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
233 shambase::parallel_for(
234 cgh, pdat.get_obj_cnt(),
"compute dtdivv + divcurl v", [=](
i32 id_a) {
235 using namespace shamrock::sph;
237 Tvec sum_axyz = ZVEC;
239 Tscal h_a = hpart[id_a];
240 Tvec xyz_a = xyz[id_a];
241 Tvec vxyz_a = vxyz[id_a];
242 Tvec axyz_a = axyz[id_a];
243 Tscal omega_a = omega[id_a];
245 Tscal rho_a = rho_h(pmass, h_a, Kernel::hfactd);
248 Tscal inv_rho_omega_a = 1. / (omega_a * rho_a);
250 Tscal sum_nabla_a = 0;
252 std::array<Tvec, dim> Rij_a{ZVEC, ZVEC, ZVEC};
254 std::array<Tvec, dim> Rij_a_dvk_dxj{ZVEC, ZVEC, ZVEC};
255 std::array<Tvec, dim> Rij_a_dak_dxj{ZVEC, ZVEC, ZVEC};
257 Tscal sum_nabla_v = 0;
258 Tvec sum_nabla_cross_v{};
260 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
262 Tvec r_ab = xyz_a -
xyz[id_b];
263 Tscal rab2 = sycl::dot(r_ab, r_ab);
264 Tscal h_b =
hpart[id_b];
266 if (rab2 > h_a * h_a * Rker2 && rab2 > h_b * h_b * Rker2) {
270 Tscal rab = sycl::sqrt(rab2);
271 Tvec vxyz_b =
vxyz[id_b];
272 Tvec axyz_b =
axyz[id_b];
273 Tvec v_ab = vxyz_a - vxyz_b;
274 Tvec a_ab = axyz_a - axyz_b;
276 Tvec r_ab_unit = r_ab / rab;
282 Tvec dWab_a = Kernel::dW_3d(rab, h_a) * r_ab_unit;
284 Tvec mdWab_b = dWab_a * pmass;
286 static_assert(dim == 3,
"this is only implemented for dim 3");
287 Rij_a[0] -= r_ab.x() * mdWab_b;
288 Rij_a[1] -= r_ab.y() * mdWab_b;
289 Rij_a[2] -= r_ab.z() * mdWab_b;
291 Rij_a_dvk_dxj[0] -= v_ab * mdWab_b.x();
292 Rij_a_dvk_dxj[1] -= v_ab * mdWab_b.y();
293 Rij_a_dvk_dxj[2] -= v_ab * mdWab_b.z();
295 Rij_a_dak_dxj[0] -= a_ab * mdWab_b.x();
296 Rij_a_dak_dxj[1] -= a_ab * mdWab_b.y();
297 Rij_a_dak_dxj[2] -= a_ab * mdWab_b.z();
300 sum_nabla_v += pmass * sycl::dot(v_ab, dWab_a);
301 sum_nabla_cross_v += pmass * sycl::cross(v_ab, dWab_a);
304 std::array<Tvec, 3> invRij = shammath::compute_inv_33(Rij_a);
306 std::array<Tvec, 3> dvi_dxk = shammath::mat_prod_33(invRij, Rij_a_dvk_dxj);
307 std::array<Tvec, 3> dai_dxk = shammath::mat_prod_33(invRij, Rij_a_dak_dxj);
309 Tscal div_ai = dai_dxk[0].x() + dai_dxk[1].y() + dai_dxk[2].z();
310 Tscal div_vi = dvi_dxk[0].x() + dvi_dxk[1].y() + dvi_dxk[2].z();
312 = {dvi_dxk[1].z() - dvi_dxk[2].y(),
313 dvi_dxk[2].x() - dvi_dxk[0].z(),
314 dvi_dxk[0].y() - dvi_dxk[1].x()};
317 = dvi_dxk[0].x() * dvi_dxk[0].x() + dvi_dxk[1].x() * dvi_dxk[0].y()
318 + dvi_dxk[2].x() * dvi_dxk[0].z() + dvi_dxk[0].y() * dvi_dxk[1].x()
319 + dvi_dxk[1].y() * dvi_dxk[1].y() + dvi_dxk[2].y() * dvi_dxk[1].z()
320 + dvi_dxk[0].z() * dvi_dxk[2].x() + dvi_dxk[1].z() * dvi_dxk[2].y()
321 + dvi_dxk[2].z() * dvi_dxk[2].z();
325 divv[id_a] = -inv_rho_omega_a * sum_nabla_v;
326 curlv[id_a] = -inv_rho_omega_a * sum_nabla_cross_v;
327 dtdivv[id_a] = div_ai - tens_nablav;
333 buf_axyz.complete_event_state(e);
334 buf_hpart.complete_event_state(e);
335 buf_omega.complete_event_state(e);
336 buf_divv.complete_event_state(e);
337 buf_curlv.complete_event_state(e);
338 buf_dtdivv.complete_event_state(e);
341 pcache.complete_event_state(resulting_events);
constexpr const char * axyz
3-acceleration field
constexpr const char * vxyz
3-velocity field
constexpr const char * xyz
Position field (3D coordinates)
constexpr const char * hpart
Smoothing length field.
constexpr const char * omega
Grad-h correction factor \Omega.
std::uint32_t u32
32 bit unsigned integer
std::int32_t i32
32 bit integer
A buffer allocated in USM (Unified Shared Memory)
void complete_event_state(sycl::event e) const
Complete the event state of the buffer.
const T * get_read_access(sham::EventList &depends_list, SourceLocation src_loc=SourceLocation{}) const
Get a read-only pointer to the buffer's data.
A SYCL queue associated with a device and a context.
sycl::event submit(Fct &&fct)
Submits a kernel to the SYCL queue.
DeviceQueue & get_queue(u32 id=0)
Get a reference to a DeviceQueue.
Class to manage a list of SYCL events.
void add_event(sycl::event e)
Add an event to the list of events.
Represents a collection of objects distributed across patches identified by a u64 id.
T & get(u64 id)
Returns a reference to an object in the collection.
u32 get_field_idx(const std::string &field_name) const
Get the field id if matching name & type.
PatchDataLayer container class, the layout is described in patchdata_layout.
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...
namespace for math utility
namespace for the main framework
Patch object that contain generic patch information.
u64 id_patch
unique key that identify the patch