From 3fb4b6481bf2e4d90d7e2101502d81227f4c13a6 Mon Sep 17 00:00:00 2001 From: deegan Date: Wed, 30 Oct 2024 15:57:33 +0100 Subject: [PATCH] ++ --- mkn.sh | 11 +- .../particles/arrays/particle_array_pc.hpp | 1 + .../ion_updater/ion_updater_multi_pc.hpp | 20 +- tests/core/data/particles/test_particles.hpp | 6 +- .../particles/test_particles_appender.hpp | 216 ++++++++++++++++++ .../particles/test_particles_converter.hpp | 156 +++++++++++++ .../ion_updater/test_multi_updater.cpp | 16 +- 7 files changed, 402 insertions(+), 24 deletions(-) create mode 100644 tests/core/data/particles/test_particles_appender.hpp create mode 100644 tests/core/data/particles/test_particles_converter.hpp diff --git a/mkn.sh b/mkn.sh index 836492b4c..534ea969b 100755 --- a/mkn.sh +++ b/mkn.sh @@ -8,8 +8,9 @@ set -e export KLOG=${KLOG:-0} export PHARE_SCOPE_TIMING=1 -export PHARE_CELLS=${PHARE_CELLS:-5} -export PHARE_PPC=${PHARE_PPC:-10} +export PHARE_CELLS=${PHARE_CELLS:-10} +export PHARE_PPC=${PHARE_PPC:-5} +export PHARE_PATCHES=${PHARE_PATCHES:-1} TEST="-M tests/core/numerics/ion_updater/test_updater_pp_main.cpp" TEST="-M tests/core/numerics/ion_updater/test_multi_updater.cpp" @@ -24,9 +25,9 @@ set -x mkn clean build -Oqp test_core -d google.test,+ -a "-fPIC" mkn clean build -tOqp core -a "-fPIC" -x res/mkn/mpi # -DPHARE_SKIP_MPI_IN_CORE ) - # mkn run -p test_core ${ARGS} $@ # -- --gtest_filter=IonUpdaterPPTest/14.updater - mkn clean build run -p test_core ${ARGS} $@ # -- --gtest_filter=IonUpdaterPPTest/14.updater -) # 1> >(tee $CWD/.mkn.sh.out ) 2> >(tee $CWD/.mkn.sh.err >&2 ) + mkn run -p test_core ${ARGS} $@ # -- --gtest_filter=IonUpdaterPPTest/14.updater + # mkn clean build run -p test_core ${ARGS} $@ # -- --gtest_filter=IonUpdaterPPTest/14.updater +) 1> >(tee $CWD/.mkn.sh.out ) 2> >(tee $CWD/.mkn.sh.err >&2 ) exit 0 # comment out to do soak test ( diff --git a/src/core/data/particles/arrays/particle_array_pc.hpp b/src/core/data/particles/arrays/particle_array_pc.hpp index 0f43f00a5..849687d49 100644 --- a/src/core/data/particles/arrays/particle_array_pc.hpp +++ b/src/core/data/particles/arrays/particle_array_pc.hpp @@ -255,6 +255,7 @@ class PerCellVector auto& box() const { return box_; } auto& ghost_box() const { return ghost_box_; } + auto& safe_box() const { return safe_box_; } // allocating box auto& operator()() const { return particles_; } diff --git a/src/core/numerics/ion_updater/ion_updater_multi_pc.hpp b/src/core/numerics/ion_updater/ion_updater_multi_pc.hpp index 892822e22..03a299e5b 100644 --- a/src/core/numerics/ion_updater/ion_updater_multi_pc.hpp +++ b/src/core/numerics/ion_updater/ion_updater_multi_pc.hpp @@ -109,7 +109,7 @@ void IonUpdaterMultiPC::updateAndDepositDomain_(Mo // add new domain particles in.streamer.host_group_mutex(group_size, [&](auto const i) { - auto is_domain_particles = in.particle_type[i] == 0; + auto is_domain_particles = in.particle_type[i] == DOMAIN_ID; if (is_domain_particles || in.particles[i]->size() == 0) return; @@ -117,7 +117,7 @@ void IonUpdaterMultiPC::updateAndDepositDomain_(Mo ParticleArrayService::copy_ghost_into_domain(*in.particles[i], *in.particles[j]); }; - if (in.particle_type[i - 1] == 0) + if (in.particle_type[i - 1] == DOMAIN_ID) copy_in(i - 1); else return; @@ -134,11 +134,11 @@ void IonUpdaterMultiPC::updateAndDepositDomain_(Mo // finished adding new domain particles in.streamer.group_barrier(group_size); - in.streamer.async_dev_idx(N_ARRAYS, 0, [=](auto const i) { // 0 = domain + in.streamer.async_dev_idx(N_ARRAYS, DOMAIN_ID, [=](auto const i) { // 0 = domain Interpolating_t::box_kernel(pps[i], layouts[i], fluxes[i], rhos[i]); }); // no patch ghost as they're injected into domain - in.streamer.async_dev_idx(N_ARRAYS, 2, [=](auto const i) { // 2 = level ghosts + in.streamer.async_dev_idx(N_ARRAYS, LEVEL_GHOST_ID, [=](auto const i) { // 2 = level ghosts Interpolating_t::box_kernel(pps[i], layouts[i], fluxes[i], rhos[i]); }); @@ -146,7 +146,7 @@ void IonUpdaterMultiPC::updateAndDepositDomain_(Mo in.streamer.sync(); #else - // throw std::runtime_error("No available implementation") + // throw std::runtime_error("No available implementation") #endif // } @@ -158,6 +158,8 @@ void IonUpdaterMultiPC::updateAndDepositAll_(Model { PHARE_LOG_SCOPE(1, "IonUpdaterMultiPC::updateAndDepositAll_"); + constexpr static std::uint8_t DOMAIN_ID = 0; + if (views.size() == 0) return; @@ -172,7 +174,7 @@ void IonUpdaterMultiPC::updateAndDepositAll_(Model // add new domain particles in.streamer.host_group_mutex(group_size, [&](auto const i) { - auto is_domain_particles = in.particle_type[i] == 0; + auto is_domain_particles = in.particle_type[i] == DOMAIN_ID; if (is_domain_particles || in.particles[i]->size() == 0) return; @@ -180,9 +182,9 @@ void IonUpdaterMultiPC::updateAndDepositAll_(Model ParticleArrayService::copy_ghost_into_domain(*in.particles[i], *in.particles[j]); }; - if (in.particle_type[i - 1] == 0) + if (in.particle_type[i - 1] == DOMAIN_ID) copy_in(i - 1); - else if (in.particle_type[i - 2] == 0) + else if (in.particle_type[i - 2] == DOMAIN_ID) copy_in(i - 2); // means there is no particle to mesh for ghosts @@ -208,7 +210,7 @@ void IonUpdaterMultiPC::updateAndDepositAll_(Model in.streamer.print_times(); #else - // throw std::runtime_error("No available implementation") + // throw std::runtime_error("No available implementation") #endif // } diff --git a/tests/core/data/particles/test_particles.hpp b/tests/core/data/particles/test_particles.hpp index 9e211183d..076948f41 100644 --- a/tests/core/data/particles/test_particles.hpp +++ b/tests/core/data/particles/test_particles.hpp @@ -1,10 +1,12 @@ #ifndef PHARE_CORE_DATA_TEST_PARTICLES_HPP #define PHARE_CORE_DATA_TEST_PARTICLES_HPP - #include "phare_core.hpp" #include "core/utilities/types.hpp" +#include "tests/core/data/particles/test_particles_appender.hpp" +#include "tests/core/data/particles/test_particles_converter.hpp" + #include namespace PHARE::core @@ -113,7 +115,7 @@ template void add_particles_from(Src const& src, Dst& dst) { static_assert(std::is_same_v); - + // SLOW! for (auto const& p : src) dst.push_back(p); diff --git a/tests/core/data/particles/test_particles_appender.hpp b/tests/core/data/particles/test_particles_appender.hpp new file mode 100644 index 000000000..bd31c5802 --- /dev/null +++ b/tests/core/data/particles/test_particles_appender.hpp @@ -0,0 +1,216 @@ +#ifndef PHARE_TEST_CORE_DATA_PARTICLES_TEST_PARTICLES_APPENDER_HPP +#define PHARE_TEST_CORE_DATA_PARTICLES_TEST_PARTICLES_APPENDER_HPP + +#include +#include +#include + +#include "phare_core.hpp" + +#include "test_particles_converter.hpp" + +namespace PHARE::core +{ + +// NOT FOR GPU +template +struct ParticlesAppender +{ + static_assert(std::is_same_v); + static_assert(Src::dimension == Dst::dimension); + auto constexpr static src_alloc_mode = Src::alloc_mode; + auto constexpr static dst_alloc_mode = Dst::alloc_mode; + + auto constexpr static src_layout_mode = Src::layout_mode; + auto constexpr static dst_layout_mode = Dst::layout_mode; + + auto& operator()(Src const& src, Dst& dst) + { + for (auto const& p : src) + dst.push_back(p); + + if constexpr (any_in(Dst::layout_mode, LayoutMode::AoSPC, LayoutMode::SoAPC)) + dst.template sync<2, type>(); + + return dst; + } +}; + + + +template +struct PAppender +{ + auto constexpr static src_layout_mode = src_layout_mde; + auto constexpr static src_alloc_mode = src_alloc_mde; + + auto constexpr static dst_layout_mode = dst_layout_mde; + auto constexpr static dst_alloc_mode = dst_alloc_mde; + + template + void operator()(Src const& src, Dst& dst, GridLayout const& layout); +}; + + +// CPU-AoSMapped to GPU_UNIFIED-SoAPC +template<> +template +void PAppender::operator()(Src const& src, Dst& dst, + GridLayout const& layout) +{ + // hax + auto const ppc = [&]() { // assume constant for the moment + for (auto const& bix : src.box()) + if (auto const n = src.nbr_particles_in(*bix); n > 0) + return n; + throw std::runtime_error("ppc 0"); + }(); + + using Tmp + = ParticleArray>; + + auto tmp = make_particles(layout); + tmp.resize(src.size()); + ParticlePacker{src}.pack(tmp); + assert(array_equals(src.delta(0), tmp.delta(0))); + + std::size_t tmp_start = 0; + auto const tmp_tuple = tmp.as_tuple(); + auto finish = [&](auto& lix) { + auto const size = ppc; + auto& dst_arr = dst(lix); + auto const curr_size = dst_arr.size(); + Dst::resize(dst_arr, curr_size + size); + auto dst_tuple = dst_arr.as_tuple(); + + for_N>([&](auto vi) { + auto const& tmp_vec = std::get(tmp_tuple); + auto& vec = std::get(dst_tuple); + PHARE_WITH_MKN_GPU( + mkn::gpu::copy(vec.data() + curr_size, tmp_vec.data() + tmp_start, size); // + ) + }); + tmp_start += size; + }; + + auto const amrbox = dst.safe_box(); + auto const lclbox = dst.local_box(); + auto amr_it = amrbox.begin(); + auto lcl_it = lclbox.begin(); + + for (; amr_it != amrbox.end(); ++amr_it, ++lcl_it) + { + if (!array_equals(**amr_it, tmp.iCell(tmp_start))) + continue; + finish(*lcl_it); + } + + dst.template sync<2, type>(); + assert(dst.size() == src.size()); + + bool valid = false; + amr_it = amrbox.begin(); + lcl_it = lclbox.begin(); + + for (; amr_it != amrbox.end(); ++amr_it, ++lcl_it) + { + if (!array_equals(**amr_it, tmp.iCell(0))) + continue; + valid = array_equals(src.delta(0), dst(*lcl_it).delta(0)); + } + + auto const& last = [&]() -> auto& { + static_assert(std::is_same_v); + if constexpr (type == ParticleType::Domain) + return dst(dst.local_cell(dst.box().upper)); + else if (type == ParticleType::Ghost) + return dst(dst.local_cell(dst.ghost_box().upper)); + }(); + assert(last.size() == ppc); + assert(valid); +} + + + + +template<> +template +void PAppender::operator()(Src const& src, Dst& dst, + GridLayout const& layout) +{ + // hax + auto const ppc = [&]() { // assume constant for the moment + for (auto const& bix : src.box()) + if (auto const n = src.nbr_particles_in(*bix); n > 0) + return n; + throw std::runtime_error("ppc 0"); + }(); + + std::size_t src_start = 0; + auto finish = [&](auto& lix) { + auto const size = ppc; + auto& dst_arr = dst(lix); + auto const curr_size = dst_arr.size(); + Dst::resize(dst_arr, curr_size + size); + PHARE_WITH_MKN_GPU( + mkn::gpu::copy(dst_arr.data() + curr_size, src.data() + src_start, size); // + ) + src_start += size; + }; + + auto const amrbox = dst.safe_box(); + auto const lclbox = dst.local_box(); + auto amr_it = amrbox.begin(); + auto lcl_it = lclbox.begin(); + + for (; amr_it != amrbox.end(); ++amr_it, ++lcl_it) + { + if (!array_equals(**amr_it, src.iCell(src_start))) + continue; + finish(*lcl_it); + } + + dst.template sync<2, type>(); + assert(dst.size() == src.size()); + + bool valid = false; + amr_it = amrbox.begin(); + lcl_it = lclbox.begin(); + + for (; amr_it != amrbox.end(); ++amr_it, ++lcl_it) + { + if (!array_equals(**amr_it, src.iCell(0))) + continue; + valid = array_equals(src.delta(0), dst(*lcl_it).delta(0)); + } + + auto const& last = [&]() -> auto& { + static_assert(std::is_same_v); + if constexpr (type == ParticleType::Domain) + return dst(dst.local_cell(dst.box().upper)); + else if (type == ParticleType::Ghost) + return dst(dst.local_cell(dst.ghost_box().upper)); + }(); + assert(last.size() == ppc); + assert(valid); +} + + + +template +void append(Src const& src, Dst& dst, GridLayout const& layout) +{ + PAppender{} + .template operator()(src, dst, layout); +} + + + +} // namespace PHARE::core + + +#endif /* PHARE_TEST_CORE_DATA_PARTICLES_TEST_PARTICLES_APPENDER_HPP */ diff --git a/tests/core/data/particles/test_particles_converter.hpp b/tests/core/data/particles/test_particles_converter.hpp new file mode 100644 index 000000000..5928f71ba --- /dev/null +++ b/tests/core/data/particles/test_particles_converter.hpp @@ -0,0 +1,156 @@ +#ifndef PHARE_TEST_CORE_DATA_PARTICLES_TEST_PARTICLES_CONVERTER_HPP +#define PHARE_TEST_CORE_DATA_PARTICLES_TEST_PARTICLES_CONVERTER_HPP + +#include "phare_core.hpp" + +#include +#include +#include + +#include "core/def.hpp" +#include "core/utilities/types.hpp" +#include "core/data/particles/particle_packer.hpp" + +#include "core/def/detail/mkn_gpu.hpp" + +namespace PHARE::core +{ + +template +struct ParticlesConverter +{ + static_assert(Src::dimension == Dst::dimension); + auto constexpr static src_alloc_mode = Src::alloc_mode; + auto constexpr static dst_alloc_mode = Dst::alloc_mode; + + auto constexpr static src_layout_mode = Src::layout_mode; + auto constexpr static dst_layout_mode = Dst::layout_mode; + + + template + auto operator()(Src const& src, GridLayout const& layout) + { + // + auto const ppc = [&]() { // assume constant for the moment + for (auto const& bix : src.box()) + if (auto const n = src.nbr_particles_in(*bix); n > 0) + return n; + throw std::runtime_error("ppc 0"); + }(); + PHARE_LOG_LINE_SS(ppc); + + auto dst = make_particles(layout); + + if constexpr (src_layout_mode == LayoutMode::AoSMapped + and dst_layout_mode == LayoutMode::SoAPC) + { + static_assert(src_alloc_mode == AllocatorMode::CPU); + static_assert(dst_alloc_mode == AllocatorMode::GPU_UNIFIED); + + using Tmp = ParticleArray< + Dst::dimension, + ParticleArrayInternals>; + + auto tmp = make_particles(layout); + tmp.resize(src.size()); + ParticlePacker{src}.pack(tmp); + + assert(array_equals(src.delta(0), tmp.delta(0))); + + dst.template reserve_ppc(ppc); + + std::size_t tmp_start = 0; + + auto const tmp_tuple = tmp.as_tuple(); + auto finish = [&](auto& lix) { + auto const size = ppc; + auto dst_tuple = dst(lix).as_tuple(); + + for_N>([&](auto vi) { + auto const& tmp_vec = std::get(tmp_tuple); + auto& vec = std::get(dst_tuple); + vec.resize(size); + PHARE_WITH_MKN_GPU( // + mkn::gpu::copy( // + vec.data(), // + tmp_vec.data() + tmp_start, // + size // + ) // + ); + + // PHARE_LOG_LINE_SS(vec.size()); + }); + tmp_start += size; + }; + + auto const amrbox = dst.safe_box(); + auto const lclbox = dst.local_box(); + auto amr_it = amrbox.begin(); + auto lcl_it = lclbox.begin(); + + for (; amr_it != amrbox.end(); ++amr_it, ++lcl_it) + { + if (!array_equals(**amr_it, tmp.iCell(tmp_start))) + continue; + + // PHARE_LOG_LINE_SS(*amr_it << " " << Point{*tmp_cell}); + + finish(*lcl_it); + } + + dst.template sync<2, type>(); + // PHARE_LOG_LINE_SS(dst.size() << " " << src.size() << " " << tmp.size()); + assert(dst.size() == src.size()); + + bool valid = false; + amr_it = amrbox.begin(); + lcl_it = lclbox.begin(); + + for (; amr_it != amrbox.end(); ++amr_it, ++lcl_it) + { + if (!array_equals(**amr_it, tmp.iCell(0))) + continue; + + PHARE_LOG_LINE_SS(Point{src.delta(0)} << " " << Point{dst(*lcl_it).delta(0)}); + + valid = array_equals(src.delta(0), dst(*lcl_it).delta(0)); + } + + auto const& last = [&]() -> auto& { + static_assert(std::is_same_v); + + if constexpr (type == ParticleType::Domain) + return dst(dst.local_cell(dst.box().upper)); + else if (type == ParticleType::Ghost) + return dst(dst.local_cell(dst.ghost_box().upper)); + }(); + + assert(last.size() == ppc); + PHARE_LOG_LINE_SS(Point{src.delta(src.size() - 1)} + << " " << Point{last.delta(last.size() - 1)}); + + assert(valid); + return dst; + } + + + throw std::runtime_error("unconvertible"); + + return make_particles(layout); + // else{} + } +}; + + +template +auto static convert(Src const& src, GridLayout const& layout) +{ + return ParticlesConverter{}(src, layout); +} + + +} // namespace PHARE::core + + +#endif /* PHARE_TEST_CORE_DATA_PARTICLES_TEST_PARTICLES_CONVERTER_HPP */ diff --git a/tests/core/numerics/ion_updater/test_multi_updater.cpp b/tests/core/numerics/ion_updater/test_multi_updater.cpp index 1b364c789..cbcacadbe 100644 --- a/tests/core/numerics/ion_updater/test_multi_updater.cpp +++ b/tests/core/numerics/ion_updater/test_multi_updater.cpp @@ -167,7 +167,7 @@ auto from_ions(GridLayout_t const& layout, Ions const& from) auto _add_particles_from = [&](auto& src, auto& dst) { ParticleArrayService::reserve_ppc_in(dst, ppc); - add_particles_from(src, dst); + append(src, dst, layout); }; _add_particles_from.template operator()( @@ -298,11 +298,11 @@ struct MultiPatchIonUpdaterTest : public ::testing::Test MultiPatchIonUpdaterTest() { patches.resize(n_patches); - /* // uncomment to do init value check - auto ref = make_ions(layout); - auto cmp = from_ions(layout, *ref); - compare(*this->layout, *ref, *cmp); // pre update check - */ + // uncomment to do init value check + + // auto ref = make_ions(layout); + // auto cmp = from_ions(layout, *ref); + // compare(*this->layout, *ref, *cmp); // pre update check } struct Patch @@ -327,8 +327,8 @@ using Permutations_t = testing::Types< // ! notice commas ! PHARE_WITH_MKN_GPU( - TestParam<3, LayoutMode::AoSPC, AllocatorMode::GPU_UNIFIED, 2, UpdaterMode::domain_only>, - TestParam<3, LayoutMode::SoAPC, AllocatorMode::GPU_UNIFIED, 2, UpdaterMode::domain_only>, + // TestParam<3, LayoutMode::AoSPC, AllocatorMode::GPU_UNIFIED, 2, UpdaterMode::domain_only>, + // TestParam<3, LayoutMode::SoAPC, AllocatorMode::GPU_UNIFIED, 2, UpdaterMode::domain_only>, TestParam<3, LayoutMode::AoSPC, AllocatorMode::GPU_UNIFIED, 2, UpdaterMode::all>, TestParam<3, LayoutMode::SoAPC, AllocatorMode::GPU_UNIFIED, 2, UpdaterMode::all>