115 bool has_B_field = solver_config.has_field_B_on_rho();
116 bool has_psi_field = solver_config.has_field_psi_on_ch();
117 bool has_epsilon_field = solver_config.dust_config.has_epsilon_field();
118 bool has_deltav_field = solver_config.dust_config.has_deltav_field();
119 bool has_s_j_field = solver_config.dust_config.has_s_j_field();
121 using namespace shamrock::solvergraph;
148 if (has_epsilon_field) {
152 if (has_deltav_field) {
164 gpart_mass.value = solver_config.gpart_mass;
174 std::vector<std::shared_ptr<shamrock::solvergraph::INode>> attach_field_sequence;
178 "set_scheduler_patchdata",
181 scheduler().for_each_patchdata_nonempty(
184 scheduler_patchdata.patchdatas.
add_obj(p.id_patch, std::ref(pdat));
189 attach_field_sequence.push_back(set_scheduler_patchdata);
193 auto attach_part_counts
199 attach_field_sequence.push_back(attach_part_counts);
209 attach_field_sequence.push_back(attach_xyz);
219 attach_field_sequence.push_back(attach_vxyz);
229 attach_field_sequence.push_back(attach_axyz);
239 attach_field_sequence.push_back(attach_uint);
249 attach_field_sequence.push_back(attach_duint);
259 attach_field_sequence.push_back(attach_hpart);
269 attach_field_sequence.push_back(attach_B_on_rho);
279 attach_field_sequence.push_back(attach_dB_on_rho);
289 attach_field_sequence.push_back(attach_psi_on_ch);
299 attach_field_sequence.push_back(attach_dpsi_on_ch);
302 if (has_epsilon_field) {
309 attach_field_sequence.push_back(attach_epsilon);
312 if (has_epsilon_field) {
319 attach_field_sequence.push_back(attach_dtepsilon);
322 if (has_deltav_field) {
329 attach_field_sequence.push_back(attach_deltav);
332 if (has_deltav_field) {
339 attach_field_sequence.push_back(attach_dtdeltav);
349 attach_field_sequence.push_back(attach_s_j);
359 attach_field_sequence.push_back(attach_ds_j_dt);
362 "attach fields to scheduler",
372 auto make_half_step_sequence = [&](std::string prefix) {
373 std::vector<std::shared_ptr<shamrock::solvergraph::INode>> half_step_sequence;
384 half_step_sequence.push_back(half_step_vxyz);
396 half_step_sequence.push_back(half_step_uint);
408 half_step_sequence.push_back(half_step_B_on_rho);
420 half_step_sequence.push_back(half_step_psi_on_ch);
423 if (has_epsilon_field) {
432 half_step_sequence.push_back(half_step_epsilon);
435 if (has_deltav_field) {
444 half_step_sequence.push_back(half_step_deltav);
448 u32 ndust = solver_config.dust_config.get_dust_nvar();
457 half_step_sequence.push_back(half_step_s_j);
463 solver_graph.
register_node(
"half_step1", make_half_step_sequence(
"half_step1"));
464 solver_graph.
register_node(
"half_step2", make_half_step_sequence(
"half_step2"));
479 "leapfrog predictor",
481 "leapfrog predictor",
493 bool do_part_killing_step = solver_config.particle_killing.kill_list.size() > 0;
495 if (do_part_killing_step) {
503 std::vector<std::shared_ptr<shamrock::solvergraph::INode>> part_kill_sequence{};
507 auto empty_part_to_remove
510 part_kill_sequence.push_back(empty_part_to_remove);
513 using kill_t =
typename ParticleKillingConfig<Tvec>::kill_t;
517 for (kill_t &kill_obj : solver_config.particle_killing.kill_list) {
518 if (kill_sphere *kill_info = std::get_if<kill_sphere>(&kill_obj)) {
521 kill_info->center, kill_info->radius);
522 node_selector.set_edges(xyz_edge, part_to_remove);
524 part_kill_sequence.push_back(
525 std::make_shared<
decltype(node_selector)>(std::move(node_selector)));
531 node_killer.set_edges(part_to_remove, patchdatas);
533 part_kill_sequence.push_back(
534 std::make_shared<
decltype(node_killer)>(std::move(node_killer)));
543 std::vector<std::shared_ptr<shamrock::solvergraph::INode>> seq{};
548 if (do_part_killing_step) {
557 = std::make_shared<shamrock::solvergraph::Indexes<u32>>(
"part_counts",
"N_{\\rm part}");
559 storage.part_counts_with_ghost = std::make_shared<shamrock::solvergraph::Indexes<u32>>(
560 "part_counts_with_ghost",
"N_{\\rm part, with ghost}");
562 storage.patch_rank_owner = std::make_shared<shamrock::solvergraph::RankGetter>(
563 [&](
u64 patch_id) ->
u32 {
564 return scheduler().get_patch_rank_owner(patch_id);
570 storage.positions_with_ghosts
571 = std::make_shared<shamrock::solvergraph::FieldRefs<Tvec>>(
"part_pos",
"\\mathbf{r}");
572 storage.hpart_with_ghosts
573 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"h_part",
"h");
576 = std::make_shared<shammodels::sph::solvergraph::NeighCache>(
"neigh_cache",
"neigh");
578 storage.omega = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"omega",
"\\Omega");
580 if (solver_config.has_field_alphaAV()) {
581 storage.alpha_av_updated = std::make_shared<shamrock::solvergraph::Field<Tscal>>(
582 1,
"alpha_av_updated",
"\\alpha_{\\rm AV}");
585 storage.pressure = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"pressure",
"P");
587 = std::make_shared<shamrock::solvergraph::Field<Tscal>>(1,
"soundspeed",
"c_s");
589 storage.exchange_gz_alpha
590 = std::make_shared<shamrock::solvergraph::ExchangeGhostField<Tscal>>();
591 storage.exchange_gz_node
592 = std::make_shared<shamrock::solvergraph::ExchangeGhostLayer>(storage.ghost_layout);
593 storage.exchange_gz_positions
594 = std::make_shared<shamrock::solvergraph::ExchangeGhostLayer>(storage.xyzh_ghost_layout);
901 using namespace shamrock::patch;
906 SPHUtils sph_utils(scheduler());
914 auto should_set_omega_mask = std::make_shared<shamrock::solvergraph::Field<u32>>(
915 1,
"should_set_omega_mask",
"should_set_omega_mask");
918 u32 hstep_max = solver_config.h_max_subcycles_count;
919 for (; hstep_cnt < hstep_max; hstep_cnt++) {
921 gen_ghost_handler(time_val + dt);
929 _h_old = utility.
save_field<Tscal>(ihpart,
"h_old");
933 if (solver_config.gpart_mass == 0) {
935 "invalid gpart_mass {}, this configuration can not converge.\n"
936 "Please set it using either model.set_particle_mass(pmass) or "
937 "cfg.set_particle_mass(pmass)",
938 solver_config.gpart_mass));
942 std::shared_ptr<shamrock::solvergraph::Indexes<u32>> sizes
943 = std::make_shared<shamrock::solvergraph::Indexes<u32>>(
"",
"");
945 sizes->indexes.add_obj(p.id_patch, pdat.get_obj_cnt());
949 auto &neigh_cache = storage.neigh_cache;
952 auto &pos_merged = storage.positions_with_ghosts;
955 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> hold
956 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"",
"");
959 auto &field = _h_old.get_field(p.id_patch);
960 hold_refs.add_obj(p.id_patch, std::ref(field));
962 hold->set_refs(hold_refs);
965 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> hnew
966 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"",
"");
969 auto &field = pdat.get_field<Tscal>(ihpart);
970 hnew_refs.add_obj(p.id_patch, std::ref(field));
972 hnew->set_refs(hnew_refs);
975 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> eps_h
976 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"",
"");
979 auto &field = _epsilon_h.get_field(p.id_patch);
980 eps_h_refs.add_obj(p.id_patch, std::ref(field));
982 eps_h->set_refs(eps_h_refs);
984 std::shared_ptr<shamrock::solvergraph::INode> smth_h_iter_ptr;
989 if (h_conf_density_based *conf
990 = std::get_if<h_conf_density_based>(&solver_config.smoothing_length_config.config)) {
991 std::shared_ptr<shammodels::sph::modules::IterateSmoothingLengthDensity<Tvec, Kernel>>
992 smth_h_iter = std::make_shared<
994 solver_config.gpart_mass,
995 solver_config.htol_up_coarse_cycle,
996 solver_config.htol_up_fine_cycle);
997 smth_h_iter->set_edges(sizes, neigh_cache, pos_merged, hold, hnew, eps_h);
998 smth_h_iter_ptr = smth_h_iter;
1000 h_conf_neigh_lim *conf
1001 = std::get_if<h_conf_neigh_lim>(&solver_config.smoothing_length_config.config)) {
1004 smth_h_iter_neigh_lim = std::make_shared<
1006 solver_config.gpart_mass,
1007 solver_config.htol_up_coarse_cycle,
1008 solver_config.htol_up_fine_cycle,
1009 conf->max_neigh_count);
1010 smth_h_iter_neigh_lim->set_edges(
1011 sizes, neigh_cache, pos_merged, hold, hnew, eps_h, should_set_omega_mask);
1012 smth_h_iter_ptr = smth_h_iter_neigh_lim;
1018 std::shared_ptr<shamrock::solvergraph::ScalarEdge<bool>> is_converged
1019 = std::make_shared<shamrock::solvergraph::ScalarEdge<bool>>(
"",
"");
1022 smth_h_iter_ptr, solver_config.epsilon_h, solver_config.h_iter_per_subcycles,
false);
1023 loop_smth_h_iter.set_edges(eps_h, is_converged);
1025 loop_smth_h_iter.evaluate();
1027 if (!is_converged->value) {
1029 Tscal largest_h = 0;
1032 largest_h = sham::max(largest_h, pdat.get_field<Tscal>(ihpart).compute_max());
1034 Tscal global_largest_h = shamalgs::collective::allreduce_max(largest_h);
1036 std::string add_info =
"";
1037 u64 cnt_unconverged = 0;
1040 = _epsilon_h.get_field(p.id_patch).get_ids_buf_where([](
auto access,
u32 id) {
1041 return access[id] == -1;
1044 if (hstep_cnt == hstep_max - 1) {
1045 if (std::get<0>(res)) {
1046 add_info +=
"\n patch " + std::to_string(p.id_patch) +
" ";
1047 add_info +=
"errored parts : \n";
1048 sycl::buffer<u32> &idx_err = *std::get<0>(res);
1053 auto pos = xyz.copy_to_stdvec();
1054 auto h = hpart.copy_to_stdvec();
1057 sycl::host_accessor acc{idx_err};
1058 for (
u32 i = 0; i < idx_err.size(); i++) {
1059 add_info += shambase::format(
1060 "{} - pos : {}, hpart : {}\n", acc[i], pos[acc[i]], h[acc[i]]);
1066 cnt_unconverged += std::get<1>(res);
1069 u64 global_cnt_unconverged = shamalgs::collective::allreduce_sum(cnt_unconverged);
1074 "smoothing length is not converged, rerunning the iterator ...\n largest h "
1077 "unconverged cnt =",
1078 global_cnt_unconverged,
1082 reset_ghost_handler();
1090 storage.merged_xyzh.reset();
1111 if (hstep_cnt == hstep_max) {
1112 logger::err_ln(
"SPH",
"the h iterator is not converged after", hstep_cnt,
"iterations");
1115 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> hnew_edge
1116 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"",
"");
1119 auto &field = pdat.get_field<Tscal>(ihpart);
1120 hnew_refs.add_obj(p.id_patch, std::ref(field));
1122 hnew_edge->set_refs(hnew_refs);
1125 compute_omega.set_edges(
1126 storage.part_counts,
1127 storage.neigh_cache,
1128 storage.positions_with_ghosts,
1133 if (solver_config.smoothing_length_config.is_density_based_neigh_lim()) {
1138 set_omega_mask.set_edges(storage.part_counts, should_set_omega_mask, storage.omega);
1236 timer_interf.
start();
1239 using namespace shamrock::patch;
1241 bool has_alphaAV_field = solver_config.has_field_alphaAV();
1242 bool has_soundspeed_field = solver_config.ghost_has_soundspeed();
1244 bool has_B_field = solver_config.has_field_B_on_rho();
1245 bool has_psi_field = solver_config.has_field_psi_on_ch();
1246 bool has_curlB_field = solver_config.has_field_curlB();
1247 bool has_epsilon_field = solver_config.dust_config.has_epsilon_field();
1248 bool has_deltav_field = solver_config.dust_config.has_deltav_field();
1249 bool has_s_j_field = solver_config.dust_config.has_s_j_field();
1259 const u32 ialpha_AV = (has_alphaAV_field) ? pdl.
get_field_idx<Tscal>(
"alpha_AV") : 0;
1260 const u32 isoundspeed = (has_soundspeed_field) ? pdl.
get_field_idx<Tscal>(
"soundspeed") : 0;
1262 const u32 iB_on_rho = (has_B_field) ? pdl.
get_field_idx<Tvec>(
"B/rho") : 0;
1263 const u32 idB_on_rho = (has_B_field) ? pdl.
get_field_idx<Tvec>(
"dB/rho") : 0;
1264 const u32 ipsi_on_ch = (has_psi_field) ? pdl.
get_field_idx<Tscal>(
"psi/ch") : 0;
1265 const u32 idpsi_on_ch = (has_psi_field) ? pdl.
get_field_idx<Tscal>(
"dpsi/ch") : 0;
1266 const u32 icurlB = (has_curlB_field) ? pdl.
get_field_idx<Tvec>(
"curlB") : 0;
1268 bool do_MHD_debug = solver_config.do_MHD_debug();
1269 const u32 imag_pressure = (do_MHD_debug) ? pdl.
get_field_idx<Tvec>(
"mag_pressure") : -1;
1270 const u32 imag_tension = (do_MHD_debug) ? pdl.
get_field_idx<Tvec>(
"mag_tension") : -1;
1271 const u32 igas_pressure = (do_MHD_debug) ? pdl.
get_field_idx<Tvec>(
"gas_pressure") : -1;
1272 const u32 itensile_corr = (do_MHD_debug) ? pdl.
get_field_idx<Tvec>(
"tensile_corr") : -1;
1273 const u32 ipsi_propag = (do_MHD_debug) ? pdl.
get_field_idx<Tscal>(
"psi_propag") : -1;
1274 const u32 ipsi_diff = (do_MHD_debug) ? pdl.
get_field_idx<Tscal>(
"psi_diff") : -1;
1275 const u32 ipsi_cons = (do_MHD_debug) ? pdl.
get_field_idx<Tscal>(
"psi_cons") : -1;
1276 const u32 iu_mhd = (do_MHD_debug) ? pdl.
get_field_idx<Tscal>(
"u_mhd") : -1;
1278 const u32 iepsilon = (has_epsilon_field) ? pdl.
get_field_idx<Tscal>(
"epsilon") : 0;
1279 const u32 ideltav = (has_deltav_field) ? pdl.
get_field_idx<Tvec>(
"deltav") : 0;
1282 auto &ghost_layout_ptr = storage.ghost_layout;
1289 const u32 iaxyz_interf
1290 = (solver_config.has_axyz_in_ghost()) ? ghost_layout.
get_field_idx<Tvec>(
"axyz") : 0;
1292 const u32 isoundspeed_interf
1293 = (has_soundspeed_field) ? ghost_layout.
get_field_idx<Tscal>(
"soundspeed") : 0;
1295 const u32 iB_interf = (has_B_field) ? ghost_layout.
get_field_idx<Tvec>(
"B/rho") : 0;
1296 const u32 ipsi_interf = (has_psi_field) ? ghost_layout.
get_field_idx<Tscal>(
"psi/ch") : 0;
1297 const u32 icurlB_interf = (has_curlB_field) ? ghost_layout.
get_field_idx<Tvec>(
"curlB") : 0;
1299 const u32 iepsilon_interf
1300 = (has_epsilon_field) ? ghost_layout.
get_field_idx<Tscal>(
"epsilon") : 0;
1301 const u32 ideltav_interf = (has_deltav_field) ? ghost_layout.
get_field_idx<Tvec>(
"deltav") : 0;
1302 const u32 is_j_interf = (has_s_j_field) ? ghost_layout.
get_field_idx<Tscal>(
"s_j") : 0;
1309 auto pdat_interf = ghost_handle.template build_interface_native<PatchDataLayer>(
1310 storage.ghost_patch_cache.get(),
1312 PatchDataLayer pdat(ghost_layout_ptr);
1319 ghost_handle.template modify_interface_native<PatchDataLayer>(
1320 storage.ghost_patch_cache.get(),
1324 InterfaceBuildInfos binfo,
1328 PatchDataLayer &sender_patch = scheduler().patch_data.get_pdat(sender);
1329 PatchDataField<Tscal> &sender_omega = omega.get(sender);
1331 sender_patch.get_field<Tscal>(ihpart).append_subset_to(
1332 buf_idx, cnt, pdat.get_field<Tscal>(ihpart_interf));
1333 sender_patch.get_field<Tscal>(iuint).append_subset_to(
1334 buf_idx, cnt, pdat.get_field<Tscal>(iuint_interf));
1336 if (solver_config.has_axyz_in_ghost()) {
1337 sender_patch.get_field<Tvec>(iaxyz).append_subset_to(
1338 buf_idx, cnt, pdat.get_field<Tvec>(iaxyz_interf));
1341 sender_patch.get_field<Tvec>(ivxyz).append_subset_to(
1342 buf_idx, cnt, pdat.get_field<Tvec>(ivxyz_interf));
1344 sender_omega.append_subset_to(buf_idx, cnt, pdat.get_field<Tscal>(iomega_interf));
1346 if (has_soundspeed_field) {
1347 sender_patch.get_field<Tscal>(isoundspeed)
1348 .append_subset_to(buf_idx, cnt, pdat.get_field<Tscal>(isoundspeed_interf));
1352 sender_patch.get_field<Tvec>(iB_on_rho).append_subset_to(
1353 buf_idx, cnt, pdat.get_field<Tvec>(iB_interf));
1356 if (has_psi_field) {
1357 sender_patch.get_field<Tscal>(ipsi_on_ch)
1358 .append_subset_to(buf_idx, cnt, pdat.get_field<Tscal>(ipsi_interf));
1361 if (has_curlB_field) {
1362 sender_patch.get_field<Tvec>(icurlB).append_subset_to(
1363 buf_idx, cnt, pdat.get_field<Tvec>(icurlB_interf));
1366 if (has_epsilon_field) {
1367 sender_patch.get_field<Tscal>(iepsilon).append_subset_to(
1368 buf_idx, cnt, pdat.get_field<Tscal>(iepsilon_interf));
1371 if (has_deltav_field) {
1372 sender_patch.get_field<Tvec>(ideltav).append_subset_to(
1373 buf_idx, cnt, pdat.get_field<Tvec>(ideltav_interf));
1376 if (has_s_j_field) {
1377 sender_patch.get_field<Tscal>(is_j).append_subset_to(
1378 buf_idx, cnt, pdat.get_field<Tscal>(is_j_interf));
1382 ghost_handle.template modify_interface_native<PatchDataLayer>(
1383 storage.ghost_patch_cache.get(),
1387 InterfaceBuildInfos binfo,
1391 if (sycl::length(binfo.offset_speed) > 0) {
1392 pdat.get_field<Tvec>(ivxyz_interf).apply_offset(binfo.offset_speed);
1398 std::move(pdat_interf),
1399 storage.exchange_gz_node,
1400 solver_config.show_ghost_zone_graph);
1402 std::map<u64, u64> sz_interf_map;
1404 sz_interf_map[r] += pdat_interf.get_obj_cnt();
1407 storage.merged_patchdata_ghost.set(
1408 ghost_handle.template merge_native<PatchDataLayer, PatchDataLayer>(
1409 std::move(interf_pdat),
1411 PatchDataLayer pdat_new(ghost_layout_ptr);
1413 u32 or_elem = pdat.get_obj_cnt();
1414 pdat_new.reserve(or_elem + sz_interf_map[p.id_patch]);
1415 u32 total_elements = or_elem;
1417 PatchDataField<Tscal> &cur_omega = omega.get(p.id_patch);
1419 pdat_new.get_field<Tscal>(ihpart_interf).insert(pdat.get_field<Tscal>(ihpart));
1420 pdat_new.get_field<Tscal>(iuint_interf).insert(pdat.get_field<Tscal>(iuint));
1421 pdat_new.get_field<Tvec>(ivxyz_interf).insert(pdat.get_field<Tvec>(ivxyz));
1423 if (solver_config.has_axyz_in_ghost()) {
1424 pdat_new.get_field<Tvec>(iaxyz_interf).insert(pdat.get_field<Tvec>(iaxyz));
1427 pdat_new.get_field<Tscal>(iomega_interf).insert(cur_omega);
1429 if (has_soundspeed_field) {
1430 pdat_new.get_field<Tscal>(isoundspeed_interf)
1431 .insert(pdat.get_field<Tscal>(isoundspeed));
1435 pdat_new.get_field<Tvec>(iB_interf).insert(pdat.get_field<Tvec>(iB_on_rho));
1438 if (has_psi_field) {
1439 pdat_new.get_field<Tscal>(ipsi_interf)
1440 .insert(pdat.get_field<Tscal>(ipsi_on_ch));
1443 if (has_curlB_field) {
1444 pdat_new.get_field<Tvec>(icurlB_interf).insert(pdat.get_field<Tvec>(icurlB));
1447 if (has_epsilon_field) {
1448 pdat_new.get_field<Tscal>(iepsilon_interf)
1449 .insert(pdat.get_field<Tscal>(iepsilon));
1452 if (has_deltav_field) {
1453 pdat_new.get_field<Tvec>(ideltav_interf).insert(pdat.get_field<Tvec>(ideltav));
1456 if (has_s_j_field) {
1457 pdat_new.get_field<Tscal>(is_j_interf).insert(pdat.get_field<Tscal>(is_j));
1460 pdat_new.check_field_obj_cnt_match();
1465 pdat.insert_elements(pdat_interf);
1468 timer_interf.stop();
1469 storage.timings_details.interface += timer_interf.elapsed_sec();
1631 for (
auto &callbacks : timestep_callbacks) {
1632 if (callbacks.step_begin_callback) {
1637 Tscal t_current = solver_config.get_time();
1638 Tscal dt = solver_config.get_dt_sph();
1644 shambase::format(
"---------------- t = {}, dt = {} ----------------", t_current, dt));
1652 .update_load_balancing();
1653 scheduler().scheduler_step(
true,
true);
1655 .update_load_balancing();
1657 scheduler().scheduler_step(
false,
false);
1663 using namespace shamrock::patch;
1665 bool has_B_field = solver_config.has_field_B_on_rho();
1666 bool has_psi_field = solver_config.has_field_psi_on_ch();
1667 bool has_epsilon_field = solver_config.dust_config.has_epsilon_field();
1668 bool has_deltav_field = solver_config.dust_config.has_deltav_field();
1669 bool has_s_j_field = solver_config.dust_config.has_s_j_field();
1679 const u32 iB_on_rho = (has_B_field) ? pdl.
get_field_idx<Tvec>(
"B/rho") : 0;
1680 const u32 idB_on_rho = (has_B_field) ? pdl.
get_field_idx<Tvec>(
"dB/rho") : 0;
1681 const u32 ipsi_on_ch = (has_psi_field) ? pdl.
get_field_idx<Tscal>(
"psi/ch") : 0;
1682 const u32 idpsi_on_ch = (has_psi_field) ? pdl.
get_field_idx<Tscal>(
"dpsi/ch") : 0;
1683 const u32 iepsilon = (has_epsilon_field) ? pdl.
get_field_idx<Tscal>(
"epsilon") : 0;
1684 const u32 idtepsilon = (has_epsilon_field) ? pdl.
get_field_idx<Tscal>(
"dtepsilon") : 0;
1686 const u32 ids_j_dt = (has_s_j_field) ? pdl.
get_field_idx<Tscal>(
"ds_j_dt") : 0;
1687 const u32 ideltav = (has_deltav_field) ? pdl.
get_field_idx<Tvec>(
"deltav") : 0;
1688 const u32 idtdeltav = (has_deltav_field) ? pdl.
get_field_idx<Tvec>(
"dtdeltav") : 0;
1695 sink_update.accrete_particles(dt);
1696 ext_forces.point_mass_accrete_particles();
1698 sink_update.predictor_step(dt);
1703 using namespace shamrock::solvergraph;
1720 sink_update.compute_ext_forces();
1724 gen_serial_patch_tree();
1728 u64 Npart_all = scheduler().get_total_obj_count();
1730 if (solver_config.enable_particle_reordering
1731 && solve_logs.step_count % solver_config.particle_reordering_step_freq == 0) {
1732 logger::info_ln(
"SPH",
"Reordering particles at step ", solve_logs.step_count);
1740 using namespace shamrock::solvergraph;
1751 if (solver_config.self_grav_config.is_sg_on()) {
1753 auto constant_G = shamrock::solvergraph::IDataEdge<Tscal>::make_shared(
"",
"");
1757 constant_G.data = solver_config.get_constant_G();
1762 auto field_xyz = shamrock::solvergraph::FieldRefs<Tvec>::make_shared(
"",
"");
1768 auto &field = pdat.get_field<Tvec>(ixyz);
1769 field_xyz_refs.
add_obj(p.id_patch, std::ref(field));
1771 field_xyz_edge.set_refs(field_xyz_refs);
1777 auto field_axyz_ext = shamrock::solvergraph::FieldRefs<Tvec>::make_shared(
"",
"");
1783 auto &field = pdat.get_field<Tvec>(iaxyz_ext);
1784 field_axyz_ext_refs.
add_obj(p.id_patch, std::ref(field));
1786 field_axyz_ext_edge.set_refs(field_axyz_ext_refs);
1788 set_field_axyz_ext.
set_edges(field_axyz_ext);
1790 auto sizes = shamrock::solvergraph::Indexes<u32>::make_shared(
"",
"");
1796 sizes.indexes.add_obj(p.id_patch, pdat.get_obj_cnt());
1801 auto gpart_mass = shamrock::solvergraph::IDataEdge<Tscal>::make_shared(
"",
"");
1805 gpart_mass.data = solver_config.gpart_mass;
1810 set_gpart_mass.evaluate();
1811 set_constant_G.evaluate();
1812 set_field_xyz.evaluate();
1813 set_field_axyz_ext.evaluate();
1814 set_sizes.evaluate();
1817 std::get_if<SelfGravConfig::SofteningPlummer>(
1818 &solver_config.self_grav_config.softening_mode))
1821 if (solver_config.self_grav_config.is_none()) {
1823 }
else if (solver_config.self_grav_config.is_direct()) {
1826 std::get_if<SelfGravConfig::Direct>(&solver_config.self_grav_config.config));
1829 eps_grav, direct_config.reference_mode);
1830 self_gravity_direct_node.set_edges(
1831 sizes, gpart_mass, constant_G, field_xyz, field_axyz_ext);
1832 self_gravity_direct_node.
evaluate();
1834 }
else if (solver_config.self_grav_config.is_mm()) {
1837 std::get_if<SelfGravConfig::MM>(&solver_config.self_grav_config.config));
1839 auto run_sg_mm = [&](
auto mm_order_tag) {
1840 constexpr u32 order =
decltype(mm_order_tag)::value;
1842 eps_grav, mm_config.opening_angle, mm_config.reduction_level);
1843 self_gravity_mm_node.set_edges(
1844 sizes, gpart_mass, constant_G, field_xyz, field_axyz_ext);
1848 switch (mm_config.order) {
1849 case 1 : run_sg_mm(std::integral_constant<u32, 1>{});
break;
1850 case 2 : run_sg_mm(std::integral_constant<u32, 2>{});
break;
1851 case 3 : run_sg_mm(std::integral_constant<u32, 3>{});
break;
1852 case 4 : run_sg_mm(std::integral_constant<u32, 4>{});
break;
1853 case 5 : run_sg_mm(std::integral_constant<u32, 5>{});
break;
1857 }
else if (solver_config.self_grav_config.is_fmm()) {
1860 std::get_if<SelfGravConfig::FMM>(&solver_config.self_grav_config.config));
1862 auto run_sg_fmm = [&](
auto fmm_order_tag) {
1863 constexpr u32 order =
decltype(fmm_order_tag)::value;
1865 eps_grav, fmm_config.opening_angle, fmm_config.reduction_level);
1866 self_gravity_mm_node.set_edges(
1867 sizes, gpart_mass, constant_G, field_xyz, field_axyz_ext);
1871 switch (fmm_config.order) {
1872 case 1 : run_sg_fmm(std::integral_constant<u32, 1>{});
break;
1873 case 2 : run_sg_fmm(std::integral_constant<u32, 2>{});
break;
1874 case 3 : run_sg_fmm(std::integral_constant<u32, 3>{});
break;
1875 case 4 : run_sg_fmm(std::integral_constant<u32, 4>{});
break;
1876 case 5 : run_sg_fmm(std::integral_constant<u32, 5>{});
break;
1880 }
else if (solver_config.self_grav_config.is_sfmm()) {
1883 std::get_if<SelfGravConfig::SFMM>(&solver_config.self_grav_config.config));
1885 auto run_sg_sfmm = [&](
auto sfmm_order_tag) {
1886 constexpr u32 order =
decltype(sfmm_order_tag)::value;
1889 sfmm_config.opening_angle,
1890 sfmm_config.leaf_lowering,
1891 sfmm_config.reduction_level);
1892 self_gravity_mm_node.set_edges(
1893 sizes, gpart_mass, constant_G, field_xyz, field_axyz_ext);
1897 switch (sfmm_config.order) {
1898 case 1 : run_sg_sfmm(std::integral_constant<u32, 1>{});
break;
1899 case 2 : run_sg_sfmm(std::integral_constant<u32, 2>{});
break;
1900 case 3 : run_sg_sfmm(std::integral_constant<u32, 3>{});
break;
1901 case 4 : run_sg_sfmm(std::integral_constant<u32, 4>{});
break;
1902 case 5 : run_sg_sfmm(std::integral_constant<u32, 5>{});
break;
1908 "Self gravity config not supported, current state is : \n"
1909 + nlohmann::json{solver_config.self_grav_config}.dump(4));
1914 auto &merged_xyzh = storage.merged_xyzh.get();
1924 u32 iB_on_rho_interf = (has_B_field) ? ghost_layout.
get_field_idx<Tvec>(
"B/rho") : 0;
1925 u32 ipsi_on_rho_interf = (has_psi_field) ? ghost_layout.
get_field_idx<Tscal>(
"psi/ch") : 0;
1932 u32 corrector_iter_cnt = 0;
1933 bool need_rerun_corrector =
false;
1939 if (corrector_iter_cnt == 50) {
1941 "the corrector has made over 50 loops, either their is a bug, either you are using "
1942 "a dt that is too large");
1948 if (solver_config.has_field_alphaAV()) {
1950 std::shared_ptr<shamrock::solvergraph::PatchDataLayerRefs> patchdatas
1951 = std::make_shared<shamrock::solvergraph::PatchDataLayerRefs>(
1952 "patchdata_layer_ref",
"patchdata_layer_ref");
1954 auto node_set_edge = scheduler().get_node_set_edge_patchdata_layer_refs();
1955 node_set_edge->set_edges(patchdatas);
1956 node_set_edge->evaluate();
1959 scheduler().get_layout_ptr_old(),
"alpha_AV");
1960 node_copy.set_edges(patchdatas, storage.alpha_av_updated);
1964 if (solver_config.has_field_dtdivv()) {
1966 if (solver_config.combined_dtdiv_divcurlv_compute) {
1967 if (solver_config.has_field_dtdivv()) {
1969 .update_dtdivv(
true);
1973 if (solver_config.has_field_divv()) {
1978 if (solver_config.has_field_curlv()) {
1983 if (solver_config.has_field_dtdivv()) {
1985 .update_dtdivv(
false);
1990 if (solver_config.has_field_divv()) {
1995 if (solver_config.has_field_curlv()) {
2012 if (solver_config.has_field_alphaAV()) {
2017 using InterfaceBuildInfos =
2021 time_interf.
start();
2023 auto field_interf = ghost_handle.template build_interface_native<PatchDataField<Tscal>>(
2024 storage.ghost_patch_cache.get(),
2027 InterfaceBuildInfos binfo,
2032 return sender_field.make_new_from_subset(buf_idx, cnt);
2036 = ghost_handle.communicate_pdatfield(
2037 std::move(field_interf), 1, storage.exchange_gz_alpha);
2041 std::move(interf_pdat),
2044 = comp_field_send.
get_field(p.id_patch);
2045 return receiver_field.duplicate();
2048 mpdat.insert(pdat_interf);
2052 storage.timings_details.interface += time_interf.
elapsed_sec();
2054 storage.alpha_av_ghost.set(std::move(merged_field));
2060 constexpr bool debug_interfaces =
false;
2061 if constexpr (debug_interfaces) {
2063 if (solver_config.do_debug_dump) {
2066 = storage.merged_patchdata_ghost.get();
2073 merged_xyzh.get(cur_p.
id_patch).field_pos.get_buf());
2074 sycl::buffer<Tvec> &buf_vxyz = mpdat.get_field_buf_ref<Tvec>(ivxyz_interf);
2075 sycl::buffer<Tscal> &buf_hpart = mpdat.get_field_buf_ref<Tscal>(ihpart_interf);
2079 SHAM_ASSERT(merged_patch.total_elements == total_elements);
2083 solver_config.gpart_mass,
2089 make_interface_debug_phantom_dump(info).gen_file().write_to_file(
2090 solver_config.debug_dump_filename);
2097 shamlog_debug_ln(
"sph::BasicGas",
"compute force");
2104 bool has_luminosity = solver_config.compute_luminosity;
2106 if (has_luminosity) {
2110 .set_refs(storage.merged_xyzh.get()
2113 return std::ref(mpdat.get_field<Tscal>(
2117 auto uint_with_ghost = shamrock::solvergraph::FieldRefs<Tscal>::make_shared(
"",
"");
2120 .set_refs(storage.merged_xyzh.get()
2123 return std::ref(mpdat.get_field<Tscal>(1));
2127 set_uint_with_ghost_refs(
2130 = storage.merged_patchdata_ghost.
get();
2135 scheduler().for_each_patchdata_nonempty(
2139 auto &field = mpdat.get_field<Tscal>(iuint_interf);
2140 field_uint_with_ghost_refs.
add_obj(p.id_patch, std::ref(field));
2143 field_uint_with_ghost_edge.set_refs(field_uint_with_ghost_refs);
2146 set_uint_with_ghost_refs.
set_edges(uint_with_ghost);
2148 auto luminosity = shamrock::solvergraph::FieldRefs<Tscal>::make_shared(
"",
"");
2151 set_luminosity_refs(
2154 = storage.merged_patchdata_ghost.
get();
2159 scheduler().for_each_patchdata_nonempty(
2161 auto &field = pdat.get_field<Tscal>(iluminosity);
2162 field_luminosity_refs.
add_obj(p.id_patch, std::ref(field));
2164 field_luminosity_edge.set_refs(field_luminosity_refs);
2167 set_luminosity_refs.
set_edges(luminosity);
2169 set_uint_with_ghost_refs.evaluate();
2170 set_luminosity_refs.evaluate();
2172 Tscal alpha_u = solver_config.artif_viscosity.get_alpha_u().value();
2175 solver_config.gpart_mass, alpha_u};
2177 compute_luminosity.set_edges(
2178 storage.part_counts,
2179 storage.neigh_cache,
2180 storage.positions_with_ghosts,
2181 storage.hpart_with_ghosts,
2199 shamlog_debug_ln(
"sph::BasicGas",
"leapfrog corrector");
2200 utility.fields_leapfrog_corrector<Tvec>(
2201 ivxyz, iaxyz, storage.old_axyz.get(), vepsilon_v_sq, dt / 2);
2202 utility.fields_leapfrog_corrector<Tscal>(
2203 iuint, iduint, storage.old_duint.get(), uepsilon_u_sq, dt / 2);
2205 if (solver_config.has_field_B_on_rho()) {
2208 utility.fields_leapfrog_corrector<Tvec>(
2209 iB_on_rho, idB_on_rho, storage.old_dB_on_rho.get(), BOR_epsilon_BOR_sq, dt / 2);
2211 if (solver_config.has_field_B_on_rho()) {
2214 utility.fields_leapfrog_corrector<Tscal>(
2215 ipsi_on_ch, idpsi_on_ch, storage.old_dpsi_on_ch.get(), POC_epsilon_POC_sq, dt / 2);
2218 if (solver_config.dust_config.has_epsilon_field()) {
2221 utility.fields_leapfrog_corrector<Tscal>(
2222 iepsilon, idtepsilon, storage.old_dtepsilon.get(), epsilon_epsilon_sq, dt / 2);
2225 if (solver_config.dust_config.has_deltav_field()) {
2228 utility.fields_leapfrog_corrector<Tvec>(
2229 ideltav, idtdeltav, storage.old_dtdeltav.get(), epsilon_deltav_sq, dt / 2);
2232 if (solver_config.dust_config.has_s_j_field()) {
2234 "s_j s_j^2", solver_config.dust_config.get_dust_nvar());
2235 utility.fields_leapfrog_corrector<Tscal>(
2236 is_j, ids_j_dt, storage.old_ds_j_dt.get(), s_j_s_j_sq, dt / 2);
2239 storage.old_axyz.reset();
2240 storage.old_duint.reset();
2241 if (solver_config.has_field_B_on_rho()) {
2242 storage.old_dB_on_rho.reset();
2244 if (solver_config.has_field_B_on_rho()) {
2245 storage.old_dpsi_on_ch.reset();
2248 if (solver_config.dust_config.has_epsilon_field()) {
2249 storage.old_dtepsilon.reset();
2252 if (solver_config.dust_config.has_deltav_field()) {
2253 storage.old_dtdeltav.reset();
2256 if (solver_config.dust_config.has_s_j_field()) {
2257 storage.old_ds_j_dt.reset();
2260 Tscal rank_veps_v = sycl::sqrt(vepsilon_v_sq.compute_rank_max());
2265 Tscal sum_vsq = utility.compute_rank_dot_sum<Tvec>(ivxyz);
2267 Tscal vmean_sq = shamalgs::collective::allreduce_sum(sum_vsq) / Tscal(Npart_all);
2269 Tscal vmean = sycl::sqrt(vmean_sq);
2271 Tscal rank_eps_v = rank_veps_v / vmean;
2277 Tscal eps_v = shamalgs::collective::allreduce_max(rank_eps_v);
2279 shamlog_debug_ln(
"BasicGas",
"epsilon v :", eps_v);
2286 "the corrector tolerance are broken the step will "
2287 "be re rerunned\n eps_v = {}",
2290 need_rerun_corrector =
true;
2291 solver_config.time_state.cfl_multiplier /= 2;
2295 need_rerun_corrector =
false;
2298 if (!need_rerun_corrector) {
2300 sink_update.corrector_step(dt);
2303 if (solver_config.has_field_alphaAV()) {
2311 = pdat.get_field<Tscal>(ialpha_AV).get_buf();
2313 = alpha_av_updated.get_field(cur_p.
id_patch).get_buf();
2315 auto &q = shamsys::instance::get_compute_scheduler().
get_queue();
2319 auto alpha_av_updated = buf_alpha_av_updated.
get_read_access(depends_list);
2321 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
2322 shambase::parallel_for(
2323 cgh, pdat.get_obj_cnt(),
"write back alpha_av", [=](
i32 id_a) {
2324 alpha_av[id_a] = alpha_av_updated[id_a];
2333 shamlog_debug_ln(
"BasicGas",
"computing next CFL");
2337 = storage.merged_xyzh.get().template map<u32>(
2339 return scheduler().patch_data.get_pdat(
id).get_obj_cnt();
2342 std::shared_ptr<shamrock::solvergraph::Field<Tscal>> vsig_max_dt
2343 = std::make_shared<shamrock::solvergraph::Field<Tscal>>(
2344 1,
"vsig_a",
"v_{\\rm sig}");
2347 std::shared_ptr<shamrock::solvergraph::Field<Tscal>> vclean_dt;
2348 if (has_psi_field) {
2349 vclean_dt = std::make_shared<shamrock::solvergraph::Field<Tscal>>(
2350 1,
"vclean_a",
"v_{\\rm clean}");
2355 = storage.merged_patchdata_ghost.
get();
2361 = merged_xyzh.get(cur_p.
id_patch).template get_field_buf_ref<Tvec>(0);
2364 = mpdat.get_field_buf_ref<Tscal>(ihpart_interf);
2374 sycl::range range_npart{pdat.get_obj_cnt()};
2383 auto &q = shamsys::instance::get_compute_scheduler().get_queue();
2388 auto hpart = buf_hpart.get_read_access(depends_list);
2389 auto u = buf_uint.get_read_access(depends_list);
2390 auto pressure = buf_pressure.get_read_access(depends_list);
2393 auto particle_looper_ptrs = pcache.get_read_access(depends_list);
2396 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
2397 const Tscal pmass = solver_config.gpart_mass;
2398 const Tscal alpha_u = 1.0;
2399 const Tscal alpha_AV = 1.0;
2400 const Tscal beta_AV = 2.0;
2404 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
2406 shambase::parallel_for(
2407 cgh, pdat.get_obj_cnt(),
"compute vsig", [=](
i32 id_a) {
2408 using namespace shamrock::sph;
2410 Tvec sum_axyz = {0, 0, 0};
2412 Tscal h_a = hpart[id_a];
2414 Tvec xyz_a = xyz[id_a];
2415 Tvec vxyz_a = vxyz[id_a];
2417 Tscal rho_a = rho_h(pmass, h_a, Kernel::hfactd);
2418 Tscal rho_a_sq = rho_a * rho_a;
2419 Tscal rho_a_inv = 1. / rho_a;
2421 Tscal P_a = pressure[id_a];
2423 const Tscal u_a = u[id_a];
2425 Tscal cs_a = cs[id_a];
2429 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
2431 Tvec dr = xyz_a - xyz[id_b];
2432 Tscal rab2 = sycl::dot(dr, dr);
2433 Tscal h_b = hpart[id_b];
2435 if (rab2 > h_a * h_a * Rker2 && rab2 > h_b * h_b * Rker2) {
2439 Tscal rab = sycl::sqrt(rab2);
2440 Tvec vxyz_b = vxyz[id_b];
2441 Tvec v_ab = vxyz_a - vxyz_b;
2442 const Tscal u_b = u[id_b];
2444 Tvec r_ab_unit = dr / rab;
2447 r_ab_unit = {0, 0, 0};
2450 Tscal rho_b = rho_h(pmass, h_b, Kernel::hfactd);
2451 Tscal P_b = pressure[id_b];
2452 Tscal cs_b = cs[id_b];
2453 Tscal v_ab_r_ab = sycl::dot(v_ab, r_ab_unit);
2454 Tscal abs_v_ab_r_ab = sycl::fabs(v_ab_r_ab);
2459 const Tscal alpha_a = alpha_AV;
2460 const Tscal alpha_b = alpha_AV;
2462 Tscal vsig_a = alpha_a * cs_a + beta_AV * abs_v_ab_r_ab;
2464 vsig_max = sycl::fmax(vsig_max, vsig_a);
2467 vsig[id_a] = vsig_max;
2471 if (has_psi_field) {
2473 Tscal
const mu_0 = solver_config.get_constant_mu_0();
2476 Tvec *B_on_rho = mpdat.get_field_buf_ref<Tvec>(iB_on_rho_interf)
2477 .get_write_access(depends_list);
2481 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
2482 const Tscal pmass = solver_config.gpart_mass;
2486 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
2488 shambase::parallel_for(
2489 cgh, pdat.get_obj_cnt(),
"compute vclean", [=](
i32 id_a) {
2490 using namespace shamrock::sph;
2492 Tscal h_a = hpart[id_a];
2493 Tscal rho_a = rho_h(pmass, h_a, Kernel::hfactd);
2494 const Tscal u_a = u[id_a];
2495 Tscal cs_a = cs[id_a];
2496 Tvec B_a = B_on_rho[id_a] * rho_a;
2498 Tscal vclean_a = shamphys::MHD_physics<Tvec, Tscal>::v_shock(
2499 cs_a, B_a, rho_a, mu_0);
2501 vclean[id_a] = vclean_a;
2504 mpdat.get_field_buf_ref<Tvec>(iB_on_rho_interf).complete_event_state(e);
2510 buf_hpart.complete_event_state(e);
2511 buf_uint.complete_event_state(e);
2512 buf_pressure.complete_event_state(e);
2518 pcache.complete_event_state(resulting_events);
2522 std::shared_ptr<shamrock::solvergraph::Field<Tscal>> cfl_dt
2523 = std::make_shared<shamrock::solvergraph::Field<Tscal>>(
2524 1,
"cfl_dt",
"\\Delta t_{cfl}");
2527 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tvec>> axyz_refs
2528 = std::make_shared<shamrock::solvergraph::FieldRefs<Tvec>>(
"axyz",
"\\mathbf{a}");
2529 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> hpart_refs
2530 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"hpart",
"h");
2532 map_field_refs(scheduler(), iaxyz, *axyz_refs);
2533 map_field_refs_ext(scheduler(), mpdats, ihpart_interf, *hpart_refs);
2535 auto &q = shamsys::instance::get_compute_scheduler().get_queue();
2537 auto reset_dt_part_field = [&]() {
2538 if (solver_config.should_save_dt_to_fields()) {
2542 = pdat.get_field_buf_ref<Tscal>(idt_part);
2543 buf_dt_part.
fill(shambase::get_infty<Tscal>());
2548 auto save_dt_min_to_dt_part = [&]() {
2549 if (solver_config.should_save_dt_to_fields()) {
2553 = pdat.get_field_buf_ref<Tscal>(idt_part);
2561 [](
u32 id_a,
const Tscal *dt, Tscal *dt_part) {
2562 dt_part[id_a] = sycl::min(dt_part[id_a], dt[id_a]);
2569 auto reset_cfl_dt = [&]() {
2571 cfl_dt->get_buf(cur_p.
id_patch).fill(shambase::get_infty<Tscal>());
2576 = solver_config.cfl_config.cfl_cour * solver_config.time_state.cfl_multiplier;
2578 = solver_config.cfl_config.cfl_force * solver_config.time_state.cfl_multiplier;
2579 Tscal eta_phi = solver_config.cfl_config.eta_sink;
2581 std::shared_ptr<shamrock::solvergraph::ScalarEdge<Tscal>> C_cour_edge
2582 = std::make_shared<shamrock::solvergraph::ScalarEdge<Tscal>>(
"C_cour",
"C_{cour}");
2583 C_cour_edge->value = C_cour;
2584 std::shared_ptr<shamrock::solvergraph::ScalarEdge<Tscal>> C_force_edge
2585 = std::make_shared<shamrock::solvergraph::ScalarEdge<Tscal>>(
2586 "C_force",
"C_{force}");
2587 C_force_edge->value = C_force;
2588 std::shared_ptr<shamrock::solvergraph::ScalarEdge<Tscal>> eta_phi_edge
2589 = std::make_shared<shamrock::solvergraph::ScalarEdge<Tscal>>(
2590 "eta_phi",
"\\eta_{\\phi}");
2591 eta_phi_edge->value = eta_phi;
2593 std::shared_ptr<ComputeCFLCourant<Tscal>> compute_cfl_courant
2594 = std::make_shared<ComputeCFLCourant<Tscal>>();
2595 compute_cfl_courant->set_edges(
2596 storage.part_counts, C_cour_edge, hpart_refs, vsig_max_dt, cfl_dt);
2598 std::shared_ptr<ComputeCFLForce<Tvec>> compute_cfl_force
2599 = std::make_shared<ComputeCFLForce<Tvec>>();
2600 compute_cfl_force->set_edges(
2601 storage.part_counts, C_force_edge, hpart_refs, axyz_refs, cfl_dt);
2603 std::shared_ptr<ComputeCFLDivBCleaning<Tscal>> compute_cfl_divB_cleaning;
2604 if (has_psi_field) {
2605 compute_cfl_divB_cleaning = std::make_shared<ComputeCFLDivBCleaning<Tscal>>();
2606 compute_cfl_divB_cleaning->set_edges(
2607 storage.part_counts, C_cour_edge, hpart_refs, vclean_dt, cfl_dt);
2610 bool show_cfl_detail = solver_config.show_cfl_detail;
2611 std::vector<std::pair<std::string, Tscal>> cfl_detail;
2613 auto save_cfl_detail = [&](
const char *key) {
2614 if (show_cfl_detail) {
2615 save_dt_min_to_dt_part();
2616 cfl_detail.push_back(
2617 {std::string(key), cfl_dt->get_native().compute_rank_min()});
2622 reset_dt_part_field();
2625 compute_cfl_courant->evaluate();
2626 save_cfl_detail(
"courant");
2628 compute_cfl_force->evaluate();
2629 save_cfl_detail(
"force");
2631 if (has_psi_field) {
2632 compute_cfl_divB_cleaning->evaluate();
2633 save_cfl_detail(
"divB_cleaning");
2636 if (!show_cfl_detail) {
2637 save_dt_min_to_dt_part();
2638 cfl_detail.push_back({
"all SPH", cfl_dt->get_native().compute_rank_min()});
2641 if (!storage.sinks.is_empty()) {
2644 Tscal sink_sink_cfl = shambase::get_infty<Tscal>();
2646 Tscal G = solver_config.get_constant_G();
2648 std::vector<SinkParticle<Tvec>> &sink_parts = storage.sinks.get();
2650 for (
u32 i = 0; i < sink_parts.size(); i++) {
2652 Tscal sink_sink_cfl_i = shambase::get_infty<Tscal>();
2654 Tvec f_i = s_i.ext_acceleration;
2656 Tscal grad_phi_i_sq = sham::dot(f_i, f_i);
2658 if (grad_phi_i_sq == 0) {
2662 for (
u32 j = 0; j < sink_parts.size(); j++) {
2669 Tvec rij = s_i.pos - s_j.pos;
2670 Tscal rij_scal = sycl::length(rij);
2672 Tscal phi_ij = G * s_j.mass / rij_scal;
2673 Tscal term_ij = sham::abs(phi_ij) / grad_phi_i_sq;
2674 Tscal dt_ij = C_force * eta_phi * sycl::sqrt(term_ij);
2676 sink_sink_cfl_i = sham::min(sink_sink_cfl_i, dt_ij);
2679 sink_sink_cfl = sham::min(sink_sink_cfl, sink_sink_cfl_i);
2682 cfl_detail.push_back({
"sink_sink", sink_sink_cfl});
2685 Tscal rank_dt = shambase::get_infty<Tscal>();
2686 for (
auto &[key, value] : cfl_detail) {
2687 rank_dt = sham::min(rank_dt, value);
2690 if (show_cfl_detail) {
2691 for (
auto &[key, value] : cfl_detail) {
2692 value = shamalgs::collective::allreduce_min(value);
2697 table.add_double_rule();
2698 table.add_data({
"key",
"value"}, shambase::table::center);
2699 table.add_double_rule();
2700 for (
auto &[key, value] : cfl_detail) {
2702 {key, shambase::format(
"{:.2e}", value)}, shambase::table::right);
2709 next_cfl = shamalgs::collective::allreduce_min(rank_dt);
2717 solver_config.time_state.cfl_multiplier);
2723 if (solver_config.has_field_soundspeed()) {
2734 sycl::range range_npart{pdat.get_obj_cnt()};
2738 auto &q = shamsys::instance::get_compute_scheduler().get_queue();
2741 auto cs_in = buf_cs_in.get_read_access(depends_list);
2744 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
2745 const Tscal pmass = solver_config.gpart_mass;
2748 sycl::range<1>{pdat.get_obj_cnt()}, [=](sycl::item<1> item) {
2749 cs[item] = cs_in[item];
2753 buf_cs_in.complete_event_state(e);
2760 corrector_iter_cnt++;
2762 if (solver_config.has_field_alphaAV()) {
2763 storage.alpha_av_ghost.reset();
2765 }
while (need_rerun_corrector);
2767 reset_merge_ghosts_fields();
2774 for (
auto it = timestep_callbacks.rbegin(); it != timestep_callbacks.rend(); ++it) {
2775 if (it->step_end_callback) {
2788 = (mem_perf_infos_end.
time_alloc_device - mem_perf_infos_start.time_alloc_device)
2789 + (mem_perf_infos_end.
time_free_device - mem_perf_infos_start.time_free_device);
2790 f64 t_host_alloc = (mem_perf_infos_end.
time_alloc_host - mem_perf_infos_start.time_alloc_host)
2791 + (mem_perf_infos_end.
time_free_host - mem_perf_infos_start.time_free_host);
2793 u64 rank_count = scheduler().get_rank_count();
2794 f64 rate =
f64(rank_count) / tstep.elapsed_sec();
2796 u64 npatch = scheduler().patch_list.local.size();
2800 std::string log_step = report_perf_timestep(
2804 tstep.elapsed_sec(),
2810 system_metrics_delta,
2811 shamsys::has_reporter());
2816 "sph::Model",
"estimated rate :", dt * (3600 / tstep.elapsed_sec()),
"(tsim/hr)");
2819 solve_logs.register_log(
2825 tstep.elapsed_sec(),
2827 system_metrics_delta});
2829 storage.timings_details.reset();
2831 reset_serial_patch_tree();
2832 reset_ghost_handler();
2838 storage.merged_xyzh.reset();
2840 clear_merged_pos_trees();
2841 clear_ghost_cache();
2842 reset_presteps_rint();
2843 reset_neighbors_cache();
2847 solver_config.set_next_dt(next_cfl);
2848 solver_config.set_time(t_current + dt);
2850 auto get_next_cfl_mult = [&]() {
2851 Tscal cfl_m = solver_config.time_state.cfl_multiplier;
2852 Tscal stiff = solver_config.cfl_config.cfl_multiplier_stiffness;
2854 return (cfl_m * stiff + 1.) / (stiff + 1.);
2857 solver_config.time_state.cfl_multiplier = get_next_cfl_mult();
2862 log.npart = rank_count;
2863 log.tcompute = tstep.elapsed_sec();