74template<
class Tvec,
template<
class>
class Kern>
75void shammodels::gsph::Solver<Tvec, Kern>::init_solver_graph() {
77 storage.part_counts = std::make_shared<shamrock::solvergraph::Indexes<u32>>(
78 edges::part_counts,
"N_{\\rm part}");
80 storage.part_counts_with_ghost = std::make_shared<shamrock::solvergraph::Indexes<u32>>(
81 edges::part_counts_with_ghost,
"N_{\\rm part, with ghost}");
83 storage.patch_rank_owner = std::make_shared<shamrock::solvergraph::RankGetter>(
85 return scheduler().get_patch_rank_owner(patch_id);
91 storage.positions_with_ghosts = std::make_shared<shamrock::solvergraph::FieldRefs<Tvec>>(
92 edges::positions_with_ghosts,
"\\mathbf{r}");
93 storage.hpart_with_ghosts
94 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(edges::hpart_with_ghosts,
"h");
97 = std::make_shared<shammodels::sph::solvergraph::NeighCache>(edges::neigh_cache,
"neigh");
100 storage.ghost_handler = storage.solver_graph.register_edge(
101 "ghost_handler", solvergraph::GhostHandlerEdge<Tvec>(
"ghost_handler",
"\\mathcal{G}"));
103 storage.omega = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"omega",
"\\Omega");
104 storage.density = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"density",
"\\rho");
105 storage.pressure = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"pressure",
"P");
107 = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"soundspeed",
"c_s");
112 = std::make_shared<shamrock::solvergraph::Field<Tvec>>(1,
"grad_density",
"\\nabla\\rho");
113 storage.grad_pressure
114 = std::make_shared<shamrock::solvergraph::Field<Tvec>>(1,
"grad_pressure",
"\\nabla P");
116 = std::make_shared<shamrock::solvergraph::Field<Tvec>>(1,
"grad_vx",
"\\nabla v_x");
118 = std::make_shared<shamrock::solvergraph::Field<Tvec>>(1,
"grad_vy",
"\\nabla v_y");
120 = std::make_shared<shamrock::solvergraph::Field<Tvec>>(1,
"grad_vz",
"\\nabla v_z");
123template<
class Tvec,
template<
class>
class Kern>
124void shammodels::gsph::Solver<Tvec, Kern>::vtk_do_dump(
125 std::string filename,
bool add_patch_world_id) {
127 modules::VTKDump<Tvec, Kern>(context, solver_config).do_dump(filename, add_patch_world_id);
130template<
class Tvec,
template<
class>
class Kern>
131void shammodels::gsph::Solver<Tvec, Kern>::gen_serial_patch_tree() {
135 _sptree.attach_buf();
136 storage.serial_patch_tree.set(std::move(_sptree));
139template<
class Tvec,
template<
class>
class Kern>
140void shammodels::gsph::Solver<Tvec, Kern>::gen_ghost_handler(Tscal time_val) {
143 using CfgClass = gsph::GSPHGhostHandlerConfig<Tvec>;
144 using BCConfig =
typename CfgClass::Variant;
146 using BCFree =
typename CfgClass::Free;
147 using BCPeriodic =
typename CfgClass::Periodic;
148 using BCShearingPeriodic =
typename CfgClass::ShearingPeriodic;
150 using SolverConfigBC =
typename Config::BCConfig;
151 using SolverBCFree =
typename SolverConfigBC::Free;
152 using SolverBCPeriodic =
typename SolverConfigBC::Periodic;
153 using SolverBCShearingPeriodic =
typename SolverConfigBC::ShearingPeriodic;
157 if (SolverBCFree *c = std::get_if<SolverBCFree>(&solver_config.boundary_config.config)) {
161 scheduler(), BCFree{}, storage.patch_rank_owner, storage.xyzh_ghost_layout});
164 = std::get_if<SolverBCPeriodic>(&solver_config.boundary_config.config)) {
170 storage.patch_rank_owner,
171 storage.xyzh_ghost_layout});
173 SolverBCShearingPeriodic *c
174 = std::get_if<SolverBCShearingPeriodic>(&solver_config.boundary_config.config)) {
181 c->shear_base, c->shear_dir, c->shear_speed * time_val, c->shear_speed},
182 storage.patch_rank_owner,
183 storage.xyzh_ghost_layout});
189template<
class Tvec,
template<
class>
class Kern>
190void shammodels::gsph::Solver<Tvec, Kern>::build_ghost_cache() {
193 using GSPHUtils = GSPHUtilities<Tvec, Kernel>;
194 GSPHUtils gsph_utils(scheduler());
200 Tscal h_evol_max = solver_config.htol_up_coarse_cycle;
201 if (solver_config.is_force_inutsuka_v2()) {
202 h_evol_max *= shambase::constants::sqrt_2<Tscal>;
205 storage.ghost_patch_cache.set(gsph_utils.build_interf_cache(
207 storage.serial_patch_tree.get(),
211template<
class Tvec,
template<
class>
class Kern>
212void shammodels::gsph::Solver<Tvec, Kern>::clear_ghost_cache() {
214 storage.ghost_patch_cache.reset();
217template<
class Tvec,
template<
class>
class Kern>
218void shammodels::gsph::Solver<Tvec, Kern>::merge_position_ghost() {
221 storage.merged_xyzh.set(
224 .build_comm_merge_positions(storage.ghost_patch_cache.get()));
228 = storage.xyzh_ghost_layout->template get_field_idx<Tvec>(gsph::names::common::xyz);
229 const u32 ihpart_ghost
230 = storage.xyzh_ghost_layout->template get_field_idx<Tscal>(gsph::names::common::hpart);
234 = storage.merged_xyzh.get().template map<u32>(
236 return scheduler().patch_data.get_pdat(
id).get_obj_cnt();
241 = storage.merged_xyzh.get().template map<u32>(
251 return std::ref(mpdat.get_field<Tvec>(ixyz_ghost));
258 return std::ref(mpdat.get_field<Tscal>(ihpart_ghost));
262template<
class Tvec,
template<
class>
class Kern>
263void shammodels::gsph::Solver<Tvec, Kern>::build_merged_pos_trees() {
266 auto &merged_xyzh = storage.merged_xyzh.get();
267 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
271 = storage.xyzh_ghost_layout->template get_field_idx<Tvec>(gsph::names::common::xyz);
276 Tvec bmax = pos.compute_max();
277 Tvec bmin = pos.compute_min();
281 Tscal infty = std::numeric_limits<Tscal>::infinity();
284 aabb.lower[0] = std::nextafter(aabb.lower[0], -infty);
285 aabb.lower[1] = std::nextafter(aabb.lower[1], -infty);
286 aabb.lower[2] = std::nextafter(aabb.lower[2], -infty);
287 aabb.upper[0] = std::nextafter(aabb.upper[0], infty);
288 aabb.upper[1] = std::nextafter(aabb.upper[1], infty);
289 aabb.upper[2] = std::nextafter(aabb.upper[2], infty);
291 auto bvh = RTree::make_empty(dev_sched);
292 bvh.rebuild_from_positions(
293 pos.get_buf(), pos.get_obj_cnt(), aabb, solver_config.tree_reduction_level);
298 storage.merged_pos_trees.set(std::move(trees));
301template<
class Tvec,
template<
class>
class Kern>
302void shammodels::gsph::Solver<Tvec, Kern>::clear_merged_pos_trees() {
304 storage.merged_pos_trees.reset();
307template<
class Tvec,
template<
class>
class Kern>
308void shammodels::gsph::Solver<Tvec, Kern>::compute_presteps_rint() {
311 auto &xyzh_merged = storage.merged_xyzh.get();
312 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
320 Tscal htol = solver_config.htol_up_coarse_cycle;
321 if (solver_config.is_force_inutsuka_v2()) {
322 htol *= shambase::constants::sqrt_2<Tscal>;
325 storage.rtree_rint_field.set(
328 shamrock::patch::PatchDataLayer &tmp = xyzh_merged.get(id);
329 auto &buf = tmp.get_field_buf_ref<Tscal>(1);
330 auto buf_int = shamtree::new_empty_karras_radix_tree_field<Tscal>();
332 auto ret = shamtree::compute_tree_field_max_field<Tscal>(
334 rtree.reduced_morton_set.get_leaf_cell_iterator(),
340 dev_sched->get_queue(),
343 ret.buf_field.get_size(),
344 [htol](
u32 i, Tscal *h_tree) {
348 return std::move(ret);
352template<
class Tvec,
template<
class>
class Kern>
353void shammodels::gsph::Solver<Tvec, Kern>::reset_presteps_rint() {
354 storage.rtree_rint_field.reset();
357template<
class Tvec,
template<
class>
class Kern>
358void shammodels::gsph::Solver<Tvec, Kern>::start_neighbors_cache() {
364 Tscal h_tolerance = solver_config.htol_up_coarse_cycle;
371 if (solver_config.is_force_inutsuka_v2()) {
372 h_tolerance *= shambase::constants::sqrt_2<Tscal>;
377 auto &mfield = storage.merged_xyzh.get().get(patch_id);
383 = storage.rtree_rint_field.get().get(patch_id).buf_field;
385 RTree &tree = storage.merged_pos_trees.get().get(patch_id);
386 auto obj_it = tree.get_object_iterator();
390 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
394 obj_cnt, shamsys::instance::get_compute_scheduler_ptr());
406 auto neigh_cnt = neigh_count.get_write_access(depends_list);
407 auto particle_looper = obj_it.get_read_access(depends_list);
409 auto e = q.
submit(depends_list, [&, h_tolerance](sycl::handler &cgh) {
410 shambase::parallel_for(cgh, obj_cnt,
"gsph_count_neighbors", [=](
u64 gid) {
413 Tscal rint_a =
hpart[id_a] * h_tolerance;
414 Tvec xyz_a =
xyz[id_a];
416 Tvec inter_box_a_min = xyz_a - rint_a * Kernel::Rkern;
417 Tvec inter_box_a_max = xyz_a + rint_a * Kernel::Rkern;
421 particle_looper.rtree_for(
423 Tscal int_r_max_cell = rint_tree[node_id] * Kernel::Rkern;
425 using namespace walker::interaction_crit;
427 return sph_radix_cell_crit(
436 Tvec dr = xyz_a -
xyz[id_b];
437 Tscal rab2 = sycl::dot(dr, dr);
438 Tscal rint_b =
hpart[id_b] * h_tolerance;
441 = rab2 > rint_a * rint_a * Rker2 && rab2 > rint_b * rint_b * Rker2;
443 cnt += (no_interact) ? 0 : 1;
446 neigh_cnt[id_a] = cnt;
452 neigh_count.complete_event_state(e);
454 obj_it.complete_event_state(e);
459 = shamrock::tree::prepare_object_cache(std::move(neigh_count), obj_cnt);
469 auto scanned_neigh_cnt = pcache.scanned_cnt.
get_read_access(depends_list);
471 auto particle_looper = obj_it.get_read_access(depends_list);
473 auto e = q.
submit(depends_list, [&, h_tolerance](sycl::handler &cgh) {
474 shambase::parallel_for(cgh, obj_cnt,
"gsph_fill_neighbors", [=](
u64 gid) {
477 Tscal rint_a =
hpart[id_a] * h_tolerance;
478 Tvec xyz_a =
xyz[id_a];
480 Tvec inter_box_a_min = xyz_a - rint_a * Kernel::Rkern;
481 Tvec inter_box_a_max = xyz_a + rint_a * Kernel::Rkern;
483 u32 write_idx = scanned_neigh_cnt[id_a];
485 particle_looper.rtree_for(
487 Tscal int_r_max_cell = rint_tree[node_id] * Kernel::Rkern;
489 using namespace walker::interaction_crit;
491 return sph_radix_cell_crit(
500 Tvec dr = xyz_a -
xyz[id_b];
501 Tscal rab2 = sycl::dot(dr, dr);
502 Tscal rint_b =
hpart[id_b] * h_tolerance;
505 = rab2 > rint_a * rint_a * Rker2 && rab2 > rint_b * rint_b * Rker2;
508 neigh[write_idx++] = id_b;
519 obj_it.complete_event_state(e);
527 using namespace shamrock::patch;
530 ncache.neigh_cache.add_obj(cur_p.
id_patch, build_neigh_cache(cur_p.
id_patch));
534 storage.timings_details.neighbors += time_neigh.
elapsed_sec();
537template<
class Tvec,
template<
class>
class Kern>
538void shammodels::gsph::Solver<Tvec, Kern>::reset_neighbors_cache() {
539 storage.neigh_cache->neigh_cache = {};
542template<
class Tvec,
template<
class>
class Kern>
547 using namespace shamrock::patch;
549 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
550 const Tscal pmass = solver_config.gpart_mass;
551 static constexpr Tscal Rkern = Kernel::Rkern;
555 "invalid gpart_mass 0 in compute_density, this configuration can not converge.");
568 auto &merged_xyzh = storage.merged_xyzh.get();
569 auto &neigh_cache = storage.neigh_cache->neigh_cache;
576 auto &mfield = merged_xyzh.get(p.id_patch);
577 auto &pcache = neigh_cache.get(p.id_patch);
580 auto &buf_xyz = mfield.template get_field_buf_ref<Tvec>(0);
581 auto &buf_hpart = pdat.get_field_buf_ref<Tscal>(ihpart);
583 auto &dens_field = density_field.
get_field(p.id_patch);
588 auto ploop_ptrs = pcache.get_read_access(depends_list);
591 auto density_acc = dens_field.get_buf().get_write_access(depends_list);
593 auto e = q.
submit(depends_list, [&, pmass](sycl::handler &cgh) {
596 shambase::parallel_for(cgh, cnt,
"gsph_compute_density", [=](
u64 gid) {
599 Tvec xyz_a = xyz_acc[id_a];
600 Tscal h_a = h_acc[id_a];
601 Tscal dint = h_a * h_a * Rkern * Rkern;
605 Tscal rho_sum = pmass * Kernel::W_3d(Tscal(0), h_a);
607 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
612 Tvec dr = xyz_a - xyz_acc[id_b];
613 Tscal rab2 = sycl::dot(dr, dr);
619 Tscal rab = sycl::sqrt(rab2);
620 rho_sum += pmass * Kernel::W_3d(rab, h_a);
623 density_acc[id_a] = sycl::max(rho_sum, Tscal(1e-30));
627 pcache.complete_event_state({e});
630 dens_field.get_buf().complete_event_state(e);
634template<
class Tvec,
template<
class>
class Kern>
635void shammodels::gsph::Solver<Tvec, Kern>::gsph_prestep(Tscal time_val, Tscal dt) {
638 shamlog_debug_ln(
"GSPH",
"Prestep at t =", time_val,
"dt =", dt);
641 using namespace shamrock::patch;
646 SPHUtils sph_utils(scheduler());
654 auto should_set_omega_mask = std::make_shared<shamrock::solvergraph::Field<u32>>(
655 1,
"should_set_omega_mask",
"should_set_omega_mask");
658 u32 hstep_max = solver_config.h_max_subcycles_count;
659 for (; hstep_cnt < hstep_max; hstep_cnt++) {
661 gen_ghost_handler(time_val + dt);
663 merge_position_ghost();
664 build_merged_pos_trees();
665 compute_presteps_rint();
666 start_neighbors_cache();
668 _epsilon_h = utility.make_compute_field<Tscal>(
"epsilon_h", 1, Tscal(100));
669 _h_old = utility.save_field<Tscal>(ihpart,
"h_old");
673 if (solver_config.gpart_mass == 0) {
675 "invalid gpart_mass {}, this configuration can not converge.\n"
676 "Please set it using either model.set_particle_mass(pmass) or "
677 "cfg.set_particle_mass(pmass)",
678 solver_config.gpart_mass));
682 std::shared_ptr<shamrock::solvergraph::Indexes<u32>> sizes
683 = std::make_shared<shamrock::solvergraph::Indexes<u32>>(
"",
"");
685 sizes->indexes.add_obj(p.id_patch, pdat.
get_obj_cnt());
692 auto &
pos_merged = storage.positions_with_ghosts;
695 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> hold
696 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"",
"");
699 auto &field = _h_old.get_field(p.id_patch);
700 hold_refs.add_obj(p.id_patch, std::ref(field));
702 hold->set_refs(hold_refs);
705 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> hnew
706 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"",
"");
709 auto &field = pdat.get_field<Tscal>(ihpart);
710 hnew_refs.add_obj(p.id_patch, std::ref(field));
712 hnew->set_refs(hnew_refs);
715 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>>
eps_h
716 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"",
"");
719 auto &field = _epsilon_h.get_field(p.id_patch);
720 eps_h_refs.add_obj(p.id_patch, std::ref(field));
722 eps_h->set_refs(eps_h_refs);
724 std::shared_ptr<shamrock::solvergraph::INode> smth_h_iter_ptr;
726 using h_conf_density_based =
typename gsph::SmoothingLengthConfig::DensityBased;
727 using h_conf_neigh_lim =
typename gsph::SmoothingLengthConfig::DensityBasedNeighLim;
729 if (h_conf_density_based *conf
730 = std::get_if<h_conf_density_based>(&solver_config.smoothing_length_config.config)) {
731 std::shared_ptr<shammodels::sph::modules::IterateSmoothingLengthDensity<Tvec, Kernel>>
732 smth_h_iter = std::make_shared<
734 solver_config.gpart_mass,
735 solver_config.htol_up_coarse_cycle,
736 solver_config.htol_up_fine_cycle,
737 solver_config.epsilon_h);
738 smth_h_iter->set_edges(sizes, neigh_cache, pos_merged, hold, hnew, eps_h);
739 smth_h_iter_ptr = smth_h_iter;
741 h_conf_neigh_lim *conf
742 = std::get_if<h_conf_neigh_lim>(&solver_config.smoothing_length_config.config)) {
745 smth_h_iter_neigh_lim = std::make_shared<
747 solver_config.gpart_mass,
748 solver_config.htol_up_coarse_cycle,
749 solver_config.htol_up_fine_cycle,
750 conf->max_neigh_count,
751 solver_config.epsilon_h);
752 smth_h_iter_neigh_lim->set_edges(
753 sizes, neigh_cache, pos_merged, hold, hnew, eps_h, should_set_omega_mask);
754 smth_h_iter_ptr = smth_h_iter_neigh_lim;
760 std::shared_ptr<shamrock::solvergraph::IDataEdge<bool>> is_converged
761 = shamrock::solvergraph::IDataEdge<bool>::make_shared(
"",
"");
764 smth_h_iter_ptr, solver_config.epsilon_h, solver_config.h_iter_per_subcycles,
false);
765 loop_smth_h_iter.set_edges(eps_h, is_converged);
767 loop_smth_h_iter.evaluate();
769 if (!is_converged->data) {
774 largest_h = sham::max(largest_h, pdat.get_field<Tscal>(ihpart).compute_max());
776 Tscal global_largest_h = shamalgs::collective::allreduce_max(largest_h);
778 std::string add_info =
"";
779 u64 cnt_unconverged = 0;
782 = _epsilon_h.get_field(p.id_patch).get_ids_buf_where([](
auto access,
u32 id) {
783 return access[id] == -1;
786 if (hstep_cnt == hstep_max - 1) {
787 if (std::get<0>(res)) {
788 add_info +=
"\n patch " + std::to_string(p.id_patch) +
" ";
789 add_info +=
"errored parts : \n";
790 sycl::buffer<u32> &idx_err = *std::get<0>(res);
795 auto pos =
xyz.copy_to_stdvec();
796 auto h =
hpart.copy_to_stdvec();
799 sycl::host_accessor acc{idx_err};
800 for (
u32 i = 0; i < idx_err.size(); i++) {
801 add_info += sham::format(
802 "{} - pos : {}, hpart : {}\n", acc[i], pos[acc[i]], h[acc[i]]);
808 cnt_unconverged += std::get<1>(res);
811 u64 global_cnt_unconverged = shamalgs::collective::allreduce_sum(cnt_unconverged);
816 "smoothing length is not converged, rerunning the iterator ...\n largest h "
820 global_cnt_unconverged,
824 reset_ghost_handler();
832 storage.merged_xyzh.reset();
834 clear_merged_pos_trees();
835 reset_presteps_rint();
836 reset_neighbors_cache();
853 if (hstep_cnt == hstep_max) {
854 logger::err_ln(
"GSPH",
"the h iterator is not converged after", hstep_cnt,
"iterations");
857 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> hnew_edge
858 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"",
"");
861 auto &field = pdat.get_field<Tscal>(ihpart);
862 hnew_refs.add_obj(p.id_patch, std::ref(field));
864 hnew_edge->set_refs(hnew_refs);
866 sph::modules::NodeComputeOmega<Tvec, Kern> compute_omega{solver_config.gpart_mass};
867 compute_omega.set_edges(
870 storage.positions_with_ghosts,
873 compute_omega.evaluate();
875 if (solver_config.smoothing_length_config.is_density_based_neigh_lim()) {
879 sph::modules::SetWhenMask<Tscal> set_omega_mask{1};
880 set_omega_mask.set_edges(storage.part_counts, should_set_omega_mask, storage.omega);
881 set_omega_mask.evaluate();
891template<
class Tvec,
template<
class>
class Kern>
892void shammodels::gsph::Solver<Tvec, Kern>::apply_position_boundary(Tscal time_val) {
895 shamlog_debug_ln(
"GSPH",
"apply position boundary");
901 auto &pdl = sched.pdl_old();
904 auto [bmin, bmax] = sched.get_box_volume<Tvec>();
906 using SolverConfigBC =
typename Config::BCConfig;
907 using SolverBCFree =
typename SolverConfigBC::Free;
908 using SolverBCPeriodic =
typename SolverConfigBC::Periodic;
909 using SolverBCShearingPeriodic =
typename SolverConfigBC::ShearingPeriodic;
911 if (SolverBCFree *c = std::get_if<SolverBCFree>(&solver_config.boundary_config.config)) {
913 logger::info_ln(
"PositionUpdated",
"free boundaries skipping geometry update");
917 = std::get_if<SolverBCPeriodic>(&solver_config.boundary_config.config)) {
918 integrators.fields_apply_periodicity(ixyz, std::pair{bmin, bmax});
920 SolverBCShearingPeriodic *c
921 = std::get_if<SolverBCShearingPeriodic>(&solver_config.boundary_config.config)) {
923 integrators.fields_apply_shearing_periodicity(
926 std::pair{bmin, bmax},
929 c->shear_speed * time_val,
935 reatrib.reatribute_patch_objects(storage.serial_patch_tree.get(), gsph::names::common::xyz);
938template<
class Tvec,
template<
class>
class Kern>
939void shammodels::gsph::Solver<Tvec, Kern>::do_predictor_leapfrog(Tscal dt) {
941 using namespace shamrock::patch;
948 const bool has_uint = solver_config.has_field_uint();
949 const u32 iuint = has_uint ? pdl.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
950 const u32 iduint = has_uint ? pdl.
get_field_idx<Tscal>(gsph::names::newtonian::duint) : 0;
952 Tscal half_dt = dt / 2;
960 auto &xyz_field = pdat.get_field<Tvec>(ixyz);
961 auto &vxyz_field = pdat.get_field<Tvec>(ivxyz);
962 auto &axyz_field = pdat.get_field<Tvec>(iaxyz);
964 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
969 dev_sched->get_queue(),
973 [half_dt, dt](
u32 i,
const Tvec *axyz, Tvec *xyz, Tvec *vxyz) {
975 vxyz[i] += axyz[i] * half_dt;
977 xyz[i] += vxyz[i] * dt;
984 auto &uint_field = pdat.get_field<Tscal>(iuint);
985 auto &duint_field = pdat.get_field<Tscal>(iduint);
988 dev_sched->get_queue(),
992 [half_dt](
u32 i,
const Tscal *duint, Tscal *uint) {
994 uint[i] += duint[i] * half_dt;
1000template<
class Tvec,
template<
class>
class Kern>
1001void shammodels::gsph::Solver<Tvec, Kern>::init_ghost_layout() {
1005 storage.xyzh_ghost_layout = std::make_shared<shamrock::patch::PatchDataLayerLayout>();
1006 storage.xyzh_ghost_layout->template add_field<Tvec>(gsph::names::common::xyz, 1);
1007 storage.xyzh_ghost_layout->template add_field<Tscal>(gsph::names::common::hpart, 1);
1010 storage.ghost_layout = std::make_shared<shamrock::patch::PatchDataLayerLayout>();
1015 solver_config.set_ghost_layout(ghost_layout);
1018template<
class Tvec,
template<
class>
class Kern>
1019void shammodels::gsph::Solver<Tvec, Kern>::communicate_merge_ghosts_fields() {
1023 timer_interf.
start();
1026 using namespace shamrock::patch;
1033 const bool has_uint = solver_config.has_field_uint();
1034 const u32 iuint = has_uint ? pdl.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
1036 auto &ghost_layout_ptr = storage.ghost_layout;
1038 u32 ihpart_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::common::hpart);
1039 u32 ivxyz_interf = ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::vxyz);
1040 u32 iomega_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::omega);
1041 u32 idensity_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::density);
1043 = has_uint ? ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
1046 const bool has_grads = solver_config.requires_gradients();
1048 = has_grads ? ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::grad_density) : 0;
1050 = has_grads ? ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::grad_pressure) : 0;
1052 = has_grads ? ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::grad_vx) : 0;
1054 = has_grads ? ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::grad_vy) : 0;
1056 = has_grads ? ghost_layout.
get_field_idx<Tvec>(gsph::names::newtonian::grad_vz) : 0;
1058 using InterfaceBuildInfos =
typename gsph::GSPHGhostHandler<Tvec>::InterfaceBuildInfos;
1060 gsph::GSPHGhostHandler<Tvec> &ghost_handle
1078 auto pdat_interf = ghost_handle.template build_interface_native<PatchDataLayer>(
1079 storage.ghost_patch_cache.get(),
1081 PatchDataLayer pdat(ghost_layout_ptr);
1087 ghost_handle.template modify_interface_native<PatchDataLayer>(
1088 storage.ghost_patch_cache.get(),
1092 InterfaceBuildInfos binfo,
1096 PatchDataLayer &sender_patch = scheduler().patch_data.get_pdat(sender);
1097 PatchDataField<Tscal> &sender_omega = omega.get(sender);
1098 PatchDataField<Tscal> &sender_density = density.get(sender);
1100 sender_patch.get_field<Tscal>(ihpart).append_subset_to(
1101 buf_idx, cnt, pdat.get_field<Tscal>(ihpart_interf));
1102 sender_patch.get_field<Tvec>(ivxyz).append_subset_to(
1103 buf_idx, cnt, pdat.get_field<Tvec>(ivxyz_interf));
1104 sender_omega.append_subset_to(buf_idx, cnt, pdat.get_field<Tscal>(iomega_interf));
1105 sender_density.append_subset_to(buf_idx, cnt, pdat.get_field<Tscal>(idensity_interf));
1108 sender_patch.get_field<Tscal>(iuint).append_subset_to(
1109 buf_idx, cnt, pdat.get_field<Tscal>(iuint_interf));
1114 grad_density_ptr->get(sender).append_subset_to(
1115 buf_idx, cnt, pdat.get_field<Tvec>(igrad_d_interf));
1116 grad_pressure_ptr->get(sender).append_subset_to(
1117 buf_idx, cnt, pdat.get_field<Tvec>(igrad_p_interf));
1118 grad_vx_ptr->get(sender).append_subset_to(
1119 buf_idx, cnt, pdat.get_field<Tvec>(igrad_vx_interf));
1120 grad_vy_ptr->get(sender).append_subset_to(
1121 buf_idx, cnt, pdat.get_field<Tvec>(igrad_vy_interf));
1122 grad_vz_ptr->get(sender).append_subset_to(
1123 buf_idx, cnt, pdat.get_field<Tvec>(igrad_vz_interf));
1128 ghost_handle.template modify_interface_native<PatchDataLayer>(
1129 storage.ghost_patch_cache.get(),
1133 InterfaceBuildInfos binfo,
1137 if (sycl::length(binfo.offset_speed) > 0) {
1138 pdat.get_field<Tvec>(ivxyz_interf).apply_offset(binfo.offset_speed);
1144 = ghost_handle.communicate_pdat(ghost_layout_ptr, std::move(pdat_interf));
1147 std::map<u64, u64> sz_interf_map;
1153 storage.merged_patchdata_ghost.set(
1154 ghost_handle.template merge_native<PatchDataLayer, PatchDataLayer>(
1155 std::move(interf_pdat),
1157 PatchDataLayer pdat_new(ghost_layout_ptr);
1159 u32 or_elem = pdat.get_obj_cnt();
1160 pdat_new.reserve(or_elem + sz_interf_map[p.id_patch]);
1162 PatchDataField<Tscal> &cur_omega = omega.get(p.id_patch);
1163 PatchDataField<Tscal> &cur_density = density.get(p.id_patch);
1166 pdat_new.get_field<Tscal>(ihpart_interf).insert(pdat.get_field<Tscal>(ihpart));
1167 pdat_new.get_field<Tvec>(ivxyz_interf).insert(pdat.get_field<Tvec>(ivxyz));
1168 pdat_new.get_field<Tscal>(iomega_interf).insert(cur_omega);
1169 pdat_new.get_field<Tscal>(idensity_interf).insert(cur_density);
1172 pdat_new.get_field<Tscal>(iuint_interf).insert(pdat.get_field<Tscal>(iuint));
1177 pdat_new.get_field<Tvec>(igrad_d_interf)
1178 .insert(grad_density_ptr->get(p.id_patch));
1179 pdat_new.get_field<Tvec>(igrad_p_interf)
1180 .insert(grad_pressure_ptr->get(p.id_patch));
1181 pdat_new.get_field<Tvec>(igrad_vx_interf).insert(grad_vx_ptr->get(p.id_patch));
1182 pdat_new.get_field<Tvec>(igrad_vy_interf).insert(grad_vy_ptr->get(p.id_patch));
1183 pdat_new.get_field<Tvec>(igrad_vz_interf).insert(grad_vz_ptr->get(p.id_patch));
1186 pdat_new.check_field_obj_cnt_match();
1190 pdat.insert_elements(pdat_interf);
1193 timer_interf.
stop();
1194 storage.timings_details.interface += timer_interf.
elapsed_sec();
1197template<
class Tvec,
template<
class>
class Kern>
1198void shammodels::gsph::Solver<Tvec, Kern>::reset_merge_ghosts_fields() {
1199 storage.merged_patchdata_ghost.reset();
1202template<
class Tvec,
template<
class>
class Kern>
1203void shammodels::gsph::Solver<Tvec, Kern>::compute_eos_fields() {
1207 using namespace shamrock::patch;
1213 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1214 const Tscal gamma = solver_config.get_eos_gamma();
1215 const bool has_uint = solver_config.has_field_uint();
1220 u32 idensity_interf = ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::density);
1222 = has_uint ? ghost_layout.
get_field_idx<Tscal>(gsph::names::newtonian::uint) : 0;
1236 storage.merged_patchdata_ghost.get().for_each([&](
u64 id,
PatchDataLayer &mpdat) {
1239 if (total_elements == 0)
1244 auto &pressure_buf = pressure_field.
get_field(
id).get_buf();
1245 auto &soundspeed_buf = soundspeed_field.
get_field(
id).get_buf();
1251 auto pressure = pressure_buf.get_write_access(depends_list);
1252 auto soundspeed = soundspeed_buf.get_write_access(depends_list);
1254 const Tscal *uint_ptr =
nullptr;
1256 uint_ptr = mpdat.get_field_buf_ref<Tscal>(iuint_interf).get_read_access(depends_list);
1259 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
1260 shambase::parallel_for(cgh, total_elements,
"compute_eos_gsph", [=](
u64 gid) {
1265 rho = sycl::max(rho, Tscal(1e-30));
1267 if (has_uint && uint_ptr !=
nullptr) {
1270 Tscal u = uint_ptr[i];
1271 u = sycl::max(u, Tscal(1e-30));
1272 Tscal P = (gamma - Tscal(1.0)) * rho * u;
1276 Tscal cs = sycl::sqrt(gamma * (gamma - Tscal(1.0)) * u);
1279 P = sycl::clamp(P, Tscal(1e-30), Tscal(1e30));
1280 cs = sycl::clamp(cs, Tscal(1e-10), Tscal(1e10));
1286 Tscal cs = Tscal(1.0);
1287 Tscal P = cs * cs * rho;
1298 mpdat.get_field_buf_ref<Tscal>(iuint_interf).complete_event_state(e);
1300 pressure_buf.complete_event_state(e);
1301 soundspeed_buf.complete_event_state(e);
1305template<
class Tvec,
template<
class>
class Kern>
1306void shammodels::gsph::Solver<Tvec, Kern>::reset_eos_fields() {
1310template<
class Tvec,
template<
class>
class Kern>
1315 using namespace shamrock::patch;
1345 auto &q = shamsys::instance::get_compute_scheduler().get_queue();
1348 auto rho_in = buf_rho_in.get_read_access(depends_list);
1352 auto P = buf_P.get_write_access(depends_list);
1353 auto cs = buf_cs.get_write_access(depends_list);
1355 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
1356 cgh.parallel_for(sycl::range<1>{npart}, [=](sycl::item<1> item) {
1357 rho[item] = rho_in[item];
1358 P[item] = P_in[item];
1359 cs[item] = cs_in[item];
1363 buf_rho_in.complete_event_state(e);
1367 buf_P.complete_event_state(e);
1368 buf_cs.complete_event_state(e);
1372template<
class Tvec,
template<
class>
class Kern>
1377 if (!solver_config.requires_gradients()) {
1382 using namespace shamrock::patch;
1384 const Tscal pmass = solver_config.gpart_mass;
1385 const Tscal gamma = solver_config.get_eos_gamma();
1387 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1392 const bool has_uint = solver_config.has_field_uint();
1416 auto &merged_xyzh = storage.merged_xyzh.get();
1417 auto &neigh_cache = storage.neigh_cache->neigh_cache;
1419 static constexpr Tscal Rkern = Kernel::Rkern;
1430 auto &mfield = merged_xyzh.get(p.id_patch);
1431 auto &pcache = neigh_cache.get(p.id_patch);
1434 auto &buf_xyz = mfield.template get_field_buf_ref<Tvec>(0);
1435 auto &buf_hpart = mfield.template get_field_buf_ref<Tscal>(1);
1436 auto &buf_vxyz = pdat.get_field_buf_ref<Tvec>(ivxyz);
1439 auto &dens_field = density_field.
get_field(p.id_patch);
1442 auto &grad_d_field = grad_density_field.
get_field(p.id_patch);
1443 auto &grad_p_field = grad_pressure_field.
get_field(p.id_patch);
1444 auto &grad_vx_buf = grad_vx_field.
get_field(p.id_patch);
1445 auto &grad_vy_buf = grad_vy_field.
get_field(p.id_patch);
1446 auto &grad_vz_buf = grad_vz_field.
get_field(p.id_patch);
1451 auto ploop_ptrs = pcache.get_read_access(depends_list);
1454 auto v_acc = buf_vxyz.get_read_access(depends_list);
1455 auto dens_acc = dens_field.get_buf().get_read_access(depends_list);
1456 auto grad_d_acc = grad_d_field.get_buf().get_write_access(depends_list);
1457 auto grad_p_acc = grad_p_field.get_buf().get_write_access(depends_list);
1458 auto grad_vx_acc = grad_vx_buf.get_buf().get_write_access(depends_list);
1459 auto grad_vy_acc = grad_vy_buf.get_buf().get_write_access(depends_list);
1460 auto grad_vz_acc = grad_vz_buf.get_buf().get_write_access(depends_list);
1463 const Tscal *uint_ptr =
nullptr;
1465 uint_ptr = pdat.get_field_buf_ref<Tscal>(iuint).get_read_access(depends_list);
1468 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
1471 shambase::parallel_for(cgh, cnt,
"gsph_compute_gradients", [=](
u64 gid) {
1474 Tvec xyz_a = xyz_acc[id_a];
1475 Tscal h_a = h_acc[id_a];
1476 Tvec v_a = v_acc[id_a];
1477 Tscal rho_a = sycl::max(dens_acc[id_a], Tscal(1e-30));
1478 Tscal dint = h_a * h_a * Rkern * Rkern;
1481 Tscal u_a = Tscal(0);
1482 if (uint_ptr !=
nullptr) {
1483 u_a = uint_ptr[id_a];
1487 Tvec grad_d = {0, 0, 0};
1488 Tvec grad_u = {0, 0, 0};
1489 Tvec grad_vx = {0, 0, 0};
1490 Tvec grad_vy = {0, 0, 0};
1491 Tvec grad_vz = {0, 0, 0};
1493 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
1494 Tvec dr = xyz_a - xyz_acc[id_b];
1495 Tscal rab2 = sycl::dot(dr, dr);
1497 if (rab2 > dint || id_a == id_b) {
1501 Tscal rab = sycl::sqrt(rab2);
1504 Tscal dWdr = Kernel::dW_3d(rab, h_a);
1508 grad_d += gradW * pmass;
1511 Tscal u_b = (uint_ptr !=
nullptr) ? uint_ptr[id_b] : Tscal(0);
1512 grad_u += gradW * (pmass * (u_b - u_a));
1515 Tvec v_b = v_acc[id_b];
1516 grad_vx += gradW * (pmass * (v_b[0] - v_a[0]));
1517 grad_vy += gradW * (pmass * (v_b[1] - v_a[1]));
1518 grad_vz += gradW * (pmass * (v_b[2] - v_a[2]));
1522 grad_d_acc[id_a] = grad_d;
1526 Tvec grad_p = (grad_d * u_a + grad_u) * (gamma - Tscal(1));
1527 grad_p_acc[id_a] = grad_p;
1532 grad_vx_acc[id_a] = grad_vx * rho_inv;
1533 grad_vy_acc[id_a] = grad_vy * rho_inv;
1534 grad_vz_acc[id_a] = grad_vz * rho_inv;
1539 pcache.complete_event_state({e});
1542 buf_vxyz.complete_event_state(e);
1543 dens_field.get_buf().complete_event_state(e);
1544 grad_d_field.get_buf().complete_event_state(e);
1545 grad_p_field.get_buf().complete_event_state(e);
1546 grad_vx_buf.get_buf().complete_event_state(e);
1547 grad_vy_buf.get_buf().complete_event_state(e);
1548 grad_vz_buf.get_buf().complete_event_state(e);
1550 pdat.get_field_buf_ref<Tscal>(iuint).complete_event_state(e);
1555template<
class Tvec,
template<
class>
class Kern>
1556void shammodels::gsph::Solver<Tvec, Kern>::prepare_corrector() {
1568 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1570 scheduler().for_each_patchdata_nonempty(
1576 auto &axyz_field = pdat.get_field<Tvec>(iaxyz);
1577 auto &old_axyz_field = old_axyz.get_field(p.id_patch);
1581 dev_sched->get_queue(),
1585 [](
u32 i,
const Tvec *src, Tvec *dst) {
1590 storage.old_axyz.set(std::move(old_axyz));
1592 if (solver_config.has_field_uint()) {
1593 const u32 iduint = pdl.
get_field_idx<Tscal>(gsph::names::newtonian::duint);
1594 auto old_duint = utility.make_compute_field<Tscal>(gsph::names::internal::old_duint, 1);
1596 scheduler().for_each_patchdata_nonempty(
1602 auto &duint_field = pdat.get_field<Tscal>(iduint);
1603 auto &old_duint_field = old_duint.get_field(p.id_patch);
1607 dev_sched->get_queue(),
1611 [](
u32 i,
const Tscal *src, Tscal *dst) {
1616 storage.old_duint.set(std::move(old_duint));
1620template<
class Tvec,
template<
class>
class Kern>
1627template<
class Tvec,
template<
class>
class Kern>
1633 using namespace shamrock::patch;
1635 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1644 Tscal C_cour = solver_config.cfl_config.cfl_cour;
1645 Tscal C_force = solver_config.cfl_config.cfl_force;
1656 auto &buf_hpart = pdat.get_field_buf_ref<Tscal>(ihpart);
1657 auto &buf_axyz = pdat.get_field_buf_ref<Tvec>(iaxyz);
1658 auto &buf_cs = soundspeed_field.get_field(cur_p.
id_patch).get_buf();
1659 auto &cfl_dt_buf = cfl_dt.get_buf_check(cur_p.
id_patch);
1665 auto axyz = buf_axyz.get_read_access(depends_list);
1666 auto cs = buf_cs.get_read_access(depends_list);
1667 auto cfl_dt_acc = cfl_dt_buf.get_write_access(depends_list);
1669 auto e = q.
submit(depends_list, [&](sycl::handler &cgh) {
1670 shambase::parallel_for(cgh, cnt,
"gsph_compute_cfl_dt", [=](
u64 gid) {
1673 Tscal h_i = hpart[i];
1675 Tscal abs_a = sycl::length(axyz[i]);
1678 if (!sycl::isfinite(h_i) || h_i <= Tscal(0))
1680 if (!sycl::isfinite(cs_i) || cs_i <= Tscal(0))
1681 cs_i = Tscal(1e-10);
1682 if (!sycl::isfinite(abs_a))
1683 abs_a = Tscal(1e30);
1687 Tscal dt_c = C_cour * h_i / cs_i;
1690 Tscal dt_f = C_force * sycl::sqrt(h_i / (abs_a + Tscal(1e-30)));
1692 Tscal dt_min = sycl::min(dt_c, dt_f);
1695 if (!sycl::isfinite(dt_min) || dt_min <= Tscal(0)) {
1696 dt_min = Tscal(1e-10);
1699 cfl_dt_acc[i] = dt_min;
1704 buf_axyz.complete_event_state(e);
1705 buf_cs.complete_event_state(e);
1706 cfl_dt_buf.complete_event_state(e);
1710 Tscal rank_dt = cfl_dt.compute_rank_min();
1713 if (!std::isfinite(rank_dt) || rank_dt <= Tscal(0)) {
1714 rank_dt = Tscal(1e-6);
1718 Tscal global_min_dt = shamalgs::collective::allreduce_min(rank_dt);
1723 const Tscal dt_min_floor = Tscal(1e-6);
1724 if (!std::isfinite(global_min_dt) || global_min_dt < dt_min_floor) {
1725 global_min_dt = dt_min_floor;
1728 return global_min_dt;
1731template<
class Tvec,
template<
class>
class Kern>
1732bool shammodels::gsph::Solver<Tvec, Kern>::apply_corrector(Tscal dt,
u64 Npart_all) {
1740 Tscal half_dt = Tscal{0.5} * dt;
1744 scheduler().for_each_patchdata_nonempty(
1750 auto &vxyz = pdat.get_field<Tvec>(ivxyz);
1751 auto &axyz = pdat.get_field<Tvec>(iaxyz);
1753 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1756 dev_sched->get_queue(),
1760 [half_dt](
u32 i,
const Tvec *axyz_new, Tvec *vxyz) {
1761 vxyz[i] += half_dt * axyz_new[i];
1765 if (solver_config.has_field_uint()) {
1767 const u32 iduint = pdl.
get_field_idx<Tscal>(gsph::names::newtonian::duint);
1769 scheduler().for_each_patchdata_nonempty(
1775 auto &uint_field = pdat.get_field<Tscal>(iuint);
1776 auto &
duint = pdat.get_field<Tscal>(iduint);
1778 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
1782 dev_sched->get_queue(),
1786 [half_dt](
u32 i,
const Tscal *duint_new, Tscal *uint) {
1787 uint[i] += half_dt * duint_new[i];
1791 storage.old_duint.reset();
1794 storage.old_axyz.reset();
1799template<
class Tvec,
template<
class>
class Kern>
1800void shammodels::gsph::Solver<Tvec, Kern>::update_sync_load_values() {
1801 modules::ComputeLoadBalanceValue<Tvec, Kern>(context, solver_config, storage)
1802 .update_load_balancing();
1803 scheduler().scheduler_step(
false,
false);
1806template<
class Tvec,
template<
class>
class Kern>
1810 solver_config.check_config_runtime();
1812 Tscal t_current = get_time();
1813 Tscal dt = get_dt();
1819 sham::format(
"---------------- GSPH t = {}, dt = {} ----------------", t_current, dt));
1827 .update_load_balancing();
1828 scheduler().scheduler_step(
true,
true);
1830 .update_load_balancing();
1831 scheduler().scheduler_step(
false,
false);
1836 using namespace shamrock::patch;
1838 u64 Npart_all = scheduler().get_total_obj_count();
1861 do_predictor_leapfrog(dt);
1865 gen_serial_patch_tree();
1866 apply_position_boundary(t_current + dt);
1873 gsph_prestep(t_current, dt);
1882 init_ghost_layout();
1886 communicate_merge_ghosts_fields();
1891 compute_eos_fields();
1895 prepare_corrector();
1901 apply_corrector(dt, Npart_all);
1907 if (dt > Tscal(0)) {
1908 dt_next = sham::min(dt_next, Tscal(2) * dt);
1915 reset_neighbors_cache();
1916 reset_presteps_rint();
1917 clear_merged_pos_trees();
1918 reset_merge_ghosts_fields();
1919 storage.merged_xyzh.reset();
1920 clear_ghost_cache();
1921 reset_serial_patch_tree();
1922 reset_ghost_handler();
1923 storage.ghost_layout.reset();
1926 set_time(t_current + dt);
1927 set_next_dt(dt_next);
1929 solve_logs.step_count++;
1936 log.rate = Tscal(Npart_all) / tstep.
elapsed_sec();
1937 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 * 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 IterateSmoothingLengthDensityNeighLim module for iterating smoothing length based on the...
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.
GSPH-specific utilities for ghost particle handling.
void compute_density()
Compute SPH-summation density for GSPH.
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.
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...
PatchDataField< T > & get_field(u64 id) const
Get the underlying PatchDataField at the given id.
A Compressed Leaf Bounding Volume Hierarchy (CLBVH) for neighborhood queries.
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.
void err_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.