1282 timer_interf.
start();
1285 using namespace shamrock::patch;
1287 bool has_alphaAV_field = solver_config.has_field_alphaAV();
1288 bool has_soundspeed_field = solver_config.ghost_has_soundspeed();
1290 bool has_B_field = solver_config.has_field_B_on_rho();
1291 bool has_psi_field = solver_config.has_field_psi_on_ch();
1292 bool has_curlB_field = solver_config.has_field_curlB();
1293 bool has_epsilon_field = solver_config.dust_config.has_epsilon_field();
1294 bool has_deltav_field = solver_config.dust_config.has_deltav_field();
1295 bool has_s_j_field = solver_config.dust_config.has_s_j_field();
1305 const u32 ialpha_AV = (has_alphaAV_field) ? pdl.
get_field_idx<Tscal>(
"alpha_AV") : 0;
1306 const u32 isoundspeed = (has_soundspeed_field) ? pdl.
get_field_idx<Tscal>(
"soundspeed") : 0;
1308 const u32 iB_on_rho = (has_B_field) ? pdl.
get_field_idx<Tvec>(
"B/rho") : 0;
1309 const u32 idB_on_rho = (has_B_field) ? pdl.
get_field_idx<Tvec>(
"dB/rho") : 0;
1310 const u32 ipsi_on_ch = (has_psi_field) ? pdl.
get_field_idx<Tscal>(
"psi/ch") : 0;
1311 const u32 idpsi_on_ch = (has_psi_field) ? pdl.
get_field_idx<Tscal>(
"dpsi/ch") : 0;
1312 const u32 icurlB = (has_curlB_field) ? pdl.
get_field_idx<Tvec>(
"curlB") : 0;
1314 bool do_MHD_debug = solver_config.do_MHD_debug();
1315 const u32 imag_pressure = (do_MHD_debug) ? pdl.
get_field_idx<Tvec>(
"mag_pressure") : -1;
1316 const u32 imag_tension = (do_MHD_debug) ? pdl.
get_field_idx<Tvec>(
"mag_tension") : -1;
1317 const u32 igas_pressure = (do_MHD_debug) ? pdl.
get_field_idx<Tvec>(
"gas_pressure") : -1;
1318 const u32 itensile_corr = (do_MHD_debug) ? pdl.
get_field_idx<Tvec>(
"tensile_corr") : -1;
1319 const u32 ipsi_propag = (do_MHD_debug) ? pdl.
get_field_idx<Tscal>(
"psi_propag") : -1;
1320 const u32 ipsi_diff = (do_MHD_debug) ? pdl.
get_field_idx<Tscal>(
"psi_diff") : -1;
1321 const u32 ipsi_cons = (do_MHD_debug) ? pdl.
get_field_idx<Tscal>(
"psi_cons") : -1;
1322 const u32 iu_mhd = (do_MHD_debug) ? pdl.
get_field_idx<Tscal>(
"u_mhd") : -1;
1324 const u32 iepsilon = (has_epsilon_field) ? pdl.
get_field_idx<Tscal>(
"epsilon") : 0;
1325 const u32 ideltav = (has_deltav_field) ? pdl.
get_field_idx<Tvec>(
"deltav") : 0;
1328 auto &ghost_layout_ptr = storage.ghost_layout;
1335 const u32 iaxyz_interf
1336 = (solver_config.has_axyz_in_ghost()) ? ghost_layout.
get_field_idx<Tvec>(
"axyz") : 0;
1338 const u32 isoundspeed_interf
1339 = (has_soundspeed_field) ? ghost_layout.
get_field_idx<Tscal>(
"soundspeed") : 0;
1341 const u32 iB_interf = (has_B_field) ? ghost_layout.
get_field_idx<Tvec>(
"B/rho") : 0;
1342 const u32 ipsi_interf = (has_psi_field) ? ghost_layout.
get_field_idx<Tscal>(
"psi/ch") : 0;
1343 const u32 icurlB_interf = (has_curlB_field) ? ghost_layout.
get_field_idx<Tvec>(
"curlB") : 0;
1345 const u32 iepsilon_interf
1346 = (has_epsilon_field) ? ghost_layout.
get_field_idx<Tscal>(
"epsilon") : 0;
1347 const u32 ideltav_interf = (has_deltav_field) ? ghost_layout.
get_field_idx<Tvec>(
"deltav") : 0;
1348 const u32 is_j_interf = (has_s_j_field) ? ghost_layout.
get_field_idx<Tscal>(
"s_j") : 0;
1355 auto pdat_interf = ghost_handle.template build_interface_native<PatchDataLayer>(
1356 storage.ghost_patch_cache.get(),
1358 PatchDataLayer pdat(ghost_layout_ptr);
1365 ghost_handle.template modify_interface_native<PatchDataLayer>(
1366 storage.ghost_patch_cache.get(),
1370 InterfaceBuildInfos binfo,
1374 PatchDataLayer &sender_patch = scheduler().patch_data.get_pdat(sender);
1375 PatchDataField<Tscal> &sender_omega = omega.get(sender);
1377 sender_patch.get_field<Tscal>(ihpart).append_subset_to(
1378 buf_idx, cnt, pdat.get_field<Tscal>(ihpart_interf));
1379 sender_patch.get_field<Tscal>(iuint).append_subset_to(
1380 buf_idx, cnt, pdat.get_field<Tscal>(iuint_interf));
1382 if (solver_config.has_axyz_in_ghost()) {
1383 sender_patch.get_field<Tvec>(iaxyz).append_subset_to(
1384 buf_idx, cnt, pdat.get_field<Tvec>(iaxyz_interf));
1387 sender_patch.get_field<Tvec>(ivxyz).append_subset_to(
1388 buf_idx, cnt, pdat.get_field<Tvec>(ivxyz_interf));
1390 sender_omega.append_subset_to(buf_idx, cnt, pdat.get_field<Tscal>(iomega_interf));
1392 if (has_soundspeed_field) {
1393 sender_patch.get_field<Tscal>(isoundspeed)
1394 .append_subset_to(buf_idx, cnt, pdat.get_field<Tscal>(isoundspeed_interf));
1398 sender_patch.get_field<Tvec>(iB_on_rho).append_subset_to(
1399 buf_idx, cnt, pdat.get_field<Tvec>(iB_interf));
1402 if (has_psi_field) {
1403 sender_patch.get_field<Tscal>(ipsi_on_ch)
1404 .append_subset_to(buf_idx, cnt, pdat.get_field<Tscal>(ipsi_interf));
1407 if (has_curlB_field) {
1408 sender_patch.get_field<Tvec>(icurlB).append_subset_to(
1409 buf_idx, cnt, pdat.get_field<Tvec>(icurlB_interf));
1412 if (has_epsilon_field) {
1413 sender_patch.get_field<Tscal>(iepsilon).append_subset_to(
1414 buf_idx, cnt, pdat.get_field<Tscal>(iepsilon_interf));
1417 if (has_deltav_field) {
1418 sender_patch.get_field<Tvec>(ideltav).append_subset_to(
1419 buf_idx, cnt, pdat.get_field<Tvec>(ideltav_interf));
1422 if (has_s_j_field) {
1423 sender_patch.get_field<Tscal>(is_j).append_subset_to(
1424 buf_idx, cnt, pdat.get_field<Tscal>(is_j_interf));
1428 ghost_handle.template modify_interface_native<PatchDataLayer>(
1429 storage.ghost_patch_cache.get(),
1433 InterfaceBuildInfos binfo,
1437 if (sycl::length(binfo.offset_speed) > 0) {
1438 pdat.get_field<Tvec>(ivxyz_interf).apply_offset(binfo.offset_speed);
1444 std::move(pdat_interf),
1445 storage.exchange_gz_node,
1446 solver_config.show_ghost_zone_graph);
1448 std::map<u64, u64> sz_interf_map;
1450 sz_interf_map[r] += pdat_interf.get_obj_cnt();
1453 storage.merged_patchdata_ghost.set(
1454 ghost_handle.template merge_native<PatchDataLayer, PatchDataLayer>(
1455 std::move(interf_pdat),
1457 PatchDataLayer pdat_new(ghost_layout_ptr);
1459 u32 or_elem = pdat.get_obj_cnt();
1460 pdat_new.reserve(or_elem + sz_interf_map[p.id_patch]);
1461 u32 total_elements = or_elem;
1463 PatchDataField<Tscal> &cur_omega = omega.get(p.id_patch);
1465 pdat_new.get_field<Tscal>(ihpart_interf).insert(pdat.get_field<Tscal>(ihpart));
1466 pdat_new.get_field<Tscal>(iuint_interf).insert(pdat.get_field<Tscal>(iuint));
1467 pdat_new.get_field<Tvec>(ivxyz_interf).insert(pdat.get_field<Tvec>(ivxyz));
1469 if (solver_config.has_axyz_in_ghost()) {
1470 pdat_new.get_field<Tvec>(iaxyz_interf).insert(pdat.get_field<Tvec>(iaxyz));
1473 pdat_new.get_field<Tscal>(iomega_interf).insert(cur_omega);
1475 if (has_soundspeed_field) {
1476 pdat_new.get_field<Tscal>(isoundspeed_interf)
1477 .insert(pdat.get_field<Tscal>(isoundspeed));
1481 pdat_new.get_field<Tvec>(iB_interf).insert(pdat.get_field<Tvec>(iB_on_rho));
1484 if (has_psi_field) {
1485 pdat_new.get_field<Tscal>(ipsi_interf)
1486 .insert(pdat.get_field<Tscal>(ipsi_on_ch));
1489 if (has_curlB_field) {
1490 pdat_new.get_field<Tvec>(icurlB_interf).insert(pdat.get_field<Tvec>(icurlB));
1493 if (has_epsilon_field) {
1494 pdat_new.get_field<Tscal>(iepsilon_interf)
1495 .insert(pdat.get_field<Tscal>(iepsilon));
1498 if (has_deltav_field) {
1499 pdat_new.get_field<Tvec>(ideltav_interf).insert(pdat.get_field<Tvec>(ideltav));
1502 if (has_s_j_field) {
1503 pdat_new.get_field<Tscal>(is_j_interf).insert(pdat.get_field<Tscal>(is_j));
1506 pdat_new.check_field_obj_cnt_match();
1511 pdat.insert_elements(pdat_interf);
1514 timer_interf.stop();
1515 storage.timings_details.interface += timer_interf.elapsed_sec();
1833 for (
auto &callbacks : timestep_callbacks) {
1834 if (callbacks.step_begin_callback) {
1839 Tscal t_current = get_time();
1840 Tscal dt = get_dt_sph();
1846 shambase::format(
"---------------- t = {}, dt = {} ----------------", t_current, dt));
1854 .update_load_balancing();
1855 scheduler().scheduler_step(
true,
true);
1857 .update_load_balancing();
1859 scheduler().scheduler_step(
false,
false);
1865 using namespace shamrock::patch;
1867 bool has_B_field = solver_config.has_field_B_on_rho();
1868 bool has_psi_field = solver_config.has_field_psi_on_ch();
1869 bool has_epsilon_field = solver_config.dust_config.has_epsilon_field();
1870 bool has_deltav_field = solver_config.dust_config.has_deltav_field();
1871 bool has_s_j_field = solver_config.dust_config.has_s_j_field();
1881 const u32 iB_on_rho = (has_B_field) ? pdl.
get_field_idx<Tvec>(
"B/rho") : 0;
1882 const u32 idB_on_rho = (has_B_field) ? pdl.
get_field_idx<Tvec>(
"dB/rho") : 0;
1883 const u32 ipsi_on_ch = (has_psi_field) ? pdl.
get_field_idx<Tscal>(
"psi/ch") : 0;
1884 const u32 idpsi_on_ch = (has_psi_field) ? pdl.
get_field_idx<Tscal>(
"dpsi/ch") : 0;
1885 const u32 iepsilon = (has_epsilon_field) ? pdl.
get_field_idx<Tscal>(
"epsilon") : 0;
1886 const u32 idtepsilon = (has_epsilon_field) ? pdl.
get_field_idx<Tscal>(
"dtepsilon") : 0;
1888 const u32 ids_j_dt = (has_s_j_field) ? pdl.
get_field_idx<Tscal>(
"ds_j_dt") : 0;
1889 const u32 ideltav = (has_deltav_field) ? pdl.
get_field_idx<Tvec>(
"deltav") : 0;
1890 const u32 idtdeltav = (has_deltav_field) ? pdl.
get_field_idx<Tvec>(
"dtdeltav") : 0;
1897 sink_update.accrete_particles(dt);
1898 ext_forces.point_mass_accrete_particles();
1900 sink_update.predictor_step(dt);
1905 using namespace shamrock::solvergraph;
1916 sink_update.compute_ext_forces();
1920 gen_serial_patch_tree();
1924 u64 Npart_all = scheduler().get_total_obj_count();
1926 if (solver_config.enable_particle_reordering
1927 && solve_logs.step_count % solver_config.particle_reordering_step_freq == 0) {
1928 logger::info_ln(
"SPH",
"Reordering particles at step ", solve_logs.step_count);
1936 using namespace shamrock::solvergraph;
1947 if (solver_config.self_grav_config.is_sg_on()) {
1949 auto constant_G = shamrock::solvergraph::IDataEdge<Tscal>::make_shared(
"",
"");
1953 constant_G.data = solver_config.get_constant_G();
1958 auto field_xyz = shamrock::solvergraph::FieldRefs<Tvec>::make_shared(
"",
"");
1964 auto &field = pdat.get_field<Tvec>(ixyz);
1965 field_xyz_refs.
add_obj(p.id_patch, std::ref(field));
1967 field_xyz_edge.set_refs(field_xyz_refs);
1973 auto field_axyz_ext = shamrock::solvergraph::FieldRefs<Tvec>::make_shared(
"",
"");
1979 auto &field = pdat.get_field<Tvec>(iaxyz_ext);
1980 field_axyz_ext_refs.
add_obj(p.id_patch, std::ref(field));
1982 field_axyz_ext_edge.set_refs(field_axyz_ext_refs);
1984 set_field_axyz_ext.
set_edges(field_axyz_ext);
1986 auto sizes = shamrock::solvergraph::Indexes<u32>::make_shared(
"",
"");
1992 sizes.indexes.add_obj(p.id_patch, pdat.get_obj_cnt());
1997 auto gpart_mass = shamrock::solvergraph::IDataEdge<Tscal>::make_shared(
"",
"");
2001 gpart_mass.data = solver_config.gpart_mass;
2006 set_gpart_mass.evaluate();
2007 set_constant_G.evaluate();
2008 set_field_xyz.evaluate();
2009 set_field_axyz_ext.evaluate();
2010 set_sizes.evaluate();
2013 std::get_if<SelfGravConfig::SofteningPlummer>(
2014 &solver_config.self_grav_config.softening_mode))
2017 if (solver_config.self_grav_config.is_none()) {
2019 }
else if (solver_config.self_grav_config.is_direct()) {
2022 std::get_if<SelfGravConfig::Direct>(&solver_config.self_grav_config.config));
2025 eps_grav, direct_config.reference_mode);
2026 self_gravity_direct_node.set_edges(
2027 sizes, gpart_mass, constant_G, field_xyz, field_axyz_ext);
2028 self_gravity_direct_node.
evaluate();
2030 }
else if (solver_config.self_grav_config.is_mm()) {
2033 std::get_if<SelfGravConfig::MM>(&solver_config.self_grav_config.config));
2035 auto run_sg_mm = [&](
auto mm_order_tag) {
2036 constexpr u32 order =
decltype(mm_order_tag)::value;
2038 eps_grav, mm_config.opening_angle, mm_config.reduction_level);
2039 self_gravity_mm_node.set_edges(
2040 sizes, gpart_mass, constant_G, field_xyz, field_axyz_ext);
2044 switch (mm_config.order) {
2045 case 1 : run_sg_mm(std::integral_constant<u32, 1>{});
break;
2046 case 2 : run_sg_mm(std::integral_constant<u32, 2>{});
break;
2047 case 3 : run_sg_mm(std::integral_constant<u32, 3>{});
break;
2048 case 4 : run_sg_mm(std::integral_constant<u32, 4>{});
break;
2049 case 5 : run_sg_mm(std::integral_constant<u32, 5>{});
break;
2053 }
else if (solver_config.self_grav_config.is_fmm()) {
2056 std::get_if<SelfGravConfig::FMM>(&solver_config.self_grav_config.config));
2058 auto run_sg_fmm = [&](
auto fmm_order_tag) {
2059 constexpr u32 order =
decltype(fmm_order_tag)::value;
2061 eps_grav, fmm_config.opening_angle, fmm_config.reduction_level);
2062 self_gravity_mm_node.set_edges(
2063 sizes, gpart_mass, constant_G, field_xyz, field_axyz_ext);
2067 switch (fmm_config.order) {
2068 case 1 : run_sg_fmm(std::integral_constant<u32, 1>{});
break;
2069 case 2 : run_sg_fmm(std::integral_constant<u32, 2>{});
break;
2070 case 3 : run_sg_fmm(std::integral_constant<u32, 3>{});
break;
2071 case 4 : run_sg_fmm(std::integral_constant<u32, 4>{});
break;
2072 case 5 : run_sg_fmm(std::integral_constant<u32, 5>{});
break;
2076 }
else if (solver_config.self_grav_config.is_sfmm()) {
2079 std::get_if<SelfGravConfig::SFMM>(&solver_config.self_grav_config.config));
2081 auto run_sg_sfmm = [&](
auto sfmm_order_tag) {
2082 constexpr u32 order =
decltype(sfmm_order_tag)::value;
2085 sfmm_config.opening_angle,
2086 sfmm_config.leaf_lowering,
2087 sfmm_config.reduction_level);
2088 self_gravity_mm_node.set_edges(
2089 sizes, gpart_mass, constant_G, field_xyz, field_axyz_ext);
2093 switch (sfmm_config.order) {
2094 case 1 : run_sg_sfmm(std::integral_constant<u32, 1>{});
break;
2095 case 2 : run_sg_sfmm(std::integral_constant<u32, 2>{});
break;
2096 case 3 : run_sg_sfmm(std::integral_constant<u32, 3>{});
break;
2097 case 4 : run_sg_sfmm(std::integral_constant<u32, 4>{});
break;
2098 case 5 : run_sg_sfmm(std::integral_constant<u32, 5>{});
break;
2104 "Self gravity config not supported, current state is : \n"
2105 + nlohmann::json{solver_config.self_grav_config}.dump(4));
2110 auto &merged_xyzh = storage.merged_xyzh.get();
2120 u32 iB_on_rho_interf = (has_B_field) ? ghost_layout.
get_field_idx<Tvec>(
"B/rho") : 0;
2121 u32 ipsi_on_rho_interf = (has_psi_field) ? ghost_layout.
get_field_idx<Tscal>(
"psi/ch") : 0;
2128 u32 corrector_iter_cnt = 0;
2129 bool need_rerun_corrector =
false;
2135 if (corrector_iter_cnt == 50) {
2137 "the corrector has made over 50 loops, either their is a bug, either you are using "
2138 "a dt that is too large");
2144 if (solver_config.has_field_alphaAV()) {
2146 std::shared_ptr<shamrock::solvergraph::PatchDataLayerRefs> patchdatas
2147 = std::make_shared<shamrock::solvergraph::PatchDataLayerRefs>(
2148 "patchdata_layer_ref",
"patchdata_layer_ref");
2150 auto node_set_edge = scheduler().get_node_set_edge_patchdata_layer_refs();
2151 node_set_edge->set_edges(patchdatas);
2152 node_set_edge->evaluate();
2155 scheduler().get_layout_ptr_old(),
"alpha_AV");
2156 node_copy.set_edges(patchdatas, storage.alpha_av_updated);
2160 if (solver_config.has_field_dtdivv()) {
2162 if (solver_config.combined_dtdiv_divcurlv_compute) {
2163 if (solver_config.has_field_dtdivv()) {
2165 .update_dtdivv(
true);
2169 if (solver_config.has_field_divv()) {
2174 if (solver_config.has_field_curlv()) {
2179 if (solver_config.has_field_dtdivv()) {
2181 .update_dtdivv(
false);
2186 if (solver_config.has_field_divv()) {
2191 if (solver_config.has_field_curlv()) {
2208 if (solver_config.has_field_alphaAV()) {
2213 using InterfaceBuildInfos =
2217 time_interf.
start();
2219 auto field_interf = ghost_handle.template build_interface_native<PatchDataField<Tscal>>(
2220 storage.ghost_patch_cache.get(),
2223 InterfaceBuildInfos binfo,
2228 return sender_field.make_new_from_subset(buf_idx, cnt);
2232 = ghost_handle.communicate_pdatfield(
2233 std::move(field_interf), 1, storage.exchange_gz_alpha);
2237 std::move(interf_pdat),
2240 = comp_field_send.
get_field(p.id_patch);
2241 return receiver_field.duplicate();
2244 mpdat.insert(pdat_interf);
2248 storage.timings_details.interface += time_interf.
elapsed_sec();
2250 storage.alpha_av_ghost.set(std::move(merged_field));
2256 constexpr bool debug_interfaces =
false;
2257 if constexpr (debug_interfaces) {
2259 if (solver_config.do_debug_dump) {
2262 = storage.merged_patchdata_ghost.get();
2269 merged_xyzh.get(cur_p.
id_patch).field_pos.get_buf());
2270 sycl::buffer<Tvec> &buf_vxyz = mpdat.get_field_buf_ref<Tvec>(ivxyz_interf);
2271 sycl::buffer<Tscal> &buf_hpart = mpdat.get_field_buf_ref<Tscal>(ihpart_interf);
2275 SHAM_ASSERT(merged_patch.total_elements == total_elements);
2279 solver_config.gpart_mass,
2285 make_interface_debug_phantom_dump(info).gen_file().write_to_file(
2286 solver_config.debug_dump_filename);
2293 shamlog_debug_ln(
"sph::BasicGas",
"compute force");
2300 bool has_luminosity = solver_config.compute_luminosity;
2302 if (has_luminosity) {
2306 .set_refs(storage.merged_xyzh.get()
2309 return std::ref(mpdat.get_field<Tscal>(
2313 auto uint_with_ghost = shamrock::solvergraph::FieldRefs<Tscal>::make_shared(
"",
"");
2316 .set_refs(storage.merged_xyzh.get()
2319 return std::ref(mpdat.get_field<Tscal>(1));
2323 set_uint_with_ghost_refs(
2326 = storage.merged_patchdata_ghost.
get();
2331 scheduler().for_each_patchdata_nonempty(
2335 auto &field = mpdat.get_field<Tscal>(iuint_interf);
2336 field_uint_with_ghost_refs.
add_obj(p.id_patch, std::ref(field));
2339 field_uint_with_ghost_edge.set_refs(field_uint_with_ghost_refs);
2342 set_uint_with_ghost_refs.
set_edges(uint_with_ghost);
2344 auto luminosity = shamrock::solvergraph::FieldRefs<Tscal>::make_shared(
"",
"");
2347 set_luminosity_refs(
2350 = storage.merged_patchdata_ghost.
get();
2355 scheduler().for_each_patchdata_nonempty(
2357 auto &field = pdat.get_field<Tscal>(iluminosity);
2358 field_luminosity_refs.
add_obj(p.id_patch, std::ref(field));
2360 field_luminosity_edge.set_refs(field_luminosity_refs);
2363 set_luminosity_refs.
set_edges(luminosity);
2365 set_uint_with_ghost_refs.evaluate();
2366 set_luminosity_refs.evaluate();
2368 Tscal alpha_u = solver_config.artif_viscosity.get_alpha_u().value();
2371 solver_config.gpart_mass, alpha_u};
2373 compute_luminosity.set_edges(
2374 storage.part_counts,
2375 storage.neigh_cache,
2376 storage.positions_with_ghosts,
2377 storage.hpart_with_ghosts,
2395 shamlog_debug_ln(
"sph::BasicGas",
"leapfrog corrector");
2396 utility.fields_leapfrog_corrector<Tvec>(
2397 ivxyz, iaxyz, storage.old_axyz.get(), vepsilon_v_sq, dt / 2);
2398 utility.fields_leapfrog_corrector<Tscal>(
2399 iuint, iduint, storage.old_duint.get(), uepsilon_u_sq, dt / 2);
2401 if (solver_config.has_field_B_on_rho()) {
2404 utility.fields_leapfrog_corrector<Tvec>(
2405 iB_on_rho, idB_on_rho, storage.old_dB_on_rho.get(), BOR_epsilon_BOR_sq, dt / 2);
2407 if (solver_config.has_field_B_on_rho()) {
2410 utility.fields_leapfrog_corrector<Tscal>(
2411 ipsi_on_ch, idpsi_on_ch, storage.old_dpsi_on_ch.get(), POC_epsilon_POC_sq, dt / 2);
2414 if (solver_config.dust_config.has_epsilon_field()) {
2417 utility.fields_leapfrog_corrector<Tscal>(
2418 iepsilon, idtepsilon, storage.old_dtepsilon.get(), epsilon_epsilon_sq, dt / 2);
2421 if (solver_config.dust_config.has_deltav_field()) {
2424 utility.fields_leapfrog_corrector<Tvec>(
2425 ideltav, idtdeltav, storage.old_dtdeltav.get(), epsilon_deltav_sq, dt / 2);
2428 if (solver_config.dust_config.has_s_j_field()) {
2430 "s_j s_j^2", solver_config.dust_config.get_dust_nvar());
2431 bool ensure_positivity
2432 = solver_config.dust_config.get_monofluid_tva().ensure_s_j_positivity;
2433 if (ensure_positivity) {
2434 utility.fields_leapfrog_corrector_positive_only<Tscal>(
2435 is_j, ids_j_dt, storage.old_ds_j_dt.get(), s_j_s_j_sq, dt / 2);
2437 utility.fields_leapfrog_corrector<Tscal>(
2438 is_j, ids_j_dt, storage.old_ds_j_dt.get(), s_j_s_j_sq, dt / 2);
2442 storage.old_axyz.reset();
2443 storage.old_duint.reset();
2444 if (solver_config.has_field_B_on_rho()) {
2445 storage.old_dB_on_rho.reset();
2447 if (solver_config.has_field_B_on_rho()) {
2448 storage.old_dpsi_on_ch.reset();
2451 if (solver_config.dust_config.has_epsilon_field()) {
2452 storage.old_dtepsilon.reset();
2455 if (solver_config.dust_config.has_deltav_field()) {
2456 storage.old_dtdeltav.reset();
2459 if (solver_config.dust_config.has_s_j_field()) {
2460 storage.old_ds_j_dt.reset();
2463 Tscal rank_veps_v = sycl::sqrt(vepsilon_v_sq.compute_rank_max());
2468 Tscal sum_vsq = utility.compute_rank_dot_sum<Tvec>(ivxyz);
2470 Tscal vmean_sq = shamalgs::collective::allreduce_sum(sum_vsq) / Tscal(Npart_all);
2472 Tscal vmean = sycl::sqrt(vmean_sq);
2474 Tscal rank_eps_v = rank_veps_v / vmean;
2480 Tscal eps_v = shamalgs::collective::allreduce_max(rank_eps_v);
2482 shamlog_debug_ln(
"BasicGas",
"epsilon v :", eps_v);
2489 "the corrector tolerance are broken the step will "
2490 "be re rerunned\n eps_v = {}",
2493 need_rerun_corrector =
true;
2494 set_cfl_multipler(get_cfl_multipler() / 2);
2498 need_rerun_corrector =
false;
2501 if (!need_rerun_corrector) {
2503 sink_update.corrector_step(dt);
2506 if (solver_config.has_field_alphaAV()) {
2514 = pdat.get_field<Tscal>(ialpha_AV).get_buf();
2516 = alpha_av_updated.get_field(cur_p.
id_patch).get_buf();
2518 auto &q = shamsys::instance::get_compute_scheduler().
get_queue();
2522 auto alpha_av_updated = buf_alpha_av_updated.
get_read_access(depends_list);
2524 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
2525 shambase::parallel_for(
2526 cgh, pdat.get_obj_cnt(),
"write back alpha_av", [=](
i32 id_a) {
2527 alpha_av[id_a] = alpha_av_updated[id_a];
2536 shamlog_debug_ln(
"BasicGas",
"computing next CFL");
2540 = storage.merged_xyzh.get().template map<u32>(
2542 return scheduler().patch_data.get_pdat(
id).get_obj_cnt();
2545 std::shared_ptr<shamrock::solvergraph::Field<Tscal>> vsig_max_dt
2546 = std::make_shared<shamrock::solvergraph::Field<Tscal>>(
2547 1,
"vsig_a",
"v_{\\rm sig}");
2550 std::shared_ptr<shamrock::solvergraph::Field<Tscal>> vclean_dt;
2551 if (has_psi_field) {
2552 vclean_dt = std::make_shared<shamrock::solvergraph::Field<Tscal>>(
2553 1,
"vclean_a",
"v_{\\rm clean}");
2558 = storage.merged_patchdata_ghost.
get();
2564 = merged_xyzh.get(cur_p.
id_patch).template get_field_buf_ref<Tvec>(0);
2567 = mpdat.get_field_buf_ref<Tscal>(ihpart_interf);
2577 sycl::range range_npart{pdat.get_obj_cnt()};
2586 auto &q = shamsys::instance::get_compute_scheduler().get_queue();
2591 auto hpart = buf_hpart.get_read_access(depends_list);
2592 auto u = buf_uint.get_read_access(depends_list);
2593 auto pressure = buf_pressure.get_read_access(depends_list);
2596 auto particle_looper_ptrs = pcache.get_read_access(depends_list);
2599 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
2600 const Tscal pmass = solver_config.gpart_mass;
2601 const Tscal alpha_u = 1.0;
2602 const Tscal alpha_AV = 1.0;
2603 const Tscal beta_AV = 2.0;
2607 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
2609 shambase::parallel_for(
2610 cgh, pdat.get_obj_cnt(),
"compute vsig", [=](
i32 id_a) {
2611 using namespace shamrock::sph;
2613 Tvec sum_axyz = {0, 0, 0};
2615 Tscal h_a = hpart[id_a];
2617 Tvec xyz_a = xyz[id_a];
2618 Tvec vxyz_a = vxyz[id_a];
2620 Tscal rho_a = rho_h(pmass, h_a, Kernel::hfactd);
2621 Tscal rho_a_sq = rho_a * rho_a;
2622 Tscal rho_a_inv = 1. / rho_a;
2624 Tscal P_a = pressure[id_a];
2626 const Tscal u_a = u[id_a];
2628 Tscal cs_a = cs[id_a];
2632 particle_looper.for_each_object(id_a, [&](
u32 id_b) {
2634 Tvec dr = xyz_a - xyz[id_b];
2635 Tscal rab2 = sycl::dot(dr, dr);
2636 Tscal h_b = hpart[id_b];
2638 if (rab2 > h_a * h_a * Rker2 && rab2 > h_b * h_b * Rker2) {
2642 Tscal rab = sycl::sqrt(rab2);
2643 Tvec vxyz_b = vxyz[id_b];
2644 Tvec v_ab = vxyz_a - vxyz_b;
2645 const Tscal u_b = u[id_b];
2647 Tvec r_ab_unit = dr / rab;
2650 r_ab_unit = {0, 0, 0};
2653 Tscal rho_b = rho_h(pmass, h_b, Kernel::hfactd);
2654 Tscal P_b = pressure[id_b];
2655 Tscal cs_b = cs[id_b];
2656 Tscal v_ab_r_ab = sycl::dot(v_ab, r_ab_unit);
2657 Tscal abs_v_ab_r_ab = sycl::fabs(v_ab_r_ab);
2662 const Tscal alpha_a = alpha_AV;
2663 const Tscal alpha_b = alpha_AV;
2665 Tscal vsig_a = alpha_a * cs_a + beta_AV * abs_v_ab_r_ab;
2667 vsig_max = sycl::fmax(vsig_max, vsig_a);
2670 vsig[id_a] = vsig_max;
2674 if (has_psi_field) {
2676 Tscal
const mu_0 = solver_config.get_constant_mu_0();
2679 Tvec *B_on_rho = mpdat.get_field_buf_ref<Tvec>(iB_on_rho_interf)
2680 .get_write_access(depends_list);
2684 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
2685 const Tscal pmass = solver_config.gpart_mass;
2689 constexpr Tscal Rker2 = Kernel::Rkern * Kernel::Rkern;
2691 shambase::parallel_for(
2692 cgh, pdat.get_obj_cnt(),
"compute vclean", [=](
i32 id_a) {
2693 using namespace shamrock::sph;
2695 Tscal h_a = hpart[id_a];
2696 Tscal rho_a = rho_h(pmass, h_a, Kernel::hfactd);
2697 const Tscal u_a = u[id_a];
2698 Tscal cs_a = cs[id_a];
2699 Tvec B_a = B_on_rho[id_a] * rho_a;
2701 Tscal vclean_a = shamphys::MHD_physics<Tvec, Tscal>::v_shock(
2702 cs_a, B_a, rho_a, mu_0);
2704 vclean[id_a] = vclean_a;
2707 mpdat.get_field_buf_ref<Tvec>(iB_on_rho_interf).complete_event_state(e);
2713 buf_hpart.complete_event_state(e);
2714 buf_uint.complete_event_state(e);
2715 buf_pressure.complete_event_state(e);
2721 pcache.complete_event_state(resulting_events);
2725 std::shared_ptr<shamrock::solvergraph::Field<Tscal>> cfl_dt
2726 = std::make_shared<shamrock::solvergraph::Field<Tscal>>(
2727 1,
"cfl_dt",
"\\Delta t_{cfl}");
2730 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tvec>> axyz_refs
2731 = std::make_shared<shamrock::solvergraph::FieldRefs<Tvec>>(
"axyz",
"\\mathbf{a}");
2732 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> hpart_refs
2733 = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"hpart",
"h");
2735 map_field_refs(scheduler(), iaxyz, *axyz_refs);
2736 map_field_refs_ext(scheduler(), mpdats, ihpart_interf, *hpart_refs);
2738 auto &q = shamsys::instance::get_compute_scheduler().get_queue();
2740 auto reset_dt_part_field = [&]() {
2741 if (solver_config.should_save_dt_to_fields()) {
2745 = pdat.get_field_buf_ref<Tscal>(idt_part);
2746 buf_dt_part.
fill(shambase::get_infty<Tscal>());
2751 auto save_dt_min_to_dt_part = [&]() {
2752 if (solver_config.should_save_dt_to_fields()) {
2756 = pdat.get_field_buf_ref<Tscal>(idt_part);
2764 [](
u32 id_a,
const Tscal *dt, Tscal *dt_part) {
2765 dt_part[id_a] = sycl::min(dt_part[id_a], dt[id_a]);
2772 auto reset_cfl_dt = [&]() {
2774 cfl_dt->get_buf(cur_p.
id_patch).fill(shambase::get_infty<Tscal>());
2778 Tscal C_cour = solver_config.cfl_config.cfl_cour * get_cfl_multipler();
2779 Tscal C_force = solver_config.cfl_config.cfl_force * get_cfl_multipler();
2780 Tscal eta_phi = solver_config.cfl_config.eta_sink;
2782 std::shared_ptr<shamrock::solvergraph::ScalarEdge<Tscal>> C_cour_edge
2783 = std::make_shared<shamrock::solvergraph::ScalarEdge<Tscal>>(
"C_cour",
"C_{cour}");
2784 C_cour_edge->value = C_cour;
2785 std::shared_ptr<shamrock::solvergraph::ScalarEdge<Tscal>> C_force_edge
2786 = std::make_shared<shamrock::solvergraph::ScalarEdge<Tscal>>(
2787 "C_force",
"C_{force}");
2788 C_force_edge->value = C_force;
2789 std::shared_ptr<shamrock::solvergraph::ScalarEdge<Tscal>> eta_phi_edge
2790 = std::make_shared<shamrock::solvergraph::ScalarEdge<Tscal>>(
2791 "eta_phi",
"\\eta_{\\phi}");
2792 eta_phi_edge->value = eta_phi;
2794 std::shared_ptr<ComputeCFLCourant<Tscal>> compute_cfl_courant
2795 = std::make_shared<ComputeCFLCourant<Tscal>>();
2796 compute_cfl_courant->set_edges(
2797 storage.part_counts, C_cour_edge, hpart_refs, vsig_max_dt, cfl_dt);
2799 std::shared_ptr<ComputeCFLForce<Tvec>> compute_cfl_force
2800 = std::make_shared<ComputeCFLForce<Tvec>>();
2801 compute_cfl_force->set_edges(
2802 storage.part_counts, C_force_edge, hpart_refs, axyz_refs, cfl_dt);
2804 std::shared_ptr<ComputeCFLDivBCleaning<Tscal>> compute_cfl_divB_cleaning;
2805 if (has_psi_field) {
2806 compute_cfl_divB_cleaning = std::make_shared<ComputeCFLDivBCleaning<Tscal>>();
2807 compute_cfl_divB_cleaning->set_edges(
2808 storage.part_counts, C_cour_edge, hpart_refs, vclean_dt, cfl_dt);
2811 std::shared_ptr<ComputeCFLDust1Fluid<Tvec>> compute_cfl_dust1_fluid;
2812 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tscal>> s_j_refs;
2813 std::shared_ptr<shamrock::solvergraph::ScalarEdge<Tscal>> hfactd_edge;
2815 if (solver_config.dust_config.has_s_j_field()) {
2816 u32 ndust = solver_config.dust_config.get_dust_nvar();
2818 compute_cfl_dust1_fluid = std::make_shared<ComputeCFLDust1Fluid<Tvec>>(ndust);
2821 = storage.solver_graph
2822 .template get_edge_ptr<shamrock::solvergraph::Field<Tscal>>(
"Ts_j");
2825 = storage.solver_graph
2826 .template get_edge_ptr<shamrock::solvergraph::ScalarEdge<Tscal>>(
2829 s_j_refs = std::make_shared<shamrock::solvergraph::FieldRefs<Tscal>>(
"s_j",
"s_j");
2831 hfactd_edge = std::make_shared<shamrock::solvergraph::ScalarEdge<Tscal>>(
2832 "hfactd",
"hfactd");
2833 hfactd_edge->value = Kernel::hfactd;
2835 map_field_refs(scheduler(), is_j, *s_j_refs);
2837 std::shared_ptr<shamrock::solvergraph::ScalarEdge<Tscal>> C_1fluid_edge
2838 = std::make_shared<shamrock::solvergraph::ScalarEdge<Tscal>>(
2839 "C_1fluid",
"C_{1fluid}");
2840 C_1fluid_edge->value
2841 = solver_config.dust_config.get_monofluid_tva().C_1_fluid * get_cfl_multipler();
2843 compute_cfl_dust1_fluid->set_edges(
2844 storage.part_counts,
2855 std::shared_ptr<ComputeCFLDustDrift<Tvec>> compute_cfl_dust_drift;
2856 std::shared_ptr<shamrock::solvergraph::ScalarEdge<Tscal>> C_drift_edge;
2857 std::shared_ptr<shamrock::solvergraph::ScalarEdge<Tscal>> cfl_density_threshold_edge;
2858 std::shared_ptr<shamrock::solvergraph::FieldRefs<Tvec>> delta_v_refs;
2860 if (solver_config.dust_config.has_s_j_field()) {
2861 u32 ndust = solver_config.dust_config.get_dust_nvar();
2863 compute_cfl_dust_drift = std::make_shared<ComputeCFLDustDrift<Tvec>>(ndust);
2865 delta_v_refs = std::make_shared<shamrock::solvergraph::FieldRefs<Tvec>>(
2866 "delta_v",
"delta_v");
2868 map_field_refs(scheduler(), idelta_v, *delta_v_refs);
2870 auto &cfg_monofluid_tva = solver_config.dust_config.get_monofluid_tva();
2872 C_drift_edge = std::make_shared<shamrock::solvergraph::ScalarEdge<Tscal>>(
2873 "C_drift",
"C_{drift}");
2874 C_drift_edge->value = cfg_monofluid_tva.C_drift * get_cfl_multipler();
2876 cfl_density_threshold_edge
2877 = std::make_shared<shamrock::solvergraph::ScalarEdge<Tscal>>(
2878 "cfl_density_threshold",
"cfl_density_threshold");
2879 cfl_density_threshold_edge->value = cfg_monofluid_tva.cfl_density_threshold;
2882 = storage.solver_graph
2883 .template get_edge_ptr<shamrock::solvergraph::ScalarEdge<Tscal>>(
2886 compute_cfl_dust_drift->set_edges(
2887 storage.part_counts,
2889 cfl_density_threshold_edge,
2898 bool show_cfl_detail = solver_config.show_cfl_detail;
2899 std::vector<std::pair<std::string, Tscal>> cfl_detail;
2901 auto save_cfl_detail = [&](
const char *key) {
2902 if (show_cfl_detail) {
2903 save_dt_min_to_dt_part();
2904 cfl_detail.push_back(
2905 {std::string(key), cfl_dt->get_native().compute_rank_min()});
2910 reset_dt_part_field();
2913 compute_cfl_courant->evaluate();
2914 save_cfl_detail(
"courant");
2916 compute_cfl_force->evaluate();
2917 save_cfl_detail(
"force");
2919 if (has_psi_field) {
2920 compute_cfl_divB_cleaning->evaluate();
2921 save_cfl_detail(
"divB_cleaning");
2924 if (solver_config.dust_config.has_s_j_field()) {
2925 compute_cfl_dust1_fluid->evaluate();
2926 save_cfl_detail(
"dust1_fluid");
2928 compute_cfl_dust_drift->evaluate();
2929 save_cfl_detail(
"dust_drift");
2932 if (!show_cfl_detail) {
2933 save_dt_min_to_dt_part();
2934 cfl_detail.push_back({
"all SPH", cfl_dt->get_native().compute_rank_min()});
2937 auto &sync = scheduler().synchronized_data;
2942 Tscal sink_sink_cfl = shambase::get_infty<Tscal>();
2944 Tscal G = solver_config.get_constant_G();
2946 auto &mass = get_sink_mass<Tvec>(sync);
2947 auto &acc_ext = get_sink_acc_ext<Tvec>(sync);
2949 for (
u32 i = 0; i < pos.size(); i++) {
2950 Tscal sink_sink_cfl_i = shambase::get_infty<Tscal>();
2952 Tvec f_i = acc_ext[i];
2954 Tscal grad_phi_i_sq = sham::dot(f_i, f_i);
2956 if (grad_phi_i_sq == 0) {
2960 for (
u32 j = 0; j < pos.size(); j++) {
2965 Tvec rij = pos[i] - pos[j];
2966 Tscal rij_scal = sycl::length(rij);
2968 Tscal phi_ij = G * mass[j] / rij_scal;
2969 Tscal term_ij = sham::abs(phi_ij) / grad_phi_i_sq;
2970 Tscal dt_ij = C_force * eta_phi * sycl::sqrt(term_ij);
2972 sink_sink_cfl_i = sham::min(sink_sink_cfl_i, dt_ij);
2975 sink_sink_cfl = sham::min(sink_sink_cfl, sink_sink_cfl_i);
2978 cfl_detail.push_back({
"sink_sink", sink_sink_cfl});
2981 Tscal rank_dt = shambase::get_infty<Tscal>();
2982 for (
auto &[key, value] : cfl_detail) {
2983 rank_dt = sham::min(rank_dt, value);
2986 if (show_cfl_detail) {
2987 for (
auto &[key, value] : cfl_detail) {
2988 value = shamalgs::collective::allreduce_min(value);
2993 table.add_double_rule();
2994 table.add_data({
"key",
"value"}, shambase::table::center);
2995 table.add_double_rule();
2996 for (
auto &[key, value] : cfl_detail) {
2998 {key, shambase::format(
"{:.2e}", value)}, shambase::table::right);
3005 next_cfl = shamalgs::collective::allreduce_min(rank_dt);
3009 "sph::Model",
"cfl dt =", next_cfl,
"cfl multiplier :", get_cfl_multipler());
3015 if (solver_config.has_field_soundspeed()) {
3026 sycl::range range_npart{pdat.get_obj_cnt()};
3030 auto &q = shamsys::instance::get_compute_scheduler().get_queue();
3033 auto cs_in = buf_cs_in.get_read_access(depends_list);
3036 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
3037 const Tscal pmass = solver_config.gpart_mass;
3040 sycl::range<1>{pdat.get_obj_cnt()}, [=](sycl::item<1> item) {
3041 cs[item] = cs_in[item];
3045 buf_cs_in.complete_event_state(e);
3052 corrector_iter_cnt++;
3054 if (solver_config.has_field_alphaAV()) {
3055 storage.alpha_av_ghost.reset();
3057 }
while (need_rerun_corrector);
3059 reset_merge_ghosts_fields();
3066 for (
auto it = timestep_callbacks.rbegin(); it != timestep_callbacks.rend(); ++it) {
3067 if (it->step_end_callback) {
3080 = (mem_perf_infos_end.
time_alloc_device - mem_perf_infos_start.time_alloc_device)
3081 + (mem_perf_infos_end.
time_free_device - mem_perf_infos_start.time_free_device);
3082 f64 t_host_alloc = (mem_perf_infos_end.
time_alloc_host - mem_perf_infos_start.time_alloc_host)
3083 + (mem_perf_infos_end.
time_free_host - mem_perf_infos_start.time_free_host);
3085 u64 rank_count = scheduler().get_rank_count();
3086 f64 rate =
f64(rank_count) / tstep.elapsed_sec();
3088 u64 npatch = scheduler().patch_list.local.size();
3092 std::string log_step = report_perf_timestep(
3096 tstep.elapsed_sec(),
3102 system_metrics_delta,
3103 shamsys::has_reporter());
3108 "sph::Model",
"estimated rate :", dt * (3600 / tstep.elapsed_sec()),
"(tsim/hr)");
3111 solve_logs.register_log(
3117 tstep.elapsed_sec(),
3119 system_metrics_delta});
3121 storage.timings_details.reset();
3123 reset_serial_patch_tree();
3124 reset_ghost_handler();
3130 storage.merged_xyzh.reset();
3132 clear_merged_pos_trees();
3133 clear_ghost_cache();
3134 reset_presteps_rint();
3135 reset_neighbors_cache();
3139 set_next_dt(next_cfl);
3140 set_time(t_current + dt);
3142 auto get_next_cfl_mult = [&]() {
3143 Tscal cfl_m = get_cfl_multipler();
3144 Tscal stiff = solver_config.cfl_config.cfl_multiplier_stiffness;
3146 return (cfl_m * stiff + 1.) / (stiff + 1.);
3149 set_cfl_multipler(get_next_cfl_mult());
3154 log.npart = rank_count;
3155 log.tcompute = tstep.elapsed_sec();