70template<
class Tvec,
template<
class>
class Kern>
71void shammodels::gsph::Solver<Tvec, Kern>::init_solver_graph() {
73 storage.part_counts = std::make_shared<shamrock::solvergraph::Indexes<u32>>(
74 edges::part_counts,
"N_{\\rm part}");
76 storage.part_counts_with_ghost = std::make_shared<shamrock::solvergraph::Indexes<u32>>(
77 edges::part_counts_with_ghost,
"N_{\\rm part, with ghost}");
79 storage.patch_rank_owner = std::make_shared<shamrock::solvergraph::RankGetter>(
81 return scheduler().get_patch_rank_owner(patch_id);
87 storage.positions_with_ghosts = std::make_shared<shamrock::solvergraph::FieldRefs<Tvec>>(
88 edges::positions_with_ghosts,
"\\mathbf{r}");
89 storage.hpart_with_ghosts
90 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(edges::hpart_with_ghosts,
"h");
93 = std::make_shared<shammodels::sph::solvergraph::NeighCache>(edges::neigh_cache,
"neigh");
96 storage.ghost_handler = storage.solver_graph.register_edge(
97 "ghost_handler", solvergraph::GhostHandlerEdge<Tvec>(
"ghost_handler",
"\\mathcal{G}"));
99 storage.omega = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"omega",
"\\Omega");
100 storage.density = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"density",
"\\rho");
101 storage.pressure = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"pressure",
"P");
103 = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"soundspeed",
"c_s");
108 = std::make_shared<shamrock::solvergraph::Field<Tvec>>(1,
"grad_density",
"\\nabla\\rho");
109 storage.grad_pressure
110 = std::make_shared<shamrock::solvergraph::Field<Tvec>>(1,
"grad_pressure",
"\\nabla P");
112 = std::make_shared<shamrock::solvergraph::Field<Tvec>>(1,
"grad_vx",
"\\nabla v_x");
114 = std::make_shared<shamrock::solvergraph::Field<Tvec>>(1,
"grad_vy",
"\\nabla v_y");
116 = std::make_shared<shamrock::solvergraph::Field<Tvec>>(1,
"grad_vz",
"\\nabla v_z");
119template<
class Tvec,
template<
class>
class Kern>
120void shammodels::gsph::Solver<Tvec, Kern>::vtk_do_dump(
121 std::string filename,
bool add_patch_world_id) {
123 modules::VTKDump<Tvec, Kern>(context, solver_config).do_dump(filename, add_patch_world_id);
126template<
class Tvec,
template<
class>
class Kern>
127void shammodels::gsph::Solver<Tvec, Kern>::gen_serial_patch_tree() {
131 _sptree.attach_buf();
132 storage.serial_patch_tree.set(std::move(_sptree));
135template<
class Tvec,
template<
class>
class Kern>
136void shammodels::gsph::Solver<Tvec, Kern>::gen_ghost_handler(Tscal time_val) {
139 using CfgClass = gsph::GSPHGhostHandlerConfig<Tvec>;
140 using BCConfig =
typename CfgClass::Variant;
142 using BCFree =
typename CfgClass::Free;
143 using BCPeriodic =
typename CfgClass::Periodic;
144 using BCShearingPeriodic =
typename CfgClass::ShearingPeriodic;
146 using SolverConfigBC =
typename Config::BCConfig;
147 using SolverBCFree =
typename SolverConfigBC::Free;
148 using SolverBCPeriodic =
typename SolverConfigBC::Periodic;
149 using SolverBCShearingPeriodic =
typename SolverConfigBC::ShearingPeriodic;
153 if (SolverBCFree *c = std::get_if<SolverBCFree>(&solver_config.boundary_config.config)) {
157 scheduler(), BCFree{}, storage.patch_rank_owner, storage.xyzh_ghost_layout});
160 = std::get_if<SolverBCPeriodic>(&solver_config.boundary_config.config)) {
166 storage.patch_rank_owner,
167 storage.xyzh_ghost_layout});
169 SolverBCShearingPeriodic *c
170 = std::get_if<SolverBCShearingPeriodic>(&solver_config.boundary_config.config)) {
177 c->shear_base, c->shear_dir, c->shear_speed * time_val, c->shear_speed},
178 storage.patch_rank_owner,
179 storage.xyzh_ghost_layout});
185template<
class Tvec,
template<
class>
class Kern>
186void shammodels::gsph::Solver<Tvec, Kern>::build_ghost_cache() {
189 using GSPHUtils = GSPHUtilities<Tvec, Kernel>;
190 GSPHUtils gsph_utils(scheduler());
196 Tscal h_evol_max = solver_config.htol_up_coarse_cycle;
197 if (solver_config.is_force_inutsuka_v2()) {
198 h_evol_max *= shambase::constants::sqrt_2<Tscal>;
201 storage.ghost_patch_cache.set(gsph_utils.build_interf_cache(
203 storage.serial_patch_tree.get(),
207template<
class Tvec,
template<
class>
class Kern>
208void shammodels::gsph::Solver<Tvec, Kern>::clear_ghost_cache() {
210 storage.ghost_patch_cache.reset();
213template<
class Tvec,
template<
class>
class Kern>
214void shammodels::gsph::Solver<Tvec, Kern>::merge_position_ghost() {
217 storage.merged_xyzh.set(
220 .build_comm_merge_positions(storage.ghost_patch_cache.get()));
224 = storage.xyzh_ghost_layout->template get_field_idx<Tvec>(gsph::names::common::xyz);
225 const u32 ihpart_ghost
226 = storage.xyzh_ghost_layout->template get_field_idx<Tscal>(gsph::names::common::hpart);
230 = storage.merged_xyzh.get().template map<u32>(
232 return scheduler().patch_data.get_pdat(
id).get_obj_cnt();
237 = storage.merged_xyzh.get().template map<u32>(
239 return mpdat.get_obj_cnt();
247 return std::ref(mpdat.get_field<Tvec>(ixyz_ghost));
254 return std::ref(mpdat.get_field<Tscal>(ihpart_ghost));
258template<
class Tvec,
template<
class>
class Kern>
259void shammodels::gsph::Solver<Tvec, Kern>::build_merged_pos_trees() {
262 auto &merged_xyzh = storage.merged_xyzh.get();
263 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
267 = storage.xyzh_ghost_layout->template get_field_idx<Tvec>(gsph::names::common::xyz);
272 Tvec bmax = pos.compute_max();
273 Tvec bmin = pos.compute_min();
277 Tscal infty = std::numeric_limits<Tscal>::infinity();
280 aabb.lower[0] = std::nextafter(aabb.lower[0], -infty);
281 aabb.lower[1] = std::nextafter(aabb.lower[1], -infty);
282 aabb.lower[2] = std::nextafter(aabb.lower[2], -infty);
283 aabb.upper[0] = std::nextafter(aabb.upper[0], infty);
284 aabb.upper[1] = std::nextafter(aabb.upper[1], infty);
285 aabb.upper[2] = std::nextafter(aabb.upper[2], infty);
287 auto bvh = RTree::make_empty(dev_sched);
288 bvh.rebuild_from_positions(
289 pos.get_buf(), pos.get_obj_cnt(), aabb, solver_config.tree_reduction_level);
294 storage.merged_pos_trees.set(std::move(trees));
297template<
class Tvec,
template<
class>
class Kern>
298void shammodels::gsph::Solver<Tvec, Kern>::clear_merged_pos_trees() {
300 storage.merged_pos_trees.reset();
303template<
class Tvec,
template<
class>
class Kern>
304void shammodels::gsph::Solver<Tvec, Kern>::compute_presteps_rint() {
307 auto &xyzh_merged = storage.merged_xyzh.get();
308 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
316 Tscal htol = solver_config.htol_up_coarse_cycle;
317 if (solver_config.is_force_inutsuka_v2()) {
318 htol *= shambase::constants::sqrt_2<Tscal>;
321 storage.rtree_rint_field.set(
324 shamrock::patch::PatchDataLayer &tmp = xyzh_merged.get(id);
325 auto &buf = tmp.get_field_buf_ref<Tscal>(1);
326 auto buf_int = shamtree::new_empty_karras_radix_tree_field<Tscal>();
328 auto ret = shamtree::compute_tree_field_max_field<Tscal>(
330 rtree.reduced_morton_set.get_leaf_cell_iterator(),
336 dev_sched->get_queue(),
339 ret.buf_field.get_size(),
340 [htol](
u32 i, Tscal *h_tree) {
344 return std::move(ret);
348template<
class Tvec,
template<
class>
class Kern>
349void shammodels::gsph::Solver<Tvec, Kern>::reset_presteps_rint() {
350 storage.rtree_rint_field.reset();
353template<
class Tvec,
template<
class>
class Kern>
354void shammodels::gsph::Solver<Tvec, Kern>::start_neighbors_cache() {
360 Tscal h_tolerance = solver_config.htol_up_coarse_cycle;
367 if (solver_config.is_force_inutsuka_v2()) {
368 h_tolerance *= shambase::constants::sqrt_2<Tscal>;
373 auto &mfield = storage.merged_xyzh.get().get(patch_id);
379 = storage.rtree_rint_field.get().get(patch_id).buf_field;
381 RTree &tree = storage.merged_pos_trees.get().get(patch_id);
382 auto obj_it = tree.get_object_iterator();
386 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
390 obj_cnt, shamsys::instance::get_compute_scheduler_ptr());
402 auto neigh_cnt = neigh_count.get_write_access(depends_list);
403 auto particle_looper = obj_it.get_read_access(depends_list);
405 auto e = q.
submit(depends_list, [&, h_tolerance](sycl::handler &cgh) {
406 shambase::parallel_for(cgh, obj_cnt,
"gsph_count_neighbors", [=](
u64 gid) {
409 Tscal rint_a =
hpart[id_a] * h_tolerance;
410 Tvec xyz_a =
xyz[id_a];
412 Tvec inter_box_a_min = xyz_a - rint_a * Kernel::Rkern;
413 Tvec inter_box_a_max = xyz_a + rint_a * Kernel::Rkern;
417 particle_looper.rtree_for(
419 Tscal int_r_max_cell = rint_tree[node_id] * Kernel::Rkern;
421 using namespace walker::interaction_crit;
423 return sph_radix_cell_crit(
432 Tvec dr = xyz_a -
xyz[id_b];
433 Tscal rab2 = sycl::dot(dr, dr);
434 Tscal rint_b =
hpart[id_b] * h_tolerance;
437 = rab2 > rint_a * rint_a * Rker2 && rab2 > rint_b * rint_b * Rker2;
439 cnt += (no_interact) ? 0 : 1;
442 neigh_cnt[id_a] = cnt;
448 neigh_count.complete_event_state(e);
450 obj_it.complete_event_state(e);
455 = shamrock::tree::prepare_object_cache(std::move(neigh_count), obj_cnt);
465 auto scanned_neigh_cnt = pcache.scanned_cnt.
get_read_access(depends_list);
467 auto particle_looper = obj_it.get_read_access(depends_list);
469 auto e = q.
submit(depends_list, [&, h_tolerance](sycl::handler &cgh) {
470 shambase::parallel_for(cgh, obj_cnt,
"gsph_fill_neighbors", [=](
u64 gid) {
473 Tscal rint_a =
hpart[id_a] * h_tolerance;
474 Tvec xyz_a =
xyz[id_a];
476 Tvec inter_box_a_min = xyz_a - rint_a * Kernel::Rkern;
477 Tvec inter_box_a_max = xyz_a + rint_a * Kernel::Rkern;
479 u32 write_idx = scanned_neigh_cnt[id_a];
481 particle_looper.rtree_for(
483 Tscal int_r_max_cell = rint_tree[node_id] * Kernel::Rkern;
485 using namespace walker::interaction_crit;
487 return sph_radix_cell_crit(
496 Tvec dr = xyz_a -
xyz[id_b];
497 Tscal rab2 = sycl::dot(dr, dr);
498 Tscal rint_b =
hpart[id_b] * h_tolerance;
501 = rab2 > rint_a * rint_a * Rker2 && rab2 > rint_b * rint_b * Rker2;
504 neigh[write_idx++] = id_b;
515 obj_it.complete_event_state(e);
523 using namespace shamrock::patch;
526 ncache.neigh_cache.add_obj(cur_p.
id_patch, build_neigh_cache(cur_p.
id_patch));
530 storage.timings_details.neighbors += time_neigh.
elapsed_sec();
533template<
class Tvec,
template<
class>
class Kern>
534void shammodels::gsph::Solver<Tvec, Kern>::reset_neighbors_cache() {
535 storage.neigh_cache->neigh_cache = {};
538template<
class Tvec,
template<
class>
class Kern>
539void shammodels::gsph::Solver<Tvec, Kern>::gsph_prestep(Tscal time_val, Tscal dt) {
542 shamlog_debug_ln(
"GSPH",
"Prestep at t =", time_val,
"dt =", dt);
545template<
class Tvec,
template<
class>
class Kern>
546void shammodels::gsph::Solver<Tvec, Kern>::apply_position_boundary(Tscal time_val) {
549 shamlog_debug_ln(
"GSPH",
"apply position boundary");
555 auto &pdl = sched.pdl_old();
556 const u32 ixyz = pdl.get_field_idx<Tvec>(gsph::names::common::xyz);
557 const u32 ivxyz = pdl.get_field_idx<Tvec>(gsph::names::newtonian::vxyz);
558 auto [bmin, bmax] = sched.get_box_volume<Tvec>();
560 using SolverConfigBC =
typename Config::BCConfig;
561 using SolverBCFree =
typename SolverConfigBC::Free;
562 using SolverBCPeriodic =
typename SolverConfigBC::Periodic;
563 using SolverBCShearingPeriodic =
typename SolverConfigBC::ShearingPeriodic;
565 if (SolverBCFree *c = std::get_if<SolverBCFree>(&solver_config.boundary_config.config)) {
567 logger::info_ln(
"PositionUpdated",
"free boundaries skipping geometry update");
571 = std::get_if<SolverBCPeriodic>(&solver_config.boundary_config.config)) {
572 integrators.fields_apply_periodicity(ixyz, std::pair{bmin, bmax});
574 SolverBCShearingPeriodic *c
575 = std::get_if<SolverBCShearingPeriodic>(&solver_config.boundary_config.config)) {
577 integrators.fields_apply_shearing_periodicity(
580 std::pair{bmin, bmax},
583 c->shear_speed * time_val,
589 reatrib.reatribute_patch_objects(storage.serial_patch_tree.get(), gsph::names::common::xyz);
592template<
class Tvec,
template<
class>
class Kern>
593void shammodels::gsph::Solver<Tvec, Kern>::do_predictor_leapfrog(Tscal dt) {
595 using namespace shamrock::patch;
602 const bool has_uint = solver_config.has_field_uint();
603 const u32 iuint = has_uint ? pdl.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
604 const u32 iduint = has_uint ? pdl.
get_field_idx<Tscal>(gsph::names::newtonian::duint) : 0;
606 Tscal half_dt = dt / 2;
610 u32 cnt = pdat.get_obj_cnt();
614 auto &xyz_field = pdat.get_field<Tvec>(ixyz);
615 auto &vxyz_field = pdat.get_field<Tvec>(ivxyz);
616 auto &axyz_field = pdat.get_field<Tvec>(iaxyz);
618 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
623 dev_sched->get_queue(),
627 [half_dt, dt](
u32 i,
const Tvec *axyz, Tvec *xyz, Tvec *vxyz) {
629 vxyz[i] += axyz[i] * half_dt;
631 xyz[i] += vxyz[i] * dt;
638 auto &uint_field = pdat.get_field<Tscal>(iuint);
639 auto &duint_field = pdat.get_field<Tscal>(iduint);
642 dev_sched->get_queue(),
646 [half_dt](
u32 i,
const Tscal *duint, Tscal *uint) {
648 uint[i] += duint[i] * half_dt;
654template<
class Tvec,
template<
class>
class Kern>
655void shammodels::gsph::Solver<Tvec, Kern>::init_ghost_layout() {
659 storage.xyzh_ghost_layout = std::make_shared<shamrock::patch::PatchDataLayerLayout>();
660 storage.xyzh_ghost_layout->template add_field<Tvec>(gsph::names::common::xyz, 1);
661 storage.xyzh_ghost_layout->template add_field<Tscal>(gsph::names::common::hpart, 1);
664 storage.ghost_layout = std::make_shared<shamrock::patch::PatchDataLayerLayout>();
669 solver_config.set_ghost_layout(ghost_layout);
672template<
class Tvec,
template<
class>
class Kern>
673void shammodels::gsph::Solver<Tvec, Kern>::communicate_merge_ghosts_fields() {
677 timer_interf.
start();
680 using namespace shamrock::patch;
687 const bool has_uint = solver_config.has_field_uint();
688 const u32 iuint = has_uint ? pdl.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
690 auto &ghost_layout_ptr = storage.ghost_layout;
692 u32 ihpart_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::common::hpart);
693 u32 ivxyz_interf = ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::vxyz);
694 u32 iomega_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::omega);
695 u32 idensity_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::density);
697 = has_uint ? ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
700 const bool has_grads = solver_config.requires_gradients();
702 = has_grads ? ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::grad_density) : 0;
704 = has_grads ? ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::grad_pressure) : 0;
706 = has_grads ? ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::grad_vx) : 0;
708 = has_grads ? ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::grad_vy) : 0;
710 = has_grads ? ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::grad_vz) : 0;
712 using InterfaceBuildInfos =
typename gsph::GSPHGhostHandler<Tvec>::InterfaceBuildInfos;
714 gsph::GSPHGhostHandler<Tvec> &ghost_handle
732 auto pdat_interf = ghost_handle.template build_interface_native<PatchDataLayer>(
733 storage.ghost_patch_cache.get(),
735 PatchDataLayer pdat(ghost_layout_ptr);
741 ghost_handle.template modify_interface_native<PatchDataLayer>(
742 storage.ghost_patch_cache.get(),
746 InterfaceBuildInfos binfo,
750 PatchDataLayer &sender_patch = scheduler().patch_data.get_pdat(sender);
751 PatchDataField<Tscal> &sender_omega = omega.get(sender);
752 PatchDataField<Tscal> &sender_density = density.get(sender);
754 sender_patch.get_field<Tscal>(ihpart).append_subset_to(
755 buf_idx, cnt, pdat.get_field<Tscal>(ihpart_interf));
756 sender_patch.get_field<Tvec>(ivxyz).append_subset_to(
757 buf_idx, cnt, pdat.get_field<Tvec>(ivxyz_interf));
758 sender_omega.append_subset_to(buf_idx, cnt, pdat.get_field<Tscal>(iomega_interf));
759 sender_density.append_subset_to(buf_idx, cnt, pdat.get_field<Tscal>(idensity_interf));
762 sender_patch.get_field<Tscal>(iuint).append_subset_to(
763 buf_idx, cnt, pdat.get_field<Tscal>(iuint_interf));
768 grad_density_ptr->get(sender).append_subset_to(
769 buf_idx, cnt, pdat.get_field<Tvec>(igrad_d_interf));
770 grad_pressure_ptr->get(sender).append_subset_to(
771 buf_idx, cnt, pdat.get_field<Tvec>(igrad_p_interf));
772 grad_vx_ptr->get(sender).append_subset_to(
773 buf_idx, cnt, pdat.get_field<Tvec>(igrad_vx_interf));
774 grad_vy_ptr->get(sender).append_subset_to(
775 buf_idx, cnt, pdat.get_field<Tvec>(igrad_vy_interf));
776 grad_vz_ptr->get(sender).append_subset_to(
777 buf_idx, cnt, pdat.get_field<Tvec>(igrad_vz_interf));
782 ghost_handle.template modify_interface_native<PatchDataLayer>(
783 storage.ghost_patch_cache.get(),
787 InterfaceBuildInfos binfo,
791 if (sycl::length(binfo.offset_speed) > 0) {
792 pdat.get_field<Tvec>(ivxyz_interf).apply_offset(binfo.offset_speed);
798 = ghost_handle.communicate_pdat(ghost_layout_ptr, std::move(pdat_interf));
801 std::map<u64, u64> sz_interf_map;
803 sz_interf_map[r] += pdat_interf.get_obj_cnt();
807 storage.merged_patchdata_ghost.set(
808 ghost_handle.template merge_native<PatchDataLayer, PatchDataLayer>(
809 std::move(interf_pdat),
811 PatchDataLayer pdat_new(ghost_layout_ptr);
813 u32 or_elem = pdat.get_obj_cnt();
814 pdat_new.reserve(or_elem + sz_interf_map[p.id_patch]);
816 PatchDataField<Tscal> &cur_omega = omega.get(p.id_patch);
817 PatchDataField<Tscal> &cur_density = density.get(p.id_patch);
820 pdat_new.get_field<Tscal>(ihpart_interf).insert(pdat.get_field<Tscal>(ihpart));
821 pdat_new.get_field<Tvec>(ivxyz_interf).insert(pdat.get_field<Tvec>(ivxyz));
822 pdat_new.get_field<Tscal>(iomega_interf).insert(cur_omega);
823 pdat_new.get_field<Tscal>(idensity_interf).insert(cur_density);
826 pdat_new.get_field<Tscal>(iuint_interf).insert(pdat.get_field<Tscal>(iuint));
831 pdat_new.get_field<Tvec>(igrad_d_interf)
832 .insert(grad_density_ptr->get(p.id_patch));
833 pdat_new.get_field<Tvec>(igrad_p_interf)
834 .insert(grad_pressure_ptr->get(p.id_patch));
835 pdat_new.get_field<Tvec>(igrad_vx_interf).insert(grad_vx_ptr->get(p.id_patch));
836 pdat_new.get_field<Tvec>(igrad_vy_interf).insert(grad_vy_ptr->get(p.id_patch));
837 pdat_new.get_field<Tvec>(igrad_vz_interf).insert(grad_vz_ptr->get(p.id_patch));
840 pdat_new.check_field_obj_cnt_match();
844 pdat.insert_elements(pdat_interf);
848 storage.timings_details.interface += timer_interf.
elapsed_sec();
851template<
class Tvec,
template<
class>
class Kern>
852void shammodels::gsph::Solver<Tvec, Kern>::reset_merge_ghosts_fields() {
853 storage.merged_patchdata_ghost.reset();
856template<
class Tvec,
template<
class>
class Kern>
857void shammodels::gsph::Solver<Tvec, Kern>::compute_omega() {
861 using namespace shamrock::patch;
863 const Tscal pmass = solver_config.gpart_mass;
867 if (pmass <= Tscal(0) || pmass < Tscal(1e-100) || !std::isfinite(pmass)) {
868 logger::warn_ln(
"GSPH",
"Invalid particle mass in compute_omega: pmass =", pmass);
876 std::shared_ptr<shamrock::solvergraph::Indexes<u32>>
sizes
877 = std::make_shared<shamrock::solvergraph::Indexes<u32>>(edges::sizes,
"N");
879 sizes->indexes.add_obj(p.id_patch, pdat.get_obj_cnt());
906 auto &merged_xyzh = storage.merged_xyzh.get();
910 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tvec>>
pos_merged
911 = std::make_shared<shamrock::solvergraph::FieldRefs<Tvec>>(edges::pos_merged,
"r");
915 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> hold
916 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(edges::h_old,
"h^{old}");
920 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> hnew
921 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(edges::h_new,
"h^{new}");
926 = storage.xyzh_ghost_layout->template get_field_idx<Tvec>(gsph::names::common::xyz);
927 const u32 ihpart_ghost
928 = storage.xyzh_ghost_layout->template get_field_idx<Tscal>(gsph::names::common::hpart);
931 scheduler().for_each_patchdata_nonempty(
933 auto &mfield = merged_xyzh.get(p.id_patch);
936 pos_refs.add_obj(p.id_patch, std::ref(mfield.template get_field<Tvec>(ixyz_ghost)));
939 hold_refs.add_obj(p.id_patch, std::ref(mfield.template get_field<Tscal>(ihpart_ghost)));
942 hnew_refs.add_obj(p.id_patch, std::ref(pdat.get_field<Tscal>(ihpart)));
946 hold->set_refs(hold_refs);
947 hnew->set_refs(hnew_refs);
950 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
952 u32 cnt = pdat.get_obj_cnt();
956 auto &mfield = merged_xyzh.get(p.id_patch);
957 auto &buf_hpart_merged = mfield.template get_field_buf_ref<Tscal>(1);
958 auto &buf_hpart_local = pdat.get_field_buf_ref<Tscal>(ihpart);
961 dev_sched->get_queue(),
965 [](
u32 i,
const Tscal *h_old, Tscal *h_new) {
976 u32 cnt = pdat.get_obj_cnt();
980 auto &eps_buf = _epsilon_h.get_buf_check(p.id_patch);
983 dev_sched->get_queue(),
987 [](
u32 i, Tscal *eps) {
993 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>>
eps_h
994 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(edges::eps_h,
"\\epsilon_h");
997 auto &field = _epsilon_h.get_field(p.id_patch);
998 eps_h_refs.add_obj(p.id_patch, std::ref(field));
1000 eps_h->set_refs(eps_h_refs);
1003 std::shared_ptr<sph::modules::IterateSmoothingLengthDensity<Tvec, Kernel>> smth_h_iter
1004 = std::make_shared<sph::modules::IterateSmoothingLengthDensity<Tvec, Kernel>>(
1005 solver_config.gpart_mass,
1006 solver_config.htol_up_coarse_cycle,
1007 solver_config.htol_up_fine_cycle);
1010 smth_h_iter->set_edges(sizes, storage.neigh_cache, pos_merged, hold, hnew, eps_h);
1013 std::shared_ptr<shamrock::solvergraph::ScalarEdge<bool>> is_converged
1014 = std::make_shared<shamrock::solvergraph::ScalarEdge<bool>>(
"is_converged",
"converged");
1018 smth_h_iter, solver_config.epsilon_h, solver_config.h_iter_per_subcycles,
false);
1019 loop_smth_h_iter.set_edges(eps_h, is_converged);
1022 loop_smth_h_iter.evaluate();
1025 if (!is_converged->value) {
1027 Tscal local_max_eps = shamrock::solvergraph::get_rank_max(*eps_h);
1028 Tscal global_max_eps = shamalgs::collective::allreduce_max(local_max_eps);
1031 u64 cnt_unconverged = 0;
1033 auto res = _epsilon_h.get_field(p.id_patch).get_ids_buf_where([](
auto access,
u32 id) {
1034 return access[id] < Tscal(0);
1036 cnt_unconverged += std::get<1>(res);
1038 u64 global_cnt_unconverged = shamalgs::collective::allreduce_sum(cnt_unconverged);
1041 if (global_cnt_unconverged > 0) {
1044 "Smoothing length iteration: ",
1045 global_cnt_unconverged,
1046 " particles need cache rebuild (h grew beyond tolerance)");
1050 "Smoothing length iteration did not converge, max eps =",
1063 static constexpr Tscal Rkern = Kernel::Rkern;
1065 auto &
neigh_cache = storage.neigh_cache->neigh_cache;
1068 u32 cnt = pdat.get_obj_cnt();
1072 auto &mfield = merged_xyzh.get(p.id_patch);
1076 auto &buf_xyz = mfield.template get_field_buf_ref<Tvec>(0);
1077 auto &buf_hpart = pdat.get_field_buf_ref<Tscal>(ihpart);
1080 auto &dens_field = density_field.
get_field(p.id_patch);
1081 auto &omeg_field = omega_field.
get_field(p.id_patch);
1086 auto ploop_ptrs = pcache.get_read_access(depends_list);
1089 auto density_acc = dens_field.get_buf().get_write_access(depends_list);
1090 auto omega_acc = omeg_field.get_buf().get_write_access(depends_list);
1092 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
1095 shambase::parallel_for(cgh, cnt,
"gsph_compute_density_omega", [=](
u64 gid) {
1098 Tvec xyz_a = xyz_acc[id_a];
1099 Tscal h_a = h_acc[id_a];
1100 Tscal dint = h_a * h_a * Rkern * Rkern;
1103 Tscal rho_sum = Tscal(0);
1104 Tscal sumdWdh = Tscal(0);
1106 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
1107 Tvec dr = xyz_a - xyz_acc[id_b];
1108 Tscal rab2 = sycl::dot(dr, dr);
1114 Tscal rab = sycl::sqrt(rab2);
1116 rho_sum += pmass * Kernel::W_3d(rab, h_a);
1117 sumdWdh += pmass * Kernel::dhW_3d(rab, h_a);
1121 density_acc[id_a] = sycl::max(rho_sum, Tscal(1e-30));
1127 Tscal omega_val = Tscal(1);
1128 if (rho_sum > Tscal(1e-30)) {
1129 omega_val = Tscal(1) + h_a / (Tscal(dim) * rho_sum) * sumdWdh;
1130 omega_val = sycl::clamp(omega_val, Tscal(0.5), Tscal(2.0));
1132 omega_acc[id_a] = omega_val;
1137 pcache.complete_event_state({e});
1140 dens_field.get_buf().complete_event_state(e);
1141 omeg_field.get_buf().complete_event_state(e);
1145template<
class Tvec,
template<
class>
class Kern>
1146void shammodels::gsph::Solver<Tvec, Kern>::compute_eos_fields() {
1150 using namespace shamrock::patch;
1156 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1157 const Tscal gamma = solver_config.get_eos_gamma();
1158 const bool has_uint = solver_config.has_field_uint();
1163 u32 idensity_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::density);
1165 = has_uint ? ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
1179 storage.merged_patchdata_ghost.get().for_each([&](
u64 id,
PatchDataLayer &mpdat) {
1182 if (total_elements == 0)
1187 auto &pressure_buf = pressure_field.
get_field(
id).get_buf();
1188 auto &soundspeed_buf = soundspeed_field.
get_field(
id).get_buf();
1194 auto pressure = pressure_buf.get_write_access(depends_list);
1195 auto soundspeed = soundspeed_buf.get_write_access(depends_list);
1197 const Tscal *uint_ptr =
nullptr;
1199 uint_ptr = mpdat.get_field_buf_ref<Tscal>(iuint_interf).get_read_access(depends_list);
1202 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
1203 shambase::parallel_for(cgh, total_elements,
"compute_eos_gsph", [=](
u64 gid) {
1208 rho = sycl::max(rho, Tscal(1e-30));
1210 if (has_uint && uint_ptr !=
nullptr) {
1213 Tscal u = uint_ptr[i];
1214 u = sycl::max(u, Tscal(1e-30));
1215 Tscal P = (gamma - Tscal(1.0)) * rho * u;
1219 Tscal cs = sycl::sqrt(gamma * (gamma - Tscal(1.0)) * u);
1222 P = sycl::clamp(P, Tscal(1e-30), Tscal(1e30));
1223 cs = sycl::clamp(cs, Tscal(1e-10), Tscal(1e10));
1229 Tscal cs = Tscal(1.0);
1230 Tscal P = cs * cs * rho;
1241 mpdat.get_field_buf_ref<Tscal>(iuint_interf).complete_event_state(e);
1243 pressure_buf.complete_event_state(e);
1244 soundspeed_buf.complete_event_state(e);
1248template<
class Tvec,
template<
class>
class Kern>
1249void shammodels::gsph::Solver<Tvec, Kern>::reset_eos_fields() {
1253template<
class Tvec,
template<
class>
class Kern>
1258 using namespace shamrock::patch;
1273 u32 npart = pdat.get_obj_cnt();
1288 auto &q = shamsys::instance::get_compute_scheduler().get_queue();
1291 auto rho_in = buf_rho_in.get_read_access(depends_list);
1295 auto P = buf_P.get_write_access(depends_list);
1296 auto cs = buf_cs.get_write_access(depends_list);
1298 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
1299 cgh.parallel_for(sycl::range<1>{npart}, [=](sycl::item<1> item) {
1300 rho[item] = rho_in[item];
1301 P[item] = P_in[item];
1302 cs[item] = cs_in[item];
1306 buf_rho_in.complete_event_state(e);
1310 buf_P.complete_event_state(e);
1311 buf_cs.complete_event_state(e);
1315template<
class Tvec,
template<
class>
class Kern>
1320 if (!solver_config.requires_gradients()) {
1325 using namespace shamrock::patch;
1327 const Tscal pmass = solver_config.gpart_mass;
1328 const Tscal gamma = solver_config.get_eos_gamma();
1330 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1335 const bool has_uint = solver_config.has_field_uint();
1359 auto &merged_xyzh = storage.merged_xyzh.get();
1360 auto &neigh_cache = storage.neigh_cache->neigh_cache;
1362 static constexpr Tscal Rkern = Kernel::Rkern;
1369 u32 cnt = pdat.get_obj_cnt();
1373 auto &mfield = merged_xyzh.get(p.id_patch);
1374 auto &pcache = neigh_cache.get(p.id_patch);
1377 auto &buf_xyz = mfield.template get_field_buf_ref<Tvec>(0);
1378 auto &buf_hpart = mfield.template get_field_buf_ref<Tscal>(1);
1379 auto &buf_vxyz = pdat.get_field_buf_ref<Tvec>(ivxyz);
1382 auto &dens_field = density_field.
get_field(p.id_patch);
1385 auto &grad_d_field = grad_density_field.
get_field(p.id_patch);
1386 auto &grad_p_field = grad_pressure_field.
get_field(p.id_patch);
1387 auto &grad_vx_buf = grad_vx_field.
get_field(p.id_patch);
1388 auto &grad_vy_buf = grad_vy_field.
get_field(p.id_patch);
1389 auto &grad_vz_buf = grad_vz_field.
get_field(p.id_patch);
1394 auto ploop_ptrs = pcache.get_read_access(depends_list);
1397 auto v_acc = buf_vxyz.get_read_access(depends_list);
1398 auto dens_acc = dens_field.get_buf().get_read_access(depends_list);
1399 auto grad_d_acc = grad_d_field.get_buf().get_write_access(depends_list);
1400 auto grad_p_acc = grad_p_field.get_buf().get_write_access(depends_list);
1401 auto grad_vx_acc = grad_vx_buf.get_buf().get_write_access(depends_list);
1402 auto grad_vy_acc = grad_vy_buf.get_buf().get_write_access(depends_list);
1403 auto grad_vz_acc = grad_vz_buf.get_buf().get_write_access(depends_list);
1406 const Tscal *uint_ptr =
nullptr;
1408 uint_ptr = pdat.get_field_buf_ref<Tscal>(iuint).get_read_access(depends_list);
1411 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
1414 shambase::parallel_for(cgh, cnt,
"gsph_compute_gradients", [=](
u64 gid) {
1417 Tvec xyz_a = xyz_acc[id_a];
1418 Tscal h_a = h_acc[id_a];
1419 Tvec v_a = v_acc[id_a];
1420 Tscal rho_a = sycl::max(dens_acc[id_a], Tscal(1e-30));
1421 Tscal dint = h_a * h_a * Rkern * Rkern;
1424 Tscal u_a = Tscal(0);
1425 if (uint_ptr !=
nullptr) {
1426 u_a = uint_ptr[id_a];
1430 Tvec grad_d = {0, 0, 0};
1431 Tvec grad_u = {0, 0, 0};
1432 Tvec grad_vx = {0, 0, 0};
1433 Tvec grad_vy = {0, 0, 0};
1434 Tvec grad_vz = {0, 0, 0};
1436 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
1437 Tvec dr = xyz_a - xyz_acc[id_b];
1438 Tscal rab2 = sycl::dot(dr, dr);
1440 if (rab2 > dint || id_a == id_b) {
1444 Tscal rab = sycl::sqrt(rab2);
1447 Tscal dWdr = Kernel::dW_3d(rab, h_a);
1451 grad_d += gradW * pmass;
1454 Tscal u_b = (uint_ptr !=
nullptr) ? uint_ptr[id_b] : Tscal(0);
1455 grad_u += gradW * (pmass * (u_b - u_a));
1458 Tvec v_b = v_acc[id_b];
1459 grad_vx += gradW * (pmass * (v_b[0] - v_a[0]));
1460 grad_vy += gradW * (pmass * (v_b[1] - v_a[1]));
1461 grad_vz += gradW * (pmass * (v_b[2] - v_a[2]));
1465 grad_d_acc[id_a] = grad_d;
1469 Tvec grad_p = (grad_d * u_a + grad_u) * (gamma - Tscal(1));
1470 grad_p_acc[id_a] = grad_p;
1475 grad_vx_acc[id_a] = grad_vx * rho_inv;
1476 grad_vy_acc[id_a] = grad_vy * rho_inv;
1477 grad_vz_acc[id_a] = grad_vz * rho_inv;
1482 pcache.complete_event_state({e});
1485 buf_vxyz.complete_event_state(e);
1486 dens_field.get_buf().complete_event_state(e);
1487 grad_d_field.get_buf().complete_event_state(e);
1488 grad_p_field.get_buf().complete_event_state(e);
1489 grad_vx_buf.get_buf().complete_event_state(e);
1490 grad_vy_buf.get_buf().complete_event_state(e);
1491 grad_vz_buf.get_buf().complete_event_state(e);
1493 pdat.get_field_buf_ref<Tscal>(iuint).complete_event_state(e);
1498template<
class Tvec,
template<
class>
class Kern>
1499void shammodels::gsph::Solver<Tvec, Kern>::prepare_corrector() {
1511 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1513 scheduler().for_each_patchdata_nonempty(
1515 u32 cnt = pdat.get_obj_cnt();
1519 auto &axyz_field = pdat.get_field<Tvec>(iaxyz);
1520 auto &old_axyz_field = old_axyz.get_field(p.id_patch);
1524 dev_sched->get_queue(),
1528 [](
u32 i,
const Tvec *src, Tvec *dst) {
1533 storage.old_axyz.set(std::move(old_axyz));
1535 if (solver_config.has_field_uint()) {
1536 const u32 iduint = pdl.
get_field_idx<Tscal>(gsph::names::newtonian::duint);
1537 auto old_duint = utility.make_compute_field<Tscal>(gsph::names::internal::old_duint, 1);
1539 scheduler().for_each_patchdata_nonempty(
1541 u32 cnt = pdat.get_obj_cnt();
1545 auto &duint_field = pdat.get_field<Tscal>(iduint);
1546 auto &old_duint_field = old_duint.get_field(p.id_patch);
1550 dev_sched->get_queue(),
1554 [](
u32 i,
const Tscal *src, Tscal *dst) {
1559 storage.old_duint.set(std::move(old_duint));
1563template<
class Tvec,
template<
class>
class Kern>
1570template<
class Tvec,
template<
class>
class Kern>
1576 using namespace shamrock::patch;
1578 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1587 Tscal C_cour = solver_config.cfl_config.cfl_cour;
1588 Tscal C_force = solver_config.cfl_config.cfl_force;
1595 u32 cnt = pdat.get_obj_cnt();
1599 auto &buf_hpart = pdat.get_field_buf_ref<Tscal>(ihpart);
1600 auto &buf_axyz = pdat.get_field_buf_ref<Tvec>(iaxyz);
1601 auto &buf_cs = soundspeed_field.get_field(cur_p.
id_patch).get_buf();
1602 auto &cfl_dt_buf = cfl_dt.get_buf_check(cur_p.
id_patch);
1608 auto axyz = buf_axyz.get_read_access(depends_list);
1609 auto cs = buf_cs.get_read_access(depends_list);
1610 auto cfl_dt_acc = cfl_dt_buf.get_write_access(depends_list);
1612 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
1613 shambase::parallel_for(cgh, cnt,
"gsph_compute_cfl_dt", [=](
u64 gid) {
1616 Tscal h_i = hpart[i];
1618 Tscal abs_a = sycl::length(axyz[i]);
1621 if (!sycl::isfinite(h_i) || h_i <= Tscal(0))
1623 if (!sycl::isfinite(cs_i) || cs_i <= Tscal(0))
1624 cs_i = Tscal(1e-10);
1625 if (!sycl::isfinite(abs_a))
1626 abs_a = Tscal(1e30);
1630 Tscal dt_c = C_cour * h_i / cs_i;
1633 Tscal dt_f = C_force * sycl::sqrt(h_i / (abs_a + Tscal(1e-30)));
1635 Tscal dt_min = sycl::min(dt_c, dt_f);
1638 if (!sycl::isfinite(dt_min) || dt_min <= Tscal(0)) {
1639 dt_min = Tscal(1e-10);
1642 cfl_dt_acc[i] = dt_min;
1647 buf_axyz.complete_event_state(e);
1648 buf_cs.complete_event_state(e);
1649 cfl_dt_buf.complete_event_state(e);
1653 Tscal rank_dt = cfl_dt.compute_rank_min();
1656 if (!std::isfinite(rank_dt) || rank_dt <= Tscal(0)) {
1657 rank_dt = Tscal(1e-6);
1661 Tscal global_min_dt = shamalgs::collective::allreduce_min(rank_dt);
1666 const Tscal dt_min_floor = Tscal(1e-6);
1667 if (!std::isfinite(global_min_dt) || global_min_dt < dt_min_floor) {
1668 global_min_dt = dt_min_floor;
1671 return global_min_dt;
1674template<
class Tvec,
template<
class>
class Kern>
1675bool shammodels::gsph::Solver<Tvec, Kern>::apply_corrector(Tscal dt,
u64 Npart_all) {
1683 Tscal half_dt = Tscal{0.5} * dt;
1687 scheduler().for_each_patchdata_nonempty(
1689 u32 cnt = pdat.get_obj_cnt();
1693 auto &vxyz = pdat.get_field<Tvec>(ivxyz);
1694 auto &axyz = pdat.get_field<Tvec>(iaxyz);
1696 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1699 dev_sched->get_queue(),
1703 [half_dt](
u32 i,
const Tvec *axyz_new, Tvec *vxyz) {
1704 vxyz[i] += half_dt * axyz_new[i];
1708 if (solver_config.has_field_uint()) {
1710 const u32 iduint = pdl.
get_field_idx<Tscal>(gsph::names::newtonian::duint);
1712 scheduler().for_each_patchdata_nonempty(
1714 u32 cnt = pdat.get_obj_cnt();
1718 auto &uint_field = pdat.get_field<Tscal>(iuint);
1719 auto &
duint = pdat.get_field<Tscal>(iduint);
1721 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1725 dev_sched->get_queue(),
1729 [half_dt](
u32 i,
const Tscal *duint_new, Tscal *uint) {
1730 uint[i] += half_dt * duint_new[i];
1734 storage.old_duint.reset();
1737 storage.old_axyz.reset();
1742template<
class Tvec,
template<
class>
class Kern>
1743void shammodels::gsph::Solver<Tvec, Kern>::update_sync_load_values() {}
1745template<
class Tvec,
template<
class>
class Kern>
1749 solver_config.check_config_runtime();
1751 Tscal t_current = get_time();
1752 Tscal dt = get_dt();
1759 "---------------- GSPH t = {}, dt = {} ----------------", t_current, dt));
1766 scheduler().scheduler_step(
true,
true);
1767 scheduler().scheduler_step(
false,
false);
1772 using namespace shamrock::patch;
1774 u64 Npart_all = scheduler().get_total_obj_count();
1795 do_predictor_leapfrog(dt);
1799 gen_serial_patch_tree();
1800 apply_position_boundary(t_current + dt);
1804 gen_ghost_handler(t_current + dt);
1807 build_ghost_cache();
1810 merge_position_ghost();
1813 build_merged_pos_trees();
1816 compute_presteps_rint();
1819 start_neighbors_cache();
1832 init_ghost_layout();
1836 communicate_merge_ghosts_fields();
1841 compute_eos_fields();
1845 prepare_corrector();
1851 apply_corrector(dt, Npart_all);
1857 if (dt > Tscal(0)) {
1858 dt_next = sham::min(dt_next, Tscal(2) * dt);
1865 reset_neighbors_cache();
1866 reset_presteps_rint();
1867 clear_merged_pos_trees();
1868 reset_merge_ghosts_fields();
1869 storage.merged_xyzh.reset();
1870 clear_ghost_cache();
1871 reset_serial_patch_tree();
1872 reset_ghost_handler();
1873 storage.ghost_layout.reset();
1876 set_time(t_current + dt);
1877 set_next_dt(dt_next);
1879 solve_logs.step_count++;
1886 log.rate = Tscal(Npart_all) / tstep.
elapsed_sec();
1887 log.npart = Npart_all;
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 * pos_merged
Position merged references (for h-iteration).
constexpr const char * old_axyz
Old acceleration (for corrector step).
constexpr const char * xyz
Position field (3D coordinates).
constexpr const char * density
Density \rho (derived from h).
constexpr const char * eps_h
Epsilon h references (for h-iteration convergence).
constexpr const char * sizes
Temporary sizes for h-iteration.
constexpr const char * soundspeed
Sound speed c_s (derived from EOS).
constexpr const char * pressure
Pressure P (derived from EOS).
constexpr const char * hpart
Smoothing length field.
constexpr const char * neigh_cache
Neighbor cache.
constexpr const char * omega
Grad-h correction factor \Omega.
GSPH-specific utilities for ghost handling.
shambase::DistributedData< PatchDataFieldRef< T > > DDPatchDataFieldRef
Alias for a DistributedData of PatchDataFieldRefs.
Declares the IterateSmoothingLengthDensity module for iterating smoothing length based on the SPH den...
Declares the LoopSmoothingLengthIter module for looping over the smoothing length iteration until con...
Header file describing a Node Instance.
sycl::queue & get_compute_queue(u32 id=0)
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
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.
Container for objects shared between two distributed data elements.
void for_each(std::function< void(u64, u64, T &)> &&f)
Apply a function to all stored objects.
Represents a collection of objects distributed across patches identified by a u64 id.
Class Timer measures the time elapsed since the timer was started.
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.
void copy_eos_to_patchdata()
Copy EOS fields from solvergraph to patchdata for persistence.
void compute_gradients()
Compute gradients for MUSCL reconstruction.
TimestepLog evolve_once()
void update_derivs()
Update derivatives using GSPH Riemann solver.
Tscal compute_dt_cfl()
Compute CFL timestep constraint.
GSPH derivative update module.
void update_derivs()
Update all derivatives using GSPH Riemann solver approach.
Utility class used to move the objects between patches.
ComputeField< T > make_compute_field(std::string new_name, u32 nvar)
create a compute field and init it to zeros
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.
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...
PatchDataField< T > & get_field(u64 id) const
Get the underlying PatchDataField at the given id.
A data structure representing a Karras Radix Tree Field.
Class holding the value of numerous constants generated from the following source.
This header file contains utility functions related to exception handling in the code.
MPI string gather / allgather helpers (declarations; implementations in shamalgs/src/collective/gathe...
Configuration for the Godunov SPH (GSPH) solver.
GSPH derivative update module.
VTK dump module for GSPH solver.
T inv_sat_positive(T v, T minvsat=T{1e-9}, T satval=T{0.}) noexcept
inverse saturated (positive numbers only)
void kernel_call(sham::DeviceQueue &q, RefIn in, RefOut in_out, u32 n, Functor &&func, SourceLocation &&callsite=SourceLocation{})
Submit a kernel to a SYCL queue.
void throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.
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...
i32 world_rank()
Gives the rank of the current process in the MPI communicator.
namespace for math utility
namespace for the main framework
void raw_ln(Types... var2)
Prints a log message with multiple arguments followed by a newline.
void info_ln(std::string module_name, Types... var2)
Prints a log message with multiple arguments followed by a newline.
void warn_ln(std::string module_name, Types... var2)
Prints a log message with multiple arguments followed by a newline.
shambase::details::BasicStackEntry StackEntry
Alias for shambase::details::BasicStackEntry.
A class that references multiple buffers or similar objects.
Axis-Aligned bounding box.
T lower
Lower bound of the AABB.
T upper
Upper bound of the AABB.
Patch object that contain generic patch information.
u64 id_patch
unique key that identify the patch
Functions related to the MPI communicator.