41template<
class Tvec,
template<
class>
class SPHKernel>
45 Cfg_Riemann cfg_riemann = solver_config.riemann_config;
47 if (Iterative *v = std::get_if<Iterative>(&cfg_riemann.config)) {
48 update_derivs_iterative(*v);
49 }
else if (HLLC *v = std::get_if<HLLC>(&cfg_riemann.config)) {
50 update_derivs_hllc(*v);
51 }
else if (Exact *v = std::get_if<Exact>(&cfg_riemann.config)) {
52 update_derivs_exact(*v);
58template<
class Tvec,
template<
class>
class SPHKernel>
59void shammodels::gsph::modules::UpdateDerivs<Tvec, SPHKernel>::update_derivs_iterative(
65 using namespace shamrock::patch;
76 const bool has_uint = solver_config.has_field_uint();
91 auto &merged_xyzh = storage.merged_xyzh.get();
106 = merged_xyzh.get(cur_p.
id_patch).template get_field_buf_ref<Tvec>(0);
129 auto vxyz = buf_vxyz.get_read_access(depends_list);
130 auto hpart = buf_hpart.get_read_access(depends_list);
131 auto omega_acc = buf_omega.get_read_access(depends_list);
133 auto pressure_acc = buf_pressure.get_read_access(depends_list);
135 auto ploop_ptrs = pcache.get_read_access(depends_list);
139 Tscal *duint_acc =
nullptr;
141 buf_duint_ptr = &pdat.get_field_buf_ref<Tscal>(iduint);
145 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
146 const Tscal pmass = solver_config.gpart_mass;
147 const Tscal gamma = solver_config.get_eos_gamma();
148 const Tscal tol = cfg.tol;
149 const u32 max_iter = cfg.max_iter;
150 const bool do_energy = has_uint;
151 const bool use_inutsuka_v2 = solver_config.is_force_inutsuka_v2();
156 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
162 const Tscal Rker2_factor = use_inutsuka_v2 ? Tscal{2} : Tscal{1};
164 shambase::parallel_for(cgh, pdat.get_obj_cnt(),
"GSPH derivs iterative", [=](
u64 gid) {
165 u32 id_a = (u32) gid;
167 using namespace shamrock::sph;
170 Tvec sum_axyz = {0, 0, 0};
174 const Tscal h_a = hpart[id_a];
175 const Tvec xyz_a = xyz[id_a];
176 const Tvec vxyz_a = vxyz[id_a];
177 const Tscal omega_a = omega_acc[id_a];
180 const Tscal rho_a = sycl::max(density_acc[id_a], Tscal(1e-30));
183 const Tscal P_a = sycl::max(pressure_acc[id_a], Tscal(1e-30));
184 const Tscal cs_a = sycl::max(cs_acc[id_a], Tscal(1e-10));
187 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
192 const Tvec dr = xyz_a -
xyz[id_b];
193 const Tscal rab2 = sycl::dot(dr, dr);
194 const Tscal h_b =
hpart[id_b];
197 if (rab2 > h_a * h_a * Rker2 * Rker2_factor
198 && rab2 > h_b * h_b * Rker2 * Rker2_factor) {
202 const Tscal rab = sycl::sqrt(rab2);
203 const Tvec vxyz_b =
vxyz[id_b];
204 const Tscal omega_b = omega_acc[id_b];
207 const Tscal rho_b = sycl::max(density_acc[id_b], Tscal(1e-30));
210 const Tscal P_b = sycl::max(pressure_acc[id_b], Tscal(1e-30));
211 const Tscal cs_b = sycl::max(cs_acc[id_b], Tscal(1e-10));
215 const Tvec r_ab_unit = dr * rab_inv;
218 const Tscal u_a_proj = sycl::dot(vxyz_a, r_ab_unit);
219 const Tscal u_b_proj = sycl::dot(vxyz_b, r_ab_unit);
223 auto riemann_result = riemann::iterative_solver<Tscal>(
233 const Tscal p_star = riemann_result.p_star;
234 const Tscal v_star = riemann_result.v_star;
256 axyz[id_a] = sum_axyz;
257 if (duint_acc !=
nullptr) {
258 duint_acc[id_a] = sum_du_a;
266 buf_vxyz.complete_event_state(e);
267 buf_hpart.complete_event_state(e);
268 buf_omega.complete_event_state(e);
270 buf_pressure.complete_event_state(e);
273 if (has_uint && buf_duint_ptr) {
279 pcache.complete_event_state(resulting_events);
283template<
class Tvec,
template<
class>
class SPHKernel>
284void shammodels::gsph::modules::UpdateDerivs<Tvec, SPHKernel>::update_derivs_exact(Exact cfg) {
289 using namespace shamrock::patch;
300 const bool has_uint = solver_config.has_field_uint();
301 const u32 iuint = has_uint ? pdl.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
302 const u32 iduint = has_uint ? pdl.
get_field_idx<Tscal>(gsph::names::newtonian::duint) : 0;
307 u32 ihpart_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::common::hpart);
308 u32 ivxyz_interf = ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::vxyz);
309 u32 iomega_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::omega);
310 u32 idensity_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::density);
312 = has_uint ? ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
315 auto &merged_xyzh = storage.merged_xyzh.get();
330 = merged_xyzh.get(cur_p.
id_patch).template get_field_buf_ref<Tvec>(0);
353 auto vxyz = buf_vxyz.get_read_access(depends_list);
354 auto hpart = buf_hpart.get_read_access(depends_list);
355 auto omega_acc = buf_omega.get_read_access(depends_list);
357 auto pressure_acc = buf_pressure.get_read_access(depends_list);
359 auto ploop_ptrs = pcache.get_read_access(depends_list);
363 Tscal *duint_acc =
nullptr;
365 buf_duint_ptr = &pdat.get_field_buf_ref<Tscal>(iduint);
369 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
370 const Tscal pmass = solver_config.gpart_mass;
371 const Tscal gamma = solver_config.get_eos_gamma();
372 const Tscal tol = cfg.tol;
373 const u32 max_iter = cfg.max_iter;
374 const bool do_energy = has_uint;
375 const bool use_inutsuka_v2 = solver_config.is_force_inutsuka_v2();
380 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
386 const Tscal Rker2_factor = use_inutsuka_v2 ? Tscal{2} : Tscal{1};
388 shambase::parallel_for(cgh, pdat.get_obj_cnt(),
"GSPH derivs exact", [=](
u64 gid) {
389 u32 id_a = (u32) gid;
391 using namespace shamrock::sph;
394 Tvec sum_axyz = {0, 0, 0};
398 const Tscal h_a = hpart[id_a];
399 const Tvec xyz_a = xyz[id_a];
400 const Tvec vxyz_a = vxyz[id_a];
401 const Tscal omega_a = omega_acc[id_a];
404 const Tscal rho_a = sycl::max(density_acc[id_a], Tscal(1e-30));
407 const Tscal P_a = sycl::max(pressure_acc[id_a], Tscal(1e-30));
408 const Tscal cs_a = sycl::max(cs_acc[id_a], Tscal(1e-10));
411 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
416 const Tvec dr = xyz_a -
xyz[id_b];
417 const Tscal rab2 = sycl::dot(dr, dr);
418 const Tscal h_b =
hpart[id_b];
421 if (rab2 > h_a * h_a * Rker2 * Rker2_factor
422 && rab2 > h_b * h_b * Rker2 * Rker2_factor) {
426 const Tscal rab = sycl::sqrt(rab2);
427 const Tvec vxyz_b =
vxyz[id_b];
428 const Tscal omega_b = omega_acc[id_b];
431 const Tscal rho_b = sycl::max(density_acc[id_b], Tscal(1e-30));
434 const Tscal P_b = sycl::max(pressure_acc[id_b], Tscal(1e-30));
435 const Tscal cs_b = sycl::max(cs_acc[id_b], Tscal(1e-10));
439 const Tvec r_ab_unit = dr * rab_inv;
442 const Tscal u_a_proj = sycl::dot(vxyz_a, r_ab_unit);
443 const Tscal u_b_proj = sycl::dot(vxyz_b, r_ab_unit);
447 auto riemann_result = riemann::exact_solver<Tscal>(
457 const Tscal p_star = riemann_result.p_star;
458 const Tscal v_star = riemann_result.v_star;
480 axyz[id_a] = sum_axyz;
481 if (duint_acc !=
nullptr) {
482 duint_acc[id_a] = sum_du_a;
490 buf_vxyz.complete_event_state(e);
491 buf_hpart.complete_event_state(e);
492 buf_omega.complete_event_state(e);
494 buf_pressure.complete_event_state(e);
497 if (has_uint && buf_duint_ptr) {
503 pcache.complete_event_state(resulting_events);
507template<
class Tvec,
template<
class>
class SPHKernel>
508void shammodels::gsph::modules::UpdateDerivs<Tvec, SPHKernel>::update_derivs_hllc(HLLC cfg) {
513 using namespace shamrock::patch;
523 const bool has_uint = solver_config.has_field_uint();
524 const u32 iuint = has_uint ? pdl.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
525 const u32 iduint = has_uint ? pdl.
get_field_idx<Tscal>(gsph::names::newtonian::duint) : 0;
530 u32 ihpart_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::common::hpart);
531 u32 ivxyz_interf = ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::vxyz);
532 u32 iomega_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::omega);
533 u32 idensity_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::density);
535 = has_uint ? ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
537 auto &merged_xyzh = storage.merged_xyzh.get();
550 = merged_xyzh.get(cur_p.
id_patch).template get_field_buf_ref<Tvec>(0);
570 auto vxyz = buf_vxyz.get_read_access(depends_list);
571 auto hpart = buf_hpart.get_read_access(depends_list);
572 auto omega_acc = buf_omega.get_read_access(depends_list);
574 auto pressure_acc = buf_pressure.get_read_access(depends_list);
576 auto ploop_ptrs = pcache.get_read_access(depends_list);
579 Tscal *duint_acc =
nullptr;
581 buf_duint_ptr = &pdat.get_field_buf_ref<Tscal>(iduint);
585 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
586 const Tscal pmass = solver_config.gpart_mass;
587 const Tscal gamma = solver_config.get_eos_gamma();
588 const bool do_energy = has_uint;
592 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
594 shambase::parallel_for(cgh, pdat.get_obj_cnt(),
"GSPH derivs HLLC", [=](
u64 gid) {
595 u32 id_a = (u32) gid;
597 using namespace shamrock::sph;
599 Tvec sum_axyz = {0, 0, 0};
602 const Tscal h_a = hpart[id_a];
603 const Tvec xyz_a = xyz[id_a];
604 const Tvec vxyz_a = vxyz[id_a];
605 const Tscal omega_a = omega_acc[id_a];
608 const Tscal rho_a = sycl::max(density_acc[id_a], Tscal(1e-30));
611 const Tscal P_a = sycl::max(pressure_acc[id_a], Tscal(1e-30));
612 const Tscal cs_a = sycl::max(cs_acc[id_a], Tscal(1e-10));
614 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
618 const Tvec dr = xyz_a -
xyz[id_b];
619 const Tscal rab2 = sycl::dot(dr, dr);
620 const Tscal h_b =
hpart[id_b];
622 if (rab2 > h_a * h_a * Rker2 && rab2 > h_b * h_b * Rker2) {
626 const Tscal rab = sycl::sqrt(rab2);
627 const Tvec vxyz_b =
vxyz[id_b];
628 const Tscal omega_b = omega_acc[id_b];
631 const Tscal rho_b = sycl::max(density_acc[id_b], Tscal(1e-30));
634 const Tscal P_b = sycl::max(pressure_acc[id_b], Tscal(1e-30));
635 const Tscal cs_b = sycl::max(cs_acc[id_b], Tscal(1e-10));
638 const Tvec r_ab_unit = dr * rab_inv;
641 const Tscal u_a_proj = sycl::dot(vxyz_a, r_ab_unit);
642 const Tscal u_b_proj = sycl::dot(vxyz_b, r_ab_unit);
646 auto riemann_result = riemann::hllc_solver<Tscal>(
654 const Tscal p_star = riemann_result.p_star;
655 const Tscal v_star = riemann_result.v_star;
657 const Tscal Fab_a = Kernel::dW_3d(rab, h_a);
658 const Tscal Fab_b = Kernel::dW_3d(rab, h_b);
677 axyz[id_a] = sum_axyz;
678 if (duint_acc !=
nullptr) {
679 duint_acc[id_a] = sum_du_a;
686 buf_vxyz.complete_event_state(e);
687 buf_hpart.complete_event_state(e);
688 buf_omega.complete_event_state(e);
690 buf_pressure.complete_event_state(e);
693 if (has_uint && buf_duint_ptr) {
699 pcache.complete_event_state(resulting_events);
Constants for field names in GSPH solver, organized by physics mode.
constexpr const char * duint
Time derivative of internal energy du/dt.
constexpr const char * axyz
3-acceleration field
constexpr const char * uint
Specific internal energy u.
constexpr const char * vxyz
3-velocity field
constexpr const char * xyz
Position field (3D coordinates).
constexpr const char * density
Density \rho (derived from h).
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::uint64_t u64
64 bit unsigned integer
A buffer allocated in USM (Unified Shared Memory).
void complete_event_state(sycl::event e) const
Complete the event state of the buffer.
T * get_write_access(sham::EventList &depends_list, SourceLocation src_loc=SourceLocation{})
Get a read-write pointer to the buffer's data.
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.
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.
GSPH derivative update module.
void update_derivs()
Update all derivatives using GSPH Riemann solver approach.
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.
PatchDataField< T > & get_field(u64 id) const
Get the underlying PatchDataField at the given id.
Exact Riemann solver for GSPH (Toro 2009).
GSPH force computation using Riemann solver results.
void accumulate_gsph_pair_force(bool use_inutsuka_v2, Tscal pmass, Tscal p_star, Tscal v_star, Tscal rho_a, Tscal rho_b, Tscal omega_a, Tscal omega_b, Tscal rab, Tscal rab_inv, Tscal h_a, Tscal h_b, Tvec r_ab_unit, Tvec vxyz_a, Tvec &sum_axyz, Tscal &sum_du_a)
Dispatch a single neighbor pair's force contribution to ChaWhitworth or InutsukaV2,...
void add_gsph_force_contribution(Tscal m_b, Tscal p_star, Tscal v_star, Tscal rho_a, Tscal rho_b, Tscal omega_a, Tscal omega_b, Tscal Fab_a, Tscal Fab_b, Tvec r_ab_unit, Tvec v_a, Tvec &dv_dt, Tscal &du_dt)
Add GSPH force contribution from a single neighbor pair.
GSPH derivative update module.
Iterative Riemann solver for GSPH (van Leer 1997).
T inv_sat_positive(T v, T minvsat=T{1e-9}, T satval=T{0.}) noexcept
inverse saturated (positive numbers only)
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...
void throw_unimplemented(SourceLocation loc=SourceLocation{})
Throw a std::runtime_error saying that the function is unimplemented.
namespace for math utility
namespace for the main framework
Effective face (volume element) interpolation for the Inutsuka (2002) GSPH formulation.
shambase::details::BasicStackEntry StackEntry
Alias for shambase::details::BasicStackEntry.
Patch object that contain generic patch information.
u64 id_patch
unique key that identify the patch