-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
minimize maxwellian vector capacity somewhat #898
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2,30 +2,30 @@ | |||||
#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 <SAMRAI/geom/CartesianPatchGeometry.h> | ||||||
#include <SAMRAI/hier/Box.h> | ||||||
#include <SAMRAI/hier/RefineOperator.h> | ||||||
#include <SAMRAI/pdat/CellOverlap.h> | ||||||
|
||||||
#include <functional> | ||||||
|
||||||
|
||||||
namespace PHARE | ||||||
{ | ||||||
namespace amr | ||||||
{ | ||||||
enum class ParticlesDataSplitType { | ||||||
coarseBoundary, | ||||||
enum class ParticlesDataSplitType : std::uint8_t { | ||||||
coarseBoundary = 0, | ||||||
interior, | ||||||
coarseBoundaryOld, | ||||||
coarseBoundaryNew | ||||||
|
@@ -53,6 +53,12 @@ namespace amr | |||||
template<typename ParticleArray, ParticlesDataSplitType splitType, typename Splitter> | ||||||
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<ParticlesData<ParticleArray>>( | ||||||
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<SAMRAI::geom::CartesianPatchGeometry>( | ||||||
destination.getPatchGeometry()); | ||||||
|
@@ -133,9 +139,15 @@ namespace amr | |||||
} | ||||||
} | ||||||
|
||||||
template<typename Fn> | ||||||
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<ParticleArray>& destParticlesData, | ||||||
|
@@ -166,43 +178,48 @@ 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}; | ||||||
|
||||||
Comment on lines
+181
to
+182
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Specify template arguments for The declaration of Apply this diff to correct the declaration: - std::array const particlesArrays{&srcInteriorParticles, &srcGhostParticles};
+ std::array<ParticleArray const*, 2> const particlesArrays{&srcInteriorParticles, &srcGhostParticles}; 📝 Committable suggestion
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it compiles without the templates, what makes you think it should have the templates? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @PhilipDeegan, you're right—since the code compiles and class template argument deduction is available from C++17 onwards, your code is valid as is. I apologize for the confusion. (_/) ✏️ Learnings added
|
||||||
auto const count_expected = [&]() { | ||||||
std::size_t incoming_estimate = 0; | ||||||
for (auto const& destinationBox : destBoxes) | ||||||
{ | ||||||
auto const coarseSplitBox | ||||||
= coarsen(phare_box_from<dim>(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. | ||||||
// In case of a coarseBoundary it will most likely give multiple boxes | ||||||
// 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<typename ParticleArray::value_type, nbRefinedPart> | ||||||
refinedParticles; | ||||||
auto particleRefinedPos = toFineGrid<interpOrder>(particle); | ||||||
auto const particleRefinedPos = toFineGrid<interpOrder>(particle); | ||||||
|
||||||
if (isInBox(splitBox, particleRefinedPos)) | ||||||
{ | ||||||
std::array<Particle_t, nbRefinedPart> 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 +260,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 | ||||||
} | ||||||
|
||||||
|
||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -44,7 +44,7 @@ class MaxwellianParticleInitializer : public ParticleInitializer<ParticleArray, | |||||||||||||||||||||||||
std::uint32_t const& nbrParticlesPerCell, std::optional<std::size_t> seed = {}, | ||||||||||||||||||||||||||
Basis const basis = Basis::Cartesian, | ||||||||||||||||||||||||||
std::array<InputFunction, 3> 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<ParticleArray, | |||||||||||||||||||||||||
, nbrParticlePerCell_{nbrParticlesPerCell} | ||||||||||||||||||||||||||
, basis_{basis} | ||||||||||||||||||||||||||
, rngSeed_{seed} | ||||||||||||||||||||||||||
, over_alloc_factor_{over_alloc_factor} | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
@@ -92,6 +93,7 @@ class MaxwellianParticleInitializer : public ParticleInitializer<ParticleArray, | |||||||||||||||||||||||||
std::uint32_t nbrParticlePerCell_; | ||||||||||||||||||||||||||
Basis basis_; | ||||||||||||||||||||||||||
std::optional<std::size_t> rngSeed_; | ||||||||||||||||||||||||||
double over_alloc_factor_ = .1; | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
@@ -178,6 +180,17 @@ void MaxwellianParticleInitializer<ParticleArray, GridLayout>::loadParticles( | |||||||||||||||||||||||||
auto randGen = getRNG(rngSeed_); | ||||||||||||||||||||||||||
ParticleDeltaDistribution<double> deltaDistrib; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
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; | ||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||
Comment on lines
+183
to
+188
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pass 'sum' by value in the lambda for 'std::accumulate' In the lambda function used with Apply this diff to adjust the lambda parameter: -auto const expected_size = std::accumulate(n, n + ndCellIndices.size(), std::size_t{0},
- [&](auto const& sum, auto const& density_value) {
+auto const expected_size = std::accumulate(n, n + ndCellIndices.size(), std::size_t{0},
+ [&](auto sum, auto const& density_value) { 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
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) | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
if (n[flatCellIdx] < densityCutOff_) | ||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,7 @@ NO_DISCARD auto cellAsPoint(Particle const& particle) | |
template<size_t dim> | ||
struct Particle | ||
{ | ||
std::array<std::uint8_t, 3> 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<int, dim> iCell = ConstArray<int, dim>(); | ||
std::array<double, dim> delta = ConstArray<double, dim>(); | ||
std::array<double, 3> v = ConstArray<double, 3>(); | ||
double weight = 0; // 8 | ||
double charge = 0; // 8 | ||
std::array<int, dim> iCell = ConstArray<int, dim>(); // 4 * dim | ||
std::array<double, dim> delta = ConstArray<double, dim>(); // 8 * dim | ||
std::array<double, 3> v = ConstArray<double, 3>(); // 8 * 3 | ||
Comment on lines
+58
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider a more maintainable approach for documenting member sizes. While the added size information is useful, it might become outdated if types change. Consider using Example implementation: static_assert(sizeof(weight) == 8, "Unexpected size for weight");
static_assert(sizeof(charge) == 8, "Unexpected size for charge");
static_assert(sizeof(iCell) == 4 * dim, "Unexpected size for iCell");
static_assert(sizeof(delta) == 8 * dim, "Unexpected size for delta");
static_assert(sizeof(v) == 8 * 3, "Unexpected size for v"); Alternatively, you could use Doxygen-style comments for better documentation: /// @brief Particle weight
/// @details Size: 8 bytes
double weight = 0; |
||
|
||
NO_DISCARD bool operator==(Particle<dim> const& that) const | ||
{ | ||
|
@@ -121,9 +121,9 @@ inline constexpr auto is_phare_particle_type | |
|
||
template<std::size_t dim, template<std::size_t> typename ParticleA, | ||
template<std::size_t> typename ParticleB> | ||
NO_DISCARD typename std::enable_if_t< | ||
is_phare_particle_type<dim, ParticleA<dim>> and is_phare_particle_type<dim, ParticleB<dim>>, | ||
bool> | ||
NO_DISCARD typename std::enable_if_t<is_phare_particle_type<dim, ParticleA<dim>> | ||
and is_phare_particle_type<dim, ParticleB<dim>>, | ||
bool> | ||
operator==(ParticleA<dim> const& particleA, ParticleB<dim> const& particleB) | ||
{ | ||
return particleA.weight == particleB.weight and // | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conflicting build configuration settings
The changes in the CMake configuration present a potential conflict:
RelWithDebInfo
toDebug
(line 81).-O3
has been added to theCMAKE_CXX_FLAGS
(line 85).These settings are contradictory:
-O3
flag enables maximum optimizations, which can interfere with debugging by reordering or optimizing out code.This combination may lead to unexpected behavior during debugging and potentially mask issues that would be apparent in a true debug build.
Consider one of the following approaches:
-O3
flag and keep theDebug
build type.RelWithDebInfo
build type, which balances optimization and debugging capabilities.Please clarify the intended goal of these changes to determine the most appropriate configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RelWithDebInfo includes
-DNDEBUG
which disables asserts, we want asserts with some optimizations. if we want to debug this build we will change it laterThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@PhilipDeegan, understood. Keeping asserts enabled with some optimizations makes sense in your context. I've noted this for future reviews.
(_/)
(•ᴥ•)💡
✏️ Learnings added