45template<
class Tvec,
template<
class>
class SPHKernel>
46f64 shammodels::sph::Model<Tvec, SPHKernel>::evolve_once_time_expl(
f64 t_curr,
f64 dt_input) {
47 auto tmp = solver.evolve_once_time_expl(t_curr, dt_input);
48 solver.print_timestep_logs();
52template<
class Tvec,
template<
class>
class SPHKernel>
54 return solver.evolve_once();
57template<
class Tvec,
template<
class>
class SPHKernel>
60 if (solver.solver_config.scheduler_conf.split_load_value == 0) {
62 "Scheduler load value should be greater than 0");
65 solver.init_required_fields();
67 solver.solver_config.scheduler_conf.split_load_value,
68 solver.solver_config.scheduler_conf.merge_load_value);
70 using namespace shamrock::patch;
76 shamlog_debug_ln(
"Sys",
"build local scheduler tables");
82 solver.init_ghost_layout();
84 solver.ensure_time_state_edges();
89 solver.init_solver_graph();
96template<
class Tvec,
template<
class>
class SPHKernel>
97u64 shammodels::sph::Model<Tvec, SPHKernel>::get_total_part_count() {
99 return shamalgs::collective::allreduce_sum(sched.get_rank_count());
102template<
class Tvec,
template<
class>
class SPHKernel>
103f64 shammodels::sph::Model<Tvec, SPHKernel>::total_mass_to_part_mass(
f64 totmass) {
104 return totmass / get_total_part_count();
107template<
class Tvec,
template<
class>
class SPHKernel>
108auto shammodels::sph::Model<Tvec, SPHKernel>::get_closest_part_to(Tvec pos) -> Tvec {
111 using namespace shamrock::patch;
113 Tvec best_dr = shambase::VectorProperties<Tvec>::get_max();
114 Tscal best_dist2 = shambase::VectorProperties<Tscal>::get_max();
119 auto acc = pdat.get_field<Tvec>(0).get_buf().copy_to_stdvec();
121 u32 cnt = pdat.get_obj_cnt();
123 for (
u32 i = 0; i < cnt; i++) {
126 Tscal dist2 = sycl::dot(dr, dr);
127 if (dist2 < best_dist2) {
134 std::vector<Tvec> list_dr{};
141 best_dr = shambase::VectorProperties<Tvec>::get_max();
142 best_dist2 = shambase::VectorProperties<Tscal>::get_max();
144 for (Tvec tmp : list_dr) {
146 Tscal dist2 = sycl::dot(dr, dr);
147 if (dist2 < best_dist2) {
153 return pos + best_dr;
156template<
class Tvec,
template<
class>
class SPHKernel>
157void shammodels::sph::Model<Tvec, SPHKernel>::remap_positions(std::function<Tvec(Tvec)> map) {
160 using namespace shamrock::patch;
164 auto &
xyz = pdat.get_field<Tvec>(0).get_buf();
165 auto acc =
xyz.copy_to_stdvec();
167 u32 cnt = pdat.get_obj_cnt();
169 for (
u32 i = 0; i < cnt; i++) {
170 acc[i] = map(acc[i]);
173 xyz.copy_from_stdvec(acc);
176 modules::ComputeLoadBalanceValue<Tvec, SPHKernel>(ctx, solver.solver_config, solver.storage)
177 .update_load_balancing();
186 reatrib.reatribute_patch_objects(sptree,
"xyz");
187 sched.check_patchdata_locality_correctness();
190 modules::ComputeLoadBalanceValue<Tvec, SPHKernel>(ctx, solver.solver_config, solver.storage)
191 .update_load_balancing();
201 reatrib.reatribute_patch_objects(sptree,
"xyz");
202 sched.check_patchdata_locality_correctness();
219 auto [m, M] = sched.get_box_tranform<Tvec>();
227 reatrib.reatribute_patch_objects(sptree,
"xyz");
228 sched.check_patchdata_locality_correctness();
240 reatrib.reatribute_patch_objects(sptree,
"xyz");
241 sched.check_patchdata_locality_correctness();
244 std::string log =
"";
246 using namespace shamrock::patch;
249 u32 largest_count = 0;
252 u32 tmp = pdat.get_obj_cnt();
253 smallest_count = sham::min(tmp, smallest_count);
254 largest_count = sham::max(tmp, largest_count);
257 smallest_count = shamalgs::collective::allreduce_min(smallest_count);
258 largest_count = shamalgs::collective::allreduce_max(largest_count);
262 "Model",
"current particle counts : min = ", smallest_count,
"max = ", largest_count);
277template<
class Tvec,
template<
class>
class SPHKernel>
278void shammodels::sph::Model<Tvec, SPHKernel>::push_particle(
279 std::vector<Tvec> &part_pos_insert,
280 std::vector<Tscal> &part_hpart_insert,
281 std::vector<Tscal> &part_u_insert) {
284 using namespace shamrock::patch;
288 std::string log =
"";
295 std::vector<Tvec> vec_acc;
296 std::vector<Tscal> hpart_acc;
297 std::vector<Tscal> u_acc;
298 for (
u32 i = 0; i < part_pos_insert.size(); i++) {
299 Tvec r = part_pos_insert[i];
300 Tscal u = part_u_insert[i];
301 if (patch_coord.contain_pos(r)) {
302 vec_acc.push_back(r);
303 hpart_acc.push_back(part_hpart_insert[i]);
308 if (vec_acc.size() == 0) {
312 log += shambase::format(
313 "\n rank = {} patch id={}, add N={} particles, coords = {} {}",
321 tmp.resize(vec_acc.size());
325 u32 len = vec_acc.size();
327 = tmp.get_field<Tvec>(sched.pdl_old().get_field_idx<Tvec>(
"xyz"));
328 sycl::buffer<Tvec> buf(vec_acc.data(), len);
329 f.override(buf, len);
333 u32 len = vec_acc.size();
335 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"hpart"));
336 sycl::buffer<Tscal> buf(hpart_acc.data(), len);
337 f.override(buf, len);
341 u32 len = u_acc.size();
343 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"uint"));
344 sycl::buffer<Tscal> buf(u_acc.data(), len);
345 f.override(buf, len);
348 pdat.insert_elements(tmp);
350 sched.check_patchdata_locality_correctness();
352 std::string log_gathered =
"";
360 modules::ComputeLoadBalanceValue<Tvec, SPHKernel>(ctx, solver.solver_config, solver.storage)
361 .update_load_balancing();
363 post_insert_data<Tvec>(sched);
367template<
class Tvec,
template<
class>
class SPHKernel>
368void shammodels::sph::Model<Tvec, SPHKernel>::push_particle_mhd(
369 std::vector<Tvec> &part_pos_insert,
370 std::vector<Tscal> &part_hpart_insert,
371 std::vector<Tscal> &part_u_insert,
372 std::vector<Tvec> &part_B_on_rho_insert,
373 std::vector<Tscal> &part_psi_on_ch_insert) {
376 using namespace shamrock::patch;
380 std::string log =
"";
387 std::vector<Tvec> vec_acc;
388 std::vector<Tscal> hpart_acc;
389 std::vector<Tscal> u_acc;
390 std::vector<Tvec> B_on_rho_acc;
391 std::vector<Tscal> psi_on_ch_acc;
392 for (
u32 i = 0; i < part_pos_insert.size(); i++) {
393 Tvec r = part_pos_insert[i];
394 Tscal u = part_u_insert[i];
395 if (patch_coord.contain_pos(r)) {
396 vec_acc.push_back(r);
397 hpart_acc.push_back(part_hpart_insert[i]);
399 B_on_rho_acc.push_back(part_B_on_rho_insert[i]);
400 psi_on_ch_acc.push_back(part_psi_on_ch_insert[i]);
404 if (vec_acc.size() == 0) {
408 log += shambase::format(
409 "\n rank = {} patch id={}, add N={} particles, coords = {} {}",
417 tmp.resize(vec_acc.size());
421 u32 len = vec_acc.size();
423 = tmp.get_field<Tvec>(sched.pdl_old().get_field_idx<Tvec>(
"xyz"));
424 sycl::buffer<Tvec> buf(vec_acc.data(), len);
425 f.override(buf, len);
429 u32 len = vec_acc.size();
431 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"hpart"));
432 sycl::buffer<Tscal> buf(hpart_acc.data(), len);
433 f.override(buf, len);
437 u32 len = u_acc.size();
439 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"uint"));
440 sycl::buffer<Tscal> buf(u_acc.data(), len);
441 f.override(buf, len);
445 u32 len = vec_acc.size();
447 = tmp.get_field<Tvec>(sched.pdl_old().get_field_idx<Tvec>(
"B/rho"));
448 sycl::buffer<Tvec> buf(B_on_rho_acc.data(), len);
449 f.override(buf, len);
453 u32 len = vec_acc.size();
455 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"psi/ch"));
456 sycl::buffer<Tscal> buf(psi_on_ch_acc.data(), len);
457 f.override(buf, len);
460 pdat.insert_elements(tmp);
462 sched.check_patchdata_locality_correctness();
464 std::string log_gathered =
"";
472 modules::ComputeLoadBalanceValue<Tvec, SPHKernel>(ctx, solver.solver_config, solver.storage)
473 .update_load_balancing();
475 post_insert_data<Tvec>(sched);
479template<
class Tvec,
template<
class>
class SPHKernel>
480void shammodels::sph::Model<Tvec, SPHKernel>::add_cube_hcp_3d(
481 Tscal dr, std::pair<Tvec, Tvec> _box) {
489 using namespace shamrock::patch;
496 auto [idxs_min, idxs_max] = Lattice::get_box_index_bounds(dr, box.lower, box.upper);
498 LatticeIter gen = LatticeIter(dr, idxs_min, idxs_max);
502 std::string log =
"";
503 while (!gen.is_done()) {
506 u64 loc_sum_ins_cnt = 0;
508 u64 max_loc_sum_ins_cnt = 0;
512 acc_count += to_ins.size();
519 std::vector<Tvec> vec_acc;
520 for (Tvec r : to_ins) {
521 if (patch_coord.contain_pos(r)) {
522 vec_acc.push_back(r);
527 loc_sum_ins_cnt += vec_acc.size();
529 if (vec_acc.size() == 0) {
533 log += shambase::format(
534 "\n rank = {} patch id={}, add N={} particles, coords = {} {}",
542 pdat.reserve(vec_acc.size());
545 tmp.resize(vec_acc.size());
549 u32 len = vec_acc.size();
551 = tmp.get_field<Tvec>(sched.pdl_old().get_field_idx<Tvec>(
"xyz"));
553 f.override(vec_acc, len);
558 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"hpart"));
562 pdat.insert_elements(tmp);
565 max_loc_sum_ins_cnt = shamalgs::collective::allreduce_max(loc_sum_ins_cnt);
570 "--> insertion loop : max loc insert count = ",
575 }
while (!gen.is_done() && max_loc_sum_ins_cnt < sched.
crit_patch_split * 8);
577 sched.check_patchdata_locality_correctness();
589 modules::ComputeLoadBalanceValue<Tvec, SPHKernel>(ctx, solver.solver_config, solver.storage)
590 .update_load_balancing();
591 post_insert_data<Tvec>(sched);
595 modules::ParticleReordering<Tvec, u32, SPHKernel>(ctx, solver.solver_config, solver.storage)
596 .reorder_particles();
605template<
class Tvec,
template<
class>
class SPHKernel>
606void shammodels::sph::Model<Tvec, SPHKernel>::add_cube_hcp_3d_v2(
607 Tscal dr, std::pair<Tvec, Tvec> _box) {
613 using namespace shamrock::patch;
620 auto [idxs_min, idxs_max] = Lattice::get_box_index_bounds(dr, box.lower, box.upper);
622 LatticeIter gen = LatticeIter(dr, idxs_min, idxs_max);
626 auto push_current_data = [&](std::vector<Tvec> pos_data) {
628 tmp.resize(pos_data.size());
632 u32 len = pos_data.size();
634 = tmp.get_field<Tvec>(sched.pdl_old().get_field_idx<Tvec>(
"xyz"));
636 f.override(pos_data, len);
641 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"hpart"));
645 inserter.push_patch_data<Tvec>(tmp,
"xyz", sched.
crit_patch_split * 8, [&]() {
646 modules::ComputeLoadBalanceValue<Tvec, SPHKernel>(
647 ctx, solver.solver_config, solver.storage)
648 .update_load_balancing();
657 auto has_pdat = [&]() {
666 while (!gen.is_done()) {
668 u64 loc_gen_count = (has_pdat()) ? insert_step : 0;
670 auto gen_info = shamalgs::collective::fetch_view(loc_gen_count);
672 u64 skip_start = gen_info.head_offset;
673 u64 gen_cnt = loc_gen_count;
674 u64 skip_end = gen_info.total_byte_count - loc_gen_count - gen_info.head_offset;
683 skip_start + gen_cnt + skip_end);
684 gen.skip(skip_start);
685 auto tmp = gen.next_n(gen_cnt);
688 std::vector<Tvec> pos_data;
691 pos_data.push_back(r);
695 push_current_data(pos_data);
697 shamlog_debug_ln(
"Gen",
"gen.is_done()", gen.is_done());
709 using Tscal = shambase::VecComponent<Tvec>;
729 std::function<Tscal(Tscal)> sigma_profile;
730 std::function<Tscal(Tscal)> cs_profile;
731 std::function<Tscal(Tscal)> rot_profile;
732 std::function<Tscal(Tscal)> vel_full_corr;
747 std::function<Tscal(Tscal)> sigma_profile,
748 std::function<Tscal(Tscal)> cs_profile,
749 std::function<Tscal(Tscal)> rot_profile)
750 : current_index(0), Npart(Npart), center(center), central_mass(central_mass),
751 r_in(r_in), r_out(r_out), disc_mass(disc_mass), p(p), H_r_in(H_r_in), q(q), G(G),
752 eng(eng), sigma_profile(sigma_profile), cs_profile(cs_profile),
753 rot_profile(rot_profile) {
760 inline bool is_done() {
return done; }
764 constexpr Tscal _2pi = 2 * shambase::constants::pi<Tscal>;
766 auto f_func = [&](Tscal r) {
767 return r * sigma_profile(r);
770 Tscal fmax = f_func(r_out);
772 auto find_r = [&]() {
776 if (u2 < f_func(r)) {
783 auto Gauss = shamalgs::random::mock_gaussian<Tscal>(eng);
788 Tscal vk = rot_profile(r);
789 Tscal cs = cs_profile(r);
790 Tscal sigma = sigma_profile(r);
792 Tscal Omega_Kep = sycl::sqrt(G * central_mass / (r * r * r));
796 Tscal H = sycl::sqrt(2.) * 3. * cs
801 auto pos = sycl::vec<Tscal, 3>{r * sycl::cos(theta), z, r * sycl::sin(theta)};
803 auto etheta = sycl::vec<Tscal, 3>{-pos.z(), 0, pos.x()};
804 etheta /= sycl::length(etheta);
806 auto vel = vk * etheta;
811 Tscal fs = 1. - sycl::sqrt(r_in / r);
812 Tscal rho = (sigma * fs) * sycl::exp(-z * z / (2 * H * H));
814 Out out{pos, vel, cs, rho};
818 if (current_index == Npart) {
825 inline std::vector<Out> next_n(
u32 nmax) {
826 std::vector<Out> ret{};
827 for (
u32 i = 0; i < nmax; i++) {
832 ret.push_back(next());
839template<
class Tvec,
template<
class>
class SPHKernel>
840void shammodels::sph::Model<Tvec, SPHKernel>::add_big_disc_3d(
853 using Config = SolverConfig;
854 using SolverConfigEOS =
typename Config::EOSConfig;
855 using SolverEOS_Adiabatic =
typename SolverConfigEOS::Adiabatic;
856 if (SolverEOS_Adiabatic *eos_config
857 = std::get_if<SolverEOS_Adiabatic>(&solver.solver_config.eos_config.config)) {
859 eos_gamma = eos_config->gamma;
867 auto sigma_profile = [=](Tscal r) {
869 constexpr Tscal sigma_0 = 1;
870 return sigma_0 * sycl::pow(r / r_in, -p);
873 auto cs_law = [=](Tscal r) {
874 return sycl::pow(r / r_in, -q);
877 auto kep_profile = [&](Tscal r) {
878 Tscal G = solver.solver_config.get_constant_G();
879 return sycl::sqrt(G * central_mass / r);
882 auto rot_profile = [&](Tscal r) -> Tscal {
884 Tscal G = solver.solver_config.get_constant_G();
885 Tscal c = solver.solver_config.get_constant_c();
887 Tscal term = G * central_mass / r;
888 Tscal term_fs = 1. - sycl::sqrt(r_in / r);
890 = -sycl::pown(cs_law(r), 2) * (1.5 + p + q);
892 Tscal det = sycl::pown(term_bh, 2) + 4. * (term + term_pr);
893 Tscal Rg = G * central_mass / sycl::pown(c, 2);
894 Tscal vkep = sqrt(G * central_mass / r);
896 Tscal vphi = 0.5 * (term_bh + sycl::sqrt(det));
901 auto cs_profile = [&](Tscal r) {
902 Tscal cs_in = (H_r_in * r_in / r) * kep_profile(r_in);
903 return cs_law(r) * cs_in;
906 auto get_hfact = []() -> Tscal {
907 return Kernel::hfactd;
910 auto int_rho_h = [&](Tscal h) -> Tscal {
911 return shamrock::sph::rho_h(solver.solver_config.gpart_mass, h, Kernel::hfactd);
914 Tscal part_mass = disc_mass / Npart;
921 using namespace shamrock::patch;
928 Tscal G = solver.solver_config.get_constant_G();
947 std::string log =
"";
948 while (!gen.is_done()) {
951 u64 loc_sum_ins_cnt = 0;
953 u64 max_loc_sum_ins_cnt = 0;
957 acc_count += to_ins.size();
964 std::vector<Out> part_list;
965 for (Out r : to_ins) {
966 if (patch_coord.contain_pos(r.pos)) {
968 part_list.push_back(r);
973 loc_sum_ins_cnt += part_list.size();
975 if (part_list.size() == 0) {
979 log += shambase::format(
980 "\n rank = {} patch id={}, add N={} particles, coords = {} {}",
988 std::vector<Tvec> vec_pos;
989 std::vector<Tvec> vec_vel;
990 std::vector<Tscal> vec_u;
991 std::vector<Tscal> vec_h;
992 std::vector<Tscal> vec_cs;
994 for (Out o : part_list) {
995 vec_pos.push_back(o.pos);
996 vec_vel.push_back(o.velocity);
997 vec_u.push_back(o.cs * o.cs / ( (eos_gamma - 1)));
998 vec_h.push_back(shamrock::sph::h_rho(part_mass, o.rho * 0.1, Kernel::hfactd));
999 vec_cs.push_back(o.cs);
1003 pdat.reserve(vec_pos.size());
1006 tmp.resize(vec_pos.size());
1010 u32 len = vec_pos.size();
1012 = tmp.get_field<Tvec>(sched.pdl_old().get_field_idx<Tvec>(
"xyz"));
1013 sycl::buffer<Tvec> buf(vec_pos.data(), len);
1014 f.override(buf, len);
1018 u32 len = vec_pos.size();
1020 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"hpart"));
1021 sycl::buffer<Tscal> buf(vec_h.data(), len);
1022 f.override(buf, len);
1026 u32 len = vec_pos.size();
1028 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"uint"));
1029 sycl::buffer<Tscal> buf(vec_u.data(), len);
1030 f.override(buf, len);
1033 if (solver.solver_config.is_eos_locally_isothermal()) {
1034 u32 len = vec_pos.size();
1036 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"soundspeed"));
1037 sycl::buffer<Tscal> buf(vec_cs.data(), len);
1038 f.override(buf, len);
1042 u32 len = vec_pos.size();
1044 = tmp.get_field<Tvec>(sched.pdl_old().get_field_idx<Tvec>(
"vxyz"));
1045 sycl::buffer<Tvec> buf(vec_vel.data(), len);
1046 f.override(buf, len);
1049 pdat.insert_elements(tmp);
1052 max_loc_sum_ins_cnt = shamalgs::collective::allreduce_max(loc_sum_ins_cnt);
1057 "--> insertion loop : max loc insert count = ",
1058 max_loc_sum_ins_cnt,
1062 }
while (!gen.is_done() && max_loc_sum_ins_cnt < sched.
crit_patch_split * 8);
1064 sched.check_patchdata_locality_correctness();
1076 modules::ComputeLoadBalanceValue<Tvec, SPHKernel>(ctx, solver.solver_config, solver.storage)
1077 .update_load_balancing();
1078 post_insert_data<Tvec>(sched);
1082 modules::ParticleReordering<Tvec, u32, SPHKernel>(ctx, solver.solver_config, solver.storage)
1083 .reorder_particles();
1092template<
class Tvec,
template<
class>
class SPHKernel>
1093void shammodels::sph::Model<Tvec, SPHKernel>::add_cube_fcc_3d(
1094 Tscal dr, std::pair<Tvec, Tvec> _box) {
1099 using namespace shamrock::patch;
1103 std::string log =
"";
1105 auto make_sliced = [&]() {
1106 std::vector<Tvec> vec_lst;
1107 generic::setup::generators::add_particles_fcc(
1109 {box.lower, box.upper},
1111 return box.contain_pos(r);
1113 [&](Tvec r, Tscal h) {
1114 vec_lst.push_back(r);
1117 std::vector<std::vector<Tvec>> sliced_buf;
1121 std::vector<Tvec> cur_buf;
1122 for (
u32 i = 0; i < vec_lst.size(); i++) {
1123 cur_buf.push_back(vec_lst[i]);
1125 if (cur_buf.size() > sz_buf) {
1126 sliced_buf.push_back(std::exchange(cur_buf, std::vector<Tvec>{}));
1130 if (cur_buf.size() > 0) {
1131 sliced_buf.push_back(std::exchange(cur_buf, std::vector<Tvec>{}));
1137 std::vector<std::vector<Tvec>> sliced_buf = make_sliced();
1139 for (std::vector<Tvec> to_ins : sliced_buf) {
1146 std::vector<Tvec> vec_acc;
1147 for (Tvec r : to_ins) {
1148 if (patch_coord.contain_pos(r)) {
1149 vec_acc.push_back(r);
1153 if (vec_acc.size() == 0) {
1157 log += shambase::format(
1158 "\n rank = {} patch id={}, add N={} particles, coords = {} {}",
1166 tmp.resize(vec_acc.size());
1170 u32 len = vec_acc.size();
1172 = tmp.get_field<Tvec>(sched.pdl_old().get_field_idx<Tvec>(
"xyz"));
1173 sycl::buffer<Tvec> buf(vec_acc.data(), len);
1174 f.override(buf, len);
1179 = tmp.get_field<Tscal>(sched.pdl_old().get_field_idx<Tscal>(
"hpart"));
1183 pdat.insert_elements(tmp);
1186 sched.check_patchdata_locality_correctness();
1188 std::string log_gathered =
"";
1196 modules::ComputeLoadBalanceValue<Tvec, SPHKernel>(ctx, solver.solver_config, solver.storage)
1197 .update_load_balancing();
1198 post_insert_data<Tvec>(sched);
1202template<
class Tvec,
template<
class>
class SPHKernel>
1203auto shammodels::sph::Model<Tvec, SPHKernel>::gen_config_from_phantom_dump(
1204 PhantomDump &phdump,
bool bypass_error) -> SolverConfig {
1206 SolverConfig conf{};
1208 auto massoftype = phdump.read_header_floats<Tscal>(
"massoftype");
1210 conf.gpart_mass = massoftype[0];
1211 conf.cfl_config.cfl_cour = phdump.read_header_float<Tscal>(
"C_cour");
1212 conf.cfl_config.cfl_force = phdump.read_header_float<Tscal>(
"C_force");
1214 conf.eos_config = get_shamrock_eosconfig<Tvec>(phdump, bypass_error);
1215 conf.artif_viscosity = get_shamrock_avconfig<Tvec>(phdump);
1217 conf.set_units(get_shamrock_units<Tscal>(phdump));
1219 conf.boundary_config = get_shamrock_boundary_config<Tvec>(phdump);
1224template<
class Tvec,
template<
class>
class SPHKernel>
1225void shammodels::sph::Model<Tvec, SPHKernel>::init_from_phantom_dump(
1226 PhantomDump &phdump, Tscal hpart_fact_load) {
1229 bool has_coord_in_header =
true;
1231 Tscal xmin, xmax, ymin, ymax, zmin, zmax;
1232 has_coord_in_header = phdump.has_header_entry(
"xmin");
1234 std::string log =
"";
1237 std::vector<Tscal> h, u, alpha;
1240 std::vector<Tscal> x, y, z, vx, vy, vz;
1242 phdump.blocks[0].fill_vec(
"x", x);
1243 phdump.blocks[0].fill_vec(
"y", y);
1244 phdump.blocks[0].fill_vec(
"z", z);
1246 if (has_coord_in_header) {
1247 xmin = phdump.read_header_float<
f64>(
"xmin");
1248 xmax = phdump.read_header_float<
f64>(
"xmax");
1249 ymin = phdump.read_header_float<
f64>(
"ymin");
1250 ymax = phdump.read_header_float<
f64>(
"ymax");
1251 zmin = phdump.read_header_float<
f64>(
"zmin");
1252 zmax = phdump.read_header_float<
f64>(
"zmax");
1254 resize_simulation_box({{xmin, ymin, zmin}, {xmax, ymax, zmax}});
1256 Tscal box_tolerance = 1.2;
1258 xmin = *std::min_element(x.begin(), x.end());
1259 xmax = *std::max_element(x.begin(), x.end());
1260 ymin = *std::min_element(y.begin(), y.end());
1261 ymax = *std::max_element(y.begin(), y.end());
1262 zmin = *std::min_element(z.begin(), z.end());
1263 zmax = *std::max_element(z.begin(), z.end());
1265 Tvec bm = {xmin, ymin, zmin};
1266 Tvec bM = {xmax, ymax, zmax};
1268 Tvec center = (bm + bM) * 0.5;
1270 Tvec d = (bM - bm) * 0.5;
1275 resize_simulation_box({center - d, center + d});
1278 phdump.blocks[0].fill_vec(
"h", h);
1280 phdump.blocks[0].fill_vec(
"vx", vx);
1281 phdump.blocks[0].fill_vec(
"vy", vy);
1282 phdump.blocks[0].fill_vec(
"vz", vz);
1284 phdump.blocks[0].fill_vec(
"u", u);
1285 phdump.blocks[0].fill_vec(
"alpha", alpha);
1287 for (
u32 i = 0; i < x.size(); i++) {
1288 xyz.push_back({x[i], y[i], z[i]});
1290 for (
u32 i = 0; i < vx.size(); i++) {
1291 vxyz.push_back({vx[i], vy[i], vz[i]});
1296 f64 time_phdump = phdump.read_header_float<
f64>(
"time");
1297 solver.set_time(time_phdump);
1299 using namespace shamrock::patch;
1307 std::vector<u64> insert_ranges;
1308 insert_ranges.push_back(0);
1309 for (
u64 i = sz_buf; i < Ntot; i += sz_buf) {
1310 insert_ranges.push_back(i);
1312 insert_ranges.push_back(Ntot);
1314 for (
u64 krange = 0; krange < insert_ranges.size() - 1; krange++) {
1315 u64 start_id = insert_ranges[krange];
1316 u64 end_id = insert_ranges[krange + 1];
1318 u64 Nloc = end_id - start_id;
1325 std::vector<u64> sel_index;
1326 for (
u64 i = start_id; i < end_id; i++) {
1329 if (patch_coord.contain_pos(r) && (h_ >= 0)) {
1330 sel_index.push_back(i);
1334 if (sel_index.size() == 0) {
1338 log += shambase::format(
1339 "\n rank = {} patch id={}, add N={} particles, coords = {} {}",
1346 std::vector<Tvec> ins_xyz, ins_vxyz;
1347 std::vector<Tscal> ins_h, ins_u, ins_alpha;
1348 for (
u64 i : sel_index) {
1349 ins_xyz.push_back(xyz[i]);
1351 for (
u64 i : sel_index) {
1352 ins_vxyz.push_back(vxyz[i]);
1354 for (
u64 i : sel_index) {
1355 ins_h.push_back(h[i] * hpart_fact_load);
1358 for (
u64 i : sel_index) {
1359 ins_u.push_back(u[i]);
1362 if (alpha.size() > 0) {
1363 for (
u64 i : sel_index) {
1364 ins_alpha.push_back(alpha[i]);
1369 ptmp.resize(sel_index.size());
1372 ptmp.override_patch_field(
"xyz", ins_xyz);
1373 ptmp.override_patch_field(
"vxyz", ins_vxyz);
1374 ptmp.override_patch_field(
"hpart", ins_h);
1376 if (ins_alpha.size() > 0) {
1377 ptmp.override_patch_field(
"alpha_AV", ins_alpha);
1380 if (ins_u.size() > 0) {
1381 ptmp.override_patch_field(
"uint", ins_u);
1384 pdat.insert_elements(ptmp);
1387 sched.check_patchdata_locality_correctness();
1389 std::string log_gathered =
"";
1397 modules::ComputeLoadBalanceValue<Tvec, SPHKernel>(ctx, solver.solver_config, solver.storage)
1398 .update_load_balancing();
1400 post_insert_data<Tvec>(sched);
1404 PhantomDumpBlock &sink_block = phdump.blocks[1];
1406 std::vector<Tscal> xsink, ysink, zsink;
1407 std::vector<Tscal> vxsink, vysink, vzsink;
1408 std::vector<Tscal> mass;
1409 std::vector<Tscal> Racc;
1411 sink_block.fill_vec(
"x", xsink);
1412 sink_block.fill_vec(
"y", ysink);
1413 sink_block.fill_vec(
"z", zsink);
1414 sink_block.fill_vec(
"vx", vxsink);
1415 sink_block.fill_vec(
"vy", vysink);
1416 sink_block.fill_vec(
"vz", vzsink);
1417 sink_block.fill_vec(
"m", mass);
1418 sink_block.fill_vec(
"h", Racc);
1420 for (
u32 i = 0; i < xsink.size(); i++) {
1423 {xsink[i], ysink[i], zsink[i]},
1424 {vxsink[i], vysink[i], vzsink[i]},
1431template<
class Tvec,
template<
class>
class SPHKernel>
1432void shammodels::sph::Model<Tvec, SPHKernel>::add_pdat_to_phantom_block(
1437 u64 xid = block.get_ref_fort_real(
"x");
1438 u64 yid = block.get_ref_fort_real(
"y");
1439 u64 zid = block.get_ref_fort_real(
"z");
1441 for (
auto vec : xyz) {
1442 block.blocks_fort_real[xid].vals.push_back(
vec.x());
1443 block.blocks_fort_real[yid].vals.push_back(
vec.y());
1444 block.blocks_fort_real[zid].vals.push_back(
vec.z());
1447 std::vector<Tscal> h = pdat.
fetch_data<Tscal>(
"hpart");
1448 u64 hid = block.get_ref_f32(
"h");
1450 block.blocks_f32[hid].vals.push_back(h_);
1453 if (solver.solver_config.has_field_alphaAV()) {
1454 std::vector<Tscal> alpha = pdat.
fetch_data<Tscal>(
"alpha_AV");
1455 u64 aid = block.get_ref_f32(
"alpha");
1456 for (
auto alp_ : alpha) {
1457 block.blocks_f32[aid].vals.push_back(alp_);
1461 if (solver.solver_config.has_field_divv()) {
1462 std::vector<Tscal> vecdivv = pdat.
fetch_data<Tscal>(
"divv");
1463 u64 divvid = block.get_ref_f32(
"divv");
1464 for (
auto d_ : vecdivv) {
1465 block.blocks_f32[divvid].vals.push_back(d_);
1471 u64 vxid = block.get_ref_fort_real(
"vx");
1472 u64 vyid = block.get_ref_fort_real(
"vy");
1473 u64 vzid = block.get_ref_fort_real(
"vz");
1475 for (
auto vec : vxyz) {
1476 block.blocks_fort_real[vxid].vals.push_back(
vec.x());
1477 block.blocks_fort_real[vyid].vals.push_back(
vec.y());
1478 block.blocks_fort_real[vzid].vals.push_back(
vec.z());
1481 std::vector<Tscal> u = pdat.
fetch_data<Tscal>(
"uint");
1482 u64 uid = block.get_ref_fort_real(
"u");
1484 block.blocks_fort_real[uid].vals.push_back(u_);
1487 block.tot_count = block.blocks_fort_real[xid].vals.size();
1490template<
class Tvec,
template<
class>
class SPHKernel>
1496 bool bypass_error_check =
false;
1498 auto get_sink_count = [&]() ->
int {
1502 dump.override_magic_number();
1504 dump.fileid = shambase::format(
"{:100s}",
"FT:Phantom Shamrock writer");
1506 u32 Ntot = get_total_part_count();
1507 dump.table_header_fort_int.add(
"nparttot", Ntot);
1508 dump.table_header_fort_int.add(
"ntypes", 8);
1509 dump.table_header_fort_int.add(
"npartoftype", Ntot);
1510 dump.table_header_fort_int.add(
"npartoftype", 0);
1511 dump.table_header_fort_int.add(
"npartoftype", 0);
1512 dump.table_header_fort_int.add(
"npartoftype", 0);
1513 dump.table_header_fort_int.add(
"npartoftype", 0);
1514 dump.table_header_fort_int.add(
"npartoftype", 0);
1515 dump.table_header_fort_int.add(
"npartoftype", 0);
1516 dump.table_header_fort_int.add(
"npartoftype", 0);
1518 dump.table_header_i64.add(
"nparttot", Ntot);
1519 dump.table_header_i64.add(
"ntypes", 8);
1520 dump.table_header_i64.add(
"npartoftype", Ntot);
1521 dump.table_header_i64.add(
"npartoftype", 0);
1522 dump.table_header_i64.add(
"npartoftype", 0);
1523 dump.table_header_i64.add(
"npartoftype", 0);
1524 dump.table_header_i64.add(
"npartoftype", 0);
1525 dump.table_header_i64.add(
"npartoftype", 0);
1526 dump.table_header_i64.add(
"npartoftype", 0);
1527 dump.table_header_i64.add(
"npartoftype", 0);
1529 dump.table_header_fort_int.add(
"nblocks", 1);
1530 dump.table_header_fort_int.add(
"nptmass", get_sink_count());
1531 dump.table_header_fort_int.add(
"ndustlarge", 0);
1532 dump.table_header_fort_int.add(
"ndustsmall", 0);
1533 dump.table_header_fort_int.add(
"idust", 7);
1534 dump.table_header_fort_int.add(
"idtmax_n", 1);
1535 dump.table_header_fort_int.add(
"idtmax_frac", 0);
1536 dump.table_header_fort_int.add(
"idumpfile", 0);
1537 dump.table_header_fort_int.add(
"majorv", 2023);
1538 dump.table_header_fort_int.add(
"minorv", 0);
1539 dump.table_header_fort_int.add(
"microv", 0);
1540 dump.table_header_fort_int.add(
"isink", 0);
1542 dump.table_header_i32.add(
"iexternalforce", 0);
1546 dump.table_header_fort_real.add(
"time", solver.get_time());
1547 dump.table_header_fort_real.add(
"dtmax", solver.get_dt_sph());
1549 dump.table_header_fort_real.add(
"rhozero", 0);
1550 dump.table_header_fort_real.add(
"hfact", Kernel::hfactd);
1551 dump.table_header_fort_real.add(
"tolh", 0.0001);
1552 dump.table_header_fort_real.add(
"C_cour", solver.solver_config.cfl_config.cfl_cour);
1553 dump.table_header_fort_real.add(
"C_force", solver.solver_config.cfl_config.cfl_force);
1554 dump.table_header_fort_real.add(
"alpha", 0);
1555 dump.table_header_fort_real.add(
"alphau", 1);
1556 dump.table_header_fort_real.add(
"alphaB", 1);
1558 dump.table_header_fort_real.add(
"massoftype", solver.solver_config.gpart_mass);
1559 dump.table_header_fort_real.add(
"massoftype", 0);
1560 dump.table_header_fort_real.add(
"massoftype", 0);
1561 dump.table_header_fort_real.add(
"massoftype", 0);
1562 dump.table_header_fort_real.add(
"massoftype", 0);
1563 dump.table_header_fort_real.add(
"massoftype", 0);
1564 dump.table_header_fort_real.add(
"massoftype", 0);
1565 dump.table_header_fort_real.add(
"massoftype", 0);
1567 dump.table_header_fort_real.add(
"Bextx", 0);
1568 dump.table_header_fort_real.add(
"Bexty", 0);
1569 dump.table_header_fort_real.add(
"Bextz", 0);
1570 dump.table_header_fort_real.add(
"dum", 0);
1574 auto box_size = sched.get_box_volume<Tvec>();
1576 write_shamrock_boundaries_in_phantom_dump(
1577 solver.solver_config.boundary_config, box_size, dump, bypass_error_check);
1579 dump.table_header_fort_real.add(
"get_conserv", -1);
1580 dump.table_header_fort_real.add(
"etot_in", 0.59762);
1581 dump.table_header_fort_real.add(
"angtot_in", 0.0189694);
1582 dump.table_header_fort_real.add(
"totmom_in", 0.0306284);
1586 PhantomDumpBlock block_part;
1590 std::vector<std::unique_ptr<shamrock::patch::PatchDataLayer>> gathered
1591 = ctx.allgather_data();
1593 for (
auto &dat : gathered) {
1598 dump.blocks.push_back(std::move(block_part));
1602 auto edges = get_sink_edges<Tvec>(sync);
1603 if (edges.has_sinks()) {
1606 PhantomDumpBlock sink_block;
1608 u64 xid = sink_block.get_ref_fort_real(
"x");
1609 u64 yid = sink_block.get_ref_fort_real(
"y");
1610 u64 zid = sink_block.get_ref_fort_real(
"z");
1611 u64 mid = sink_block.get_ref_fort_real(
"m");
1612 u64 hid = sink_block.get_ref_fort_real(
"h");
1613 u64 vxid = sink_block.get_ref_fort_real(
"vx");
1614 u64 vyid = sink_block.get_ref_fort_real(
"vy");
1615 u64 vzid = sink_block.get_ref_fort_real(
"vz");
1617 for (SinkParticle<Tvec> s : sinks) {
1618 sink_block.blocks_fort_real[xid].vals.push_back(s.pos.x());
1619 sink_block.blocks_fort_real[yid].vals.push_back(s.pos.y());
1620 sink_block.blocks_fort_real[zid].vals.push_back(s.pos.z());
1621 sink_block.blocks_fort_real[mid].vals.push_back(s.mass);
1622 sink_block.blocks_fort_real[hid].vals.push_back(s.accretion_radius);
1623 sink_block.blocks_fort_real[vxid].vals.push_back(s.velocity.x());
1624 sink_block.blocks_fort_real[vyid].vals.push_back(s.velocity.y());
1625 sink_block.blocks_fort_real[vzid].vals.push_back(s.velocity.z());
1628 sink_block.tot_count = sinks.size();
1630 dump.blocks.push_back(std::move(sink_block));
constexpr const char * vxyz
3-velocity field
constexpr const char * xyz
Position field (3D coordinates).
Header file describing a Node Instance.
double f64
Alias for double.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
SchedulerPatchData patch_data
handle the data of the patches of the scheduler
u64 crit_patch_split
splitting limit (if load value > crit_patch_split => patch split)
PatchTree patch_tree
handle the tree structure of the patches
void scheduler_step(bool do_split_merge, bool do_load_balancing)
scheduler step
SynchronizedData synchronized_data
data that is synchroneous across all ranks
SchedulerPatchList patch_list
handle the list of the patches of the scheduler
std::unordered_set< u64 > owned_patch_id
(owned_patch_id = patch_list.build_local())
void add_root_patch()
add patch to the scheduler
std::unordered_set< u64 > build_local()
select owned patches owned by the node to rebuild local
void build_local_idx_map()
recompute id_patch_to_local_idx
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.
Iterator utility to generate the lattice.
utility for generating HCP crystal lattices
Vector class based on std::array storage and mdspan.
void init()
Initialise the model and all the related data structures (patch scheduler in particular).
Class to insert data in the PatchScheduler.
Utility class used to move the objects between patches.
PatchDataLayer container class, the layout is described in patchdata_layout.
std::vector< T > fetch_data(std::string key)
Fetch data of a patchdata field into a std::vector.
std::tuple< T, T > get_bounding_box() const
Get the stored bounding box of the domain.
PatchCoordTransform< T > get_patch_transform() const
Get a PatchCoordTransform object that describes the conversion between patch coordinates and domain c...
shamrock::patch::SimulationBoxInfo sim_box
simulation box geometry info
shambase::DistributedData< PatchData > owned_data
map container for patchdata owned by the current node (layout : id_patch,data)
This header file contains utility functions related to exception handling in the code.
std::vector< int > vector_allgatherv(const std::vector< T > &send_vec, const MPI_Datatype &send_type, std::vector< T > &recv_vec, const MPI_Datatype &recv_type, const MPI_Comm comm)
allgatherv on vector with size query (size querying variant of vector_allgatherv_ks) //TODO add fault...
void gather_str(const std::string &send_vec, std::string &recv_vec)
Gathers a string from all nodes and store the result in a std::string.
T mock_value(Engine &eng, T min_bound, T max_bound)
Generates a random mock value within specified bounds.
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...
ExcptTypes make_except_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Create an exception with a message and a location.
i32 world_rank()
Gives the rank of the current process in the MPI communicator.
namespace for math utility
std::vector< SinkParticle< Tvec > > to_sink_particles(const SinkEdges< Tvec > &e)
Build an AoS sink list from the current SoA edges (Python API / dump helpers).
void ensure_sink_edges(shamrock::solvergraph::SolverGraphSerializable &sync)
Register sink SoA synchronized edges if missing (idempotent).
void write_shamrock_units_in_phantom_dump(std::optional< shamunits::UnitSystem< Tscal > > &units, PhantomDump &dump, bool bypass_error)
Write shamrock units config into the phantom dump.
void add_sink(SinkEdges< Tvec > &e, typename SinkEdges< Tvec >::Tscal mass, Tvec pos, Tvec velocity, typename SinkEdges< Tvec >::Tscal accretion_radius)
Append one sink to the SoA edges.
void write_shamrock_eos_in_phantom_dump(EOSConfig< Tvec > &cfg, PhantomDump &dump, bool bypass_error)
Write the eos config to th phantom dump header.
constexpr u32 u32_max
u32 max value
Contains traits and utilities for backend related types.
void info_ln(std::string module_name, Types... var2)
Prints a log message with multiple arguments followed by a newline.
Helpers to access SPH sink particles stored as SoA synchronized data edges.
This file contains the definition for the stacktrace related functionality.
shambase::details::NamedBasicStackEntry NamedStackEntry
Alias for shambase::details::NamedBasicStackEntry.
shambase::details::BasicStackEntry StackEntry
Alias for shambase::details::BasicStackEntry.
Class representing a Phantom dump file.
Patch object that contain generic patch information.
static bool is_in_patch_converted(sycl::vec< T, 3 > val, sycl::vec< T, 3 > min_val, sycl::vec< T, 3 > max_val)
check if particle is in the asked range, given the output of @convert_coord