From 03b725bff7d9e1e7104ad35aa66f0efeb2709201 Mon Sep 17 00:00:00 2001 From: deegan Date: Thu, 3 Oct 2024 13:08:27 +0200 Subject: [PATCH] minimize maxwellian vector capacity somewhat --- .../maxwellian_particle_initializer.hpp | 14 +++++ src/core/data/particles/particle.hpp | 18 +++--- src/core/utilities/box/box.hpp | 11 +++- .../test_maxwellian_particle_initializer.cpp | 61 ++++++++++++++++--- 4 files changed, 85 insertions(+), 19 deletions(-) diff --git a/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp b/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp index 49098af06..c26f2a473 100644 --- a/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp +++ b/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp @@ -178,6 +178,20 @@ void MaxwellianParticleInitializer::loadParticles( auto randGen = getRNG(rngSeed_); ParticleDeltaDistribution deltaDistrib; + std::size_t const expected_size = [&]() { + std::size_t size = 0; + for (std::size_t flatCellIdx = 0; flatCellIdx < ndCellIndices.size(); ++flatCellIdx) + if (n[flatCellIdx] >= densityCutOff_) + ++size; + return size * nbrParticlePerCell_; + }(); + + double const over_alloc_factor = .1; // todo from dict + std::size_t const allocate_size + = expected_size + + (layout.AMRBox().surface_cell_count() * (nbrParticlePerCell_ * over_alloc_factor)); + particles.reserve(allocate_size); + for (std::size_t flatCellIdx = 0; flatCellIdx < ndCellIndices.size(); ++flatCellIdx) { if (n[flatCellIdx] < densityCutOff_) diff --git a/src/core/data/particles/particle.hpp b/src/core/data/particles/particle.hpp index 0457865c2..bc81289b0 100644 --- a/src/core/data/particles/particle.hpp +++ b/src/core/data/particles/particle.hpp @@ -39,6 +39,7 @@ NO_DISCARD auto cellAsPoint(Particle const& particle) template struct Particle { + std::array constexpr static sizes = {52, 64, 76}; static_assert(dim > 0 and dim < 4, "Only dimensions 1,2,3 are supported."); static const size_t dimension = dim; @@ -54,12 +55,11 @@ struct Particle Particle() = default; - double weight = 0; - double charge = 0; - - std::array iCell = ConstArray(); - std::array delta = ConstArray(); - std::array v = ConstArray(); + double weight = 0; // 8 + double charge = 0; // 8 + std::array iCell = ConstArray(); // 4 * dim + std::array delta = ConstArray(); // 8 * dim + std::array v = ConstArray(); // 8 * 3 NO_DISCARD bool operator==(Particle const& that) const { @@ -121,9 +121,9 @@ inline constexpr auto is_phare_particle_type template typename ParticleA, template typename ParticleB> -NO_DISCARD typename std::enable_if_t< - is_phare_particle_type> and is_phare_particle_type>, - bool> +NO_DISCARD typename std::enable_if_t> + and is_phare_particle_type>, + bool> operator==(ParticleA const& particleA, ParticleB const& particleB) { return particleA.weight == particleB.weight and // diff --git a/src/core/utilities/box/box.hpp b/src/core/utilities/box/box.hpp index 0ff5d1a8a..ec0832609 100644 --- a/src/core/utilities/box/box.hpp +++ b/src/core/utilities/box/box.hpp @@ -26,7 +26,7 @@ template struct Box { static const size_t dimension = dim; - + using value_type = Type; Point lower; Point upper; @@ -130,9 +130,16 @@ struct Box return iterator{this, {upper[0] + 1, upper[1] + 1, upper[2] + 1}}; } } - using value_type = Type; + NO_DISCARD auto surface_cell_count() const + { + // assumes box never smaller than 3 in any direction + auto const shape_ = shape(); + auto const nested = shape_ - 2; + return core::product(shape_) - core::product(nested); + } + NO_DISCARD constexpr static std::size_t nbrRemainBoxes() { if constexpr (dim == 1) diff --git a/tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp b/tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp index f3f4899cb..09c0013e6 100644 --- a/tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp +++ b/tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp @@ -9,22 +9,23 @@ #include "core/utilities/box/box.hpp" #include "core/utilities/point/point.hpp" -#include "gmock/gmock.h" #include "gtest/gtest.h" #include "tests/initializer/init_functions.hpp" -using namespace PHARE::initializer::test_fn::func_1d; // density/etc are here +#include "tests/core/data/gridlayout/test_gridlayout.hpp" using namespace PHARE::core; -using namespace PHARE::initializer; + +namespace PHARE::initializer::test_fn::func_1d +{ class AMaxwellianParticleInitializer1D : public ::testing::Test { private: - using GridLayoutT = GridLayout>; using ParticleArrayT = ParticleArray<1>; using InitFunctionArray = std::array, 3>; + using GridLayoutT = GridLayout>; public: AMaxwellianParticleInitializer1D() @@ -34,10 +35,8 @@ class AMaxwellianParticleInitializer1D : public ::testing::Test density, InitFunctionArray{vx, vy, vz}, InitFunctionArray{vthx, vthy, vthz}, 1., nbrParticlesPerCell)} { - // } - GridLayoutT layout; ParticleArrayT particles; std::uint32_t nbrParticlesPerCell{10000}; @@ -46,7 +45,6 @@ class AMaxwellianParticleInitializer1D : public ::testing::Test - TEST_F(AMaxwellianParticleInitializer1D, loadsTheCorrectNbrOfParticles) { auto nbrCells = layout.nbrCells(); @@ -57,7 +55,6 @@ TEST_F(AMaxwellianParticleInitializer1D, loadsTheCorrectNbrOfParticles) - TEST_F(AMaxwellianParticleInitializer1D, loadsParticlesInTheDomain) { initializer->loadParticles(particles, layout); @@ -73,8 +70,56 @@ TEST_F(AMaxwellianParticleInitializer1D, loadsParticlesInTheDomain) } } +} // namespace PHARE::initializer::test_fn::func_1d + + +namespace PHARE::initializer::test_fn::func_2d +{ + +class AMaxwellianParticleInitializer2D : public ::testing::Test +{ +private: + using ParticleArrayT = ParticleArray<2>; + using InitFunctionArray = std::array, 3>; + using GridLayoutT = GridLayout>; + + + +public: + AMaxwellianParticleInitializer2D() + : layout{50} + , initializer{std::make_unique>( + density, InitFunctionArray{vx, vy, vz}, InitFunctionArray{vthx, vthy, vthz}, 1., + nbrParticlesPerCell)} + { + } + + TestGridLayout layout; + ParticleArrayT particles{layout.AMRBox()}; + std::uint32_t nbrParticlesPerCell{600}; + std::unique_ptr> initializer; +}; + +TEST_F(AMaxwellianParticleInitializer2D, loadsTheCorrectNbrOfParticles) +{ + // vector push back allocation observations + // 100 ppc = 262144 - 250000 = 12144 == 12144 * 64 / 1e6 == .7MB overallocated + // 600 ppc = 2097152 - 1500000 = 597152 * 64 / 1e6 == 38MB overallocated + + auto const expectedNbrParticles = nbrParticlesPerCell * product(layout.AMRBox().shape()); + initializer->loadParticles(particles, layout); + EXPECT_EQ(expectedNbrParticles, particles.size()); + auto outer_cell_count = std::pow(50, 2) - std::pow(48, 2); + EXPECT_EQ(particles.capacity(), + particles.size() + (outer_cell_count * nbrParticlesPerCell * .1)); + + // new method + // 100 ppc = (1511760 - 1500000) * 64 / 1e6 == 0.12544 overallocated + // 600 ppc = (1511760 - 1500000) * 64 / 1e6 == 0.75264 overallocated +} +} // namespace PHARE::initializer::test_fn::func_2d int main(int argc, char** argv) {