Skip to content

Commit

Permalink
++
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilipDeegan committed Oct 30, 2024
1 parent 530394b commit 3fb4b64
Show file tree
Hide file tree
Showing 7 changed files with 402 additions and 24 deletions.
11 changes: 6 additions & 5 deletions mkn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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

(
Expand Down
1 change: 1 addition & 0 deletions src/core/data/particles/arrays/particle_array_pc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_; }
Expand Down
20 changes: 11 additions & 9 deletions src/core/numerics/ion_updater/ion_updater_multi_pc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,15 @@ void IonUpdaterMultiPC<Ions, Electromag, GridLayout>::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;

auto copy_in = [&](auto const j) {
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;
Expand All @@ -134,19 +134,19 @@ void IonUpdaterMultiPC<Ions, Electromag, GridLayout>::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]);
});

in.streamer();
in.streamer.sync();

#else
// throw std::runtime_error("No available implementation")
// throw std::runtime_error("No available implementation")
#endif
//
}
Expand All @@ -158,6 +158,8 @@ void IonUpdaterMultiPC<Ions, Electromag, GridLayout>::updateAndDepositAll_(Model
{
PHARE_LOG_SCOPE(1, "IonUpdaterMultiPC::updateAndDepositAll_");

constexpr static std::uint8_t DOMAIN_ID = 0;

if (views.size() == 0)
return;

Expand All @@ -172,17 +174,17 @@ void IonUpdaterMultiPC<Ions, Electromag, GridLayout>::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;

auto copy_in = [&](auto const j) {
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
Expand All @@ -208,7 +210,7 @@ void IonUpdaterMultiPC<Ions, Electromag, GridLayout>::updateAndDepositAll_(Model
in.streamer.print_times();

#else
// throw std::runtime_error("No available implementation")
// throw std::runtime_error("No available implementation")
#endif
//
}
Expand Down
6 changes: 4 additions & 2 deletions tests/core/data/particles/test_particles.hpp
Original file line number Diff line number Diff line change
@@ -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 <fstream>

namespace PHARE::core
Expand Down Expand Up @@ -113,7 +115,7 @@ template<auto type, typename Src, typename Dst>
void add_particles_from(Src const& src, Dst& dst)
{
static_assert(std::is_same_v<decltype(type), ParticleType>);

// SLOW!
for (auto const& p : src)
dst.push_back(p);

Expand Down
216 changes: 216 additions & 0 deletions tests/core/data/particles/test_particles_appender.hpp
Original file line number Diff line number Diff line change
@@ -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 <string>
#include <cassert>
#include <functional>

#include "phare_core.hpp"

#include "test_particles_converter.hpp"

namespace PHARE::core
{

// NOT FOR GPU
template<auto type, typename Src, typename Dst>
struct ParticlesAppender
{
static_assert(std::is_same_v<decltype(type), ParticleType>);
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<auto src_layout_mde, auto src_alloc_mde, auto dst_layout_mde, auto dst_alloc_mde>
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<auto type, typename Src, typename Dst, typename GridLayout>
void operator()(Src const& src, Dst& dst, GridLayout const& layout);
};


// CPU-AoSMapped to GPU_UNIFIED-SoAPC
template<>
template<auto type, typename Src, typename Dst, typename GridLayout>
void PAppender<LayoutMode::AoSMapped, AllocatorMode::CPU, LayoutMode::SoAPC,
AllocatorMode::GPU_UNIFIED>::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<Dst::dimension,
ParticleArrayInternals<Dst::dimension, LayoutMode::SoA, StorageMode::VECTOR,
src_alloc_mode, Dst::impl>>;

auto tmp = make_particles<Tmp>(layout);
tmp.resize(src.size());
ParticlePacker<Src>{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<std::tuple_size_v<decltype(dst_tuple)>>([&](auto vi) {
auto const& tmp_vec = std::get<vi>(tmp_tuple);
auto& vec = std::get<vi>(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<decltype(type), ParticleType>);
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<auto type, typename Src, typename Dst, typename GridLayout>
void PAppender<LayoutMode::AoSMapped, AllocatorMode::CPU, LayoutMode::AoSPC,
AllocatorMode::GPU_UNIFIED>::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<decltype(type), ParticleType>);
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<auto type, typename Src, typename Dst, typename GridLayout>
void append(Src const& src, Dst& dst, GridLayout const& layout)
{
PAppender<Src::layout_mode, Src::alloc_mode, Dst::layout_mode, Dst::alloc_mode>{}
.template operator()<type>(src, dst, layout);
}



} // namespace PHARE::core


#endif /* PHARE_TEST_CORE_DATA_PARTICLES_TEST_PARTICLES_APPENDER_HPP */
Loading

0 comments on commit 3fb4b64

Please sign in to comment.