From 04b1b6926e64d5dfeb9e78a61dab0e913ba26a3d Mon Sep 17 00:00:00 2001 From: deegan Date: Tue, 15 Oct 2024 13:24:09 +0200 Subject: [PATCH] reserve refinement --- .github/workflows/cmake_ubuntu.yml | 4 +- .../field/refine/electric_field_refiner.hpp | 10 +-- .../particles/refine/particles_data_split.hpp | 68 ++++++++++++------- src/amr/utilities/box/amr_box.hpp | 22 +++++- .../maxwellian_particle_initializer.hpp | 28 ++++---- 5 files changed, 82 insertions(+), 50 deletions(-) diff --git a/.github/workflows/cmake_ubuntu.yml b/.github/workflows/cmake_ubuntu.yml index c718e7ab2..58ac44f3a 100644 --- a/.github/workflows/cmake_ubuntu.yml +++ b/.github/workflows/cmake_ubuntu.yml @@ -78,11 +78,11 @@ jobs: make -j2 && sudo make install && cd ../.. && rm -rf samrai cd ${{runner.workspace}}/build && rm -rf * cmake $GITHUB_WORKSPACE -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON --fresh \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo -Dasan=OFF \ + -DCMAKE_BUILD_TYPE=Debug -Dasan=OFF \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DlowResourceTests=ON -DdevMode=ON -Dbench=ON \ - -DCMAKE_CXX_FLAGS="-DPHARE_DIAG_DOUBLES=1 " -Dphare_configurator=ON + -DCMAKE_CXX_FLAGS="-O3 -DPHARE_DIAG_DOUBLES=1 " -Dphare_configurator=ON - name: Build working-directory: ${{runner.workspace}}/build diff --git a/src/amr/data/field/refine/electric_field_refiner.hpp b/src/amr/data/field/refine/electric_field_refiner.hpp index 57698b350..bd849659d 100644 --- a/src/amr/data/field/refine/electric_field_refiner.hpp +++ b/src/amr/data/field/refine/electric_field_refiner.hpp @@ -4,13 +4,15 @@ #include "core/def/phare_mpi.hpp" -#include - +#include "amr/amr_constants.hpp" #include "amr/resources_manager/amr_utils.hpp" + #include "core/utilities/constants.hpp" #include "core/data/grid/gridlayoutdefs.hpp" #include "core/utilities/point/point.hpp" +#include + #include namespace PHARE::amr @@ -43,8 +45,8 @@ class ElectricFieldRefiner { TBOX_ASSERT(coarseField.physicalQuantity() == fineField.physicalQuantity()); - auto const locFineIdx = AMRToLocal(fineIndex, fineBox_); - auto constexpr refinementRatio = 2; + auto const locFineIdx = AMRToLocal(fineIndex, fineBox_); + auto coarseIdx{fineIndex}; for (auto& idx : coarseIdx) idx = idx / refinementRatio; diff --git a/src/amr/data/particles/refine/particles_data_split.hpp b/src/amr/data/particles/refine/particles_data_split.hpp index 90c62cc9c..8bbe880c3 100644 --- a/src/amr/data/particles/refine/particles_data_split.hpp +++ b/src/amr/data/particles/refine/particles_data_split.hpp @@ -2,22 +2,22 @@ #define PHARE_PARTICLES_DATA_SPLIT_HPP +#include "core/def.hpp" +#include "phare_core.hpp" #include "core/def/phare_mpi.hpp" +#include "core/utilities/constants.hpp" -#include "core/def.hpp" -#include "amr/data/particles/particles_data.hpp" -#include "amr/resources_manager/amr_utils.hpp" #include "split.hpp" -#include "core/utilities/constants.hpp" -#include "phare_core.hpp" #include "amr/amr_constants.hpp" +#include "amr/utilities/box/amr_box.hpp" +#include "amr/resources_manager/amr_utils.hpp" +#include "amr/data/particles/particles_data.hpp" #include #include #include #include -#include namespace PHARE @@ -53,6 +53,12 @@ namespace amr template class ParticlesRefineOperator : public SAMRAI::hier::RefineOperator { + using Particle_t = typename ParticleArray::value_type; + static constexpr bool putParticlesInCoarseBoundary + = splitType == ParticlesDataSplitType::coarseBoundary + || splitType == ParticlesDataSplitType::coarseBoundaryOld + || splitType == ParticlesDataSplitType::coarseBoundaryNew; + public: static constexpr auto dim = Splitter::dimension; static constexpr auto interpOrder = Splitter::interp_order; @@ -99,7 +105,7 @@ namespace amr = std::dynamic_pointer_cast>( source.getPatchData(sourceComponent)); - // Finnaly we need the cartesion geometry of both patch. + // Finaly we need the cartesion geometry of both patch. auto patchGeomDestination = std::dynamic_pointer_cast( destination.getPatchGeometry()); @@ -133,9 +139,15 @@ namespace amr } } + template + static void _reserve(ParticleArray& particles, Fn&& counter) + { // only reserve for regular refinement of domain to start with + if constexpr (!putParticlesInCoarseBoundary) + particles.reserve(counter() * nbRefinedPart); + } /** @brief given two ParticlesData (destination and source), - * an overlap , a ratio and the geometry of both patches, perform the + * an overlap, a ratio and the geometry of both patches, perform the * splitting of coarse particles onto the destination patch */ void refine_(ParticlesData& destParticlesData, @@ -166,6 +178,21 @@ namespace amr // same for destinationGhostBox and destinationDomainBox the later will allow to get an // index relative to the interior + std::array const particlesArrays{&srcInteriorParticles, &srcGhostParticles}; + + auto const count_expected = [&]() { + std::size_t incoming_estimate = 0; + for (auto const& destinationBox : destBoxes) + { + auto const coarseSplitBox + = coarsen(phare_box_from(getSplitBox(destinationBox))); + for (auto const& sourceParticlesArray : particlesArrays) + incoming_estimate += sourceParticlesArray->nbr_particles_in(coarseSplitBox); + } + return incoming_estimate; + }; + _reserve(destDomainParticles, count_expected); + Splitter split; // The PatchLevelFillPattern had compute boxes that correspond to the expected filling. @@ -173,36 +200,25 @@ namespace amr // in case of interior, this will be just one box usually for (auto const& destinationBox : destBoxes) { - std::array particlesArrays{&srcInteriorParticles, &srcGhostParticles}; - auto splitBox = getSplitBox(destinationBox); + auto const splitBox = getSplitBox(destinationBox); - auto isInDest = [&destinationBox](auto const& particle) // + auto const isInDest = [&destinationBox](auto const& particle) // { return isInBox(destinationBox, particle); }; - for (auto const& sourceParticlesArray : particlesArrays) { for (auto const& particle : *sourceParticlesArray) { - std::array - refinedParticles; - auto particleRefinedPos = toFineGrid(particle); + auto const particleRefinedPos = toFineGrid(particle); if (isInBox(splitBox, particleRefinedPos)) { + std::array refinedParticles; split(particleRefinedPos, refinedParticles); - // we need to know in which of interior or levelGhostParticlesXXXX // arrays we must put particles - bool constexpr putParticlesInCoarseBoundary - = splitType == ParticlesDataSplitType::coarseBoundary - || splitType == ParticlesDataSplitType::coarseBoundaryOld - || splitType == ParticlesDataSplitType::coarseBoundaryNew; - - - if constexpr (putParticlesInCoarseBoundary) { if constexpr (splitType == ParticlesDataSplitType::coarseBoundary) @@ -243,9 +259,9 @@ namespace amr std::back_inserter(destDomainParticles), isInDest); } } // end is candidate for split - } // end loop on particles - } // end loop on source particle arrays - } // loop on destination box + } // end loop on particles + } // end loop on source particle arrays + } // loop on destination box } diff --git a/src/amr/utilities/box/amr_box.hpp b/src/amr/utilities/box/amr_box.hpp index 4b615acd9..8004a897c 100644 --- a/src/amr/utilities/box/amr_box.hpp +++ b/src/amr/utilities/box/amr_box.hpp @@ -2,13 +2,13 @@ #define PHARE_AMR_UTILITIES_BOX_BOX_HPP +#include "core/def.hpp" #include "core/def/phare_mpi.hpp" +#include "core/utilities/box/box.hpp" +#include "amr/amr_constants.hpp" #include "SAMRAI/hier/Box.h" -#include "core/utilities/box/box.hpp" -#include "core/def.hpp" - namespace PHARE::amr { @@ -85,6 +85,22 @@ struct Box : public PHARE::core::Box } }; +template +auto refine(core::Box box) +{ + for (std::uint8_t di = 0; di < dim; ++di) + box.lower[di] *= refinementRatio, box.upper[di] *= refinementRatio; + return box; +} +template +auto coarsen(core::Box box) +{ + for (std::uint8_t di = 0; di < dim; ++di) + box.lower[di] /= refinementRatio, box.upper[di] /= refinementRatio; + + return box; +} + } // namespace PHARE::amr #endif 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 e37a55d50..ff30af972 100644 --- a/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp +++ b/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp @@ -44,7 +44,7 @@ class MaxwellianParticleInitializer : public ParticleInitializer seed = {}, Basis const basis = Basis::Cartesian, std::array const& magneticField = {nullptr, nullptr, nullptr}, - double densityCutOff = 1e-5) + double const densityCutOff = 1e-5, double const over_alloc_factor = .1) : density_{density} , bulkVelocity_{bulkVelocity} , thermalVelocity_{thermalVelocity} @@ -54,6 +54,7 @@ class MaxwellianParticleInitializer : public ParticleInitializer rngSeed_; + double over_alloc_factor_ = .1; }; @@ -178,20 +180,16 @@ void MaxwellianParticleInitializer::loadParticles( auto randGen = getRNG(rngSeed_); ParticleDeltaDistribution deltaDistrib; - std::size_t const expected_size - = [&](auto const& _n /* or error: reference to local binding 'n' declared*/) { - std::size_t size = 0; - for (std::size_t flatCellIdx = 0; flatCellIdx < ndCellIndices.size(); ++flatCellIdx) - if (_n[flatCellIdx] >= densityCutOff_) - ++size; - return size * nbrParticlePerCell_; - }(n); - - 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); + auto const expected_size = std::accumulate(n, n + ndCellIndices.size(), std::size_t{0}, + [&](auto const& sum, auto const& density_value) { + return (density_value > densityCutOff_) + ? sum + nbrParticlePerCell_ + : sum; + }); + + auto const incoming_estimate + = (layout.AMRBox().surface_cell_count() * (nbrParticlePerCell_ * over_alloc_factor_)); + particles.reserve(expected_size + incoming_estimate); for (std::size_t flatCellIdx = 0; flatCellIdx < ndCellIndices.size(); ++flatCellIdx) {