|
chombo-discharge
|
AMR-hierarchy container of computational particles, stored per patch in Struct-of-Arrays form. More...
#include <CD_ParticleContainer.H>

Public Types | |
| using | Leaf = ParticleSoA< P, Traits > |
| The per-patch leaf type owned at every (level, box). | |
| using | LevelParticles = LayoutData< Leaf > |
| The per-level holder type (one Leaf per box on the level's DisjointBoxLayout). | |
Public Member Functions | |
| LevelTiles::LevelAndBox | findDestination (const RealVect &a_pos) const |
| Map a position to its owning (level, grid index, rank) via the finest containing tile. | |
Construction and lifetime | |
| ParticleContainer () | |
| Construct an empty, undefined container. Call define() before use. | |
| ~ParticleContainer ()=default | |
| Destructor. | |
| ParticleContainer (const ParticleContainer &)=delete | |
| Copy construction is deleted (holders are shared RefCountedPtr – a copy would alias). | |
| ParticleContainer & | operator= (const ParticleContainer &)=delete |
| Copy assignment is deleted (move-only ownership). | |
| void | define (const Vector< DisjointBoxLayout > &a_grids, const Vector< ProblemDomain > &a_domains, const Vector< Real > &a_dx, const Vector< int > &a_refRat, const RealVect &a_probLo, const int a_minBlockSize, const Vector< RefCountedPtr< LevelTiles > > &a_levelTiles, const int a_finestLevel, const std::string &a_realm, const Vector< RefCountedPtr< LevelData< BaseFab< bool > > > > *a_validCells) |
| Allocate the per-level holders and the per-level tile-ownership maps over the AMR grids. | |
Grid metadata | |
| const Vector< DisjointBoxLayout > & | getGrids () const |
| Per-level AMR grids. | |
| Vector< RealVect > | getDx () const |
| Per-level grid spacing. | |
| RealVect | getProbLo () const |
| Lower-left corner of the physical domain. | |
| int | getFinestLevel () const |
| Finest AMR level index. | |
| std::string | getRealm () const |
| Realm label. | |
Particle holders | |
| AMRParticlesSoA< P, Traits > & | getParticles () |
| The valid particles on all levels. | |
| const AMRParticlesSoA< P, Traits > & | getParticles () const |
| The valid particles on all levels (const). | |
| AMRParticlesSoA< P, Traits > & | getMaskParticles () |
| The halo/mask particles on all levels. | |
| const AMRParticlesSoA< P, Traits > & | getMaskParticles () const |
| The halo/mask particles on all levels (const). | |
| AMRParticlesSoA< P, Traits > & | getBufferParticles () |
| The grown-grid buffer particles on all levels. | |
| const AMRParticlesSoA< P, Traits > & | getBufferParticles () const |
| The grown-grid buffer particles on all levels (const). | |
| LevelParticles & | operator[] (const int a_lvl) |
| Valid particles on one level (index by DataIndex to reach a patch's Leaf). | |
| const LevelParticles & | operator[] (const int a_lvl) const |
| Valid particles on one level (const). | |
State | |
| bool | isOrganizedByCell () const |
| Whether the valid leaves are currently cell-sorted. | |
| bool | isDefined () const |
| Whether define() has been called. | |
Population | |
| void | clearParticles () |
| Drop all valid particles on every level (keeps each leaf's arena capacity). | |
| void | addParticlesDestructive (ParticleSoA< P, Traits > &a_particles) |
| Add a free-standing buffer of particles to the container, routing each to its owner. | |
Counting | |
| unsigned long long | getNumberOfValidParticlesLocal () const |
| Number of valid particles owned by this rank. | |
| unsigned long long | getNumberOfValidParticlesGlobal () const |
| Number of valid particles across all ranks. | |
| unsigned long long | getNumberOfOutcastParticlesLocal () const |
| Number of particles dropped off-domain by the most recent remap() on this rank. | |
| unsigned long long | getNumberOfOutcastParticlesGlobal () const |
| Number of particles dropped off-domain by the most recent remap(), across all ranks. | |
Dynamics | |
| void | remap () |
| Redistribute every valid particle to the patch/level/rank that owns its cell. | |
| void | preRegrid () |
| Cache the current valid particles ahead of a regrid. | |
| void | regrid (const Vector< DisjointBoxLayout > &a_grids, const Vector< ProblemDomain > &a_domains, const Vector< Real > &a_dx, const Vector< int > &a_refRat, const int a_minBlockSize, const Vector< RefCountedPtr< LevelTiles > > &a_levelTiles, const int a_newFinestLevel) |
| Rebuild over a new AMR layout and redistribute the preRegrid()-cached particles onto it. | |
Ghost particles | |
| void | fillGhostParticles (const AMRParticleGhostMask &a_maskSame, const AMRParticleGhostMask &a_maskCoarToFine, const AMRParticleGhostMask &a_maskFineToCoar) |
| Fill each patch's ghost halo from prebuilt Realm particle ghost masks. | |
| void | clearGhostParticles () |
| Remove every ghost particle (any non-Valid GhostType) from all levels and patches. | |
| void | claimOwnership (const bool a_onlyValidRegion) |
| Claim ownership of this rank's particles by stamping their owner rank (rankID = procID()). | |
| long long | resetParticleIDs (const bool a_onlyValidRegion, const ParticleID a_startID) |
| Assign globally-unique, contiguous particle IDs to the owned particles. | |
Halo and buffer particles | |
| void | copyMaskParticles (const Vector< RefCountedPtr< LevelData< BaseFab< bool > > > > &a_mask) |
| Copy the valid particles selected by a per-cell mask into the mask holder, all levels. | |
| void | copyMaskParticles (const int a_level, const LevelData< BaseFab< bool > > &a_mask) |
| Copy the valid particles whose cell the mask marks true into the mask holder, one level. | |
| void | transferMaskParticles (const Vector< RefCountedPtr< LevelData< BaseFab< bool > > > > &a_mask) |
| Move the valid particles selected by a per-cell mask into the mask holder, all levels. | |
| void | transferMaskParticles (const int a_level, const LevelData< BaseFab< bool > > &a_mask) |
| Move the valid particles whose cell the mask marks true into the mask holder, one level. | |
| void | clearMaskParticles () |
| Drop all mask/halo particles on every level (keeps capacity). | |
| void | clearBufferParticles () |
| Drop all buffer particles on every level (keeps capacity). | |
| const Vector< BoxLayout > & | getGrownGrids () const |
| Per-level grown grids that the buffer particles live on. | |
| void | transferParticles (AMRParticlesSoA< P, Traits > &a_source) |
| Move all particles from another holder (on the same valid grids) into the valid holder. | |
Cell sorting | |
| void | organizeParticlesByCell () |
| Cell-sort every valid leaf (counting sort into Fortran cell order + CSR cell offsets). | |
| void | organizeParticlesByPatch () |
| Return to a by-patch view (the leaves remain a single contiguous array per patch). | |
Protected Types | |
| using | PoolKey = std::pair< int, unsigned int > |
| Pool key identifying a destination patch: (level, grid index within the level). | |
| using | MoverPool = std::vector< std::map< PoolKey, Leaf > > |
| Per-rank pool of movers: pool[rank] maps a destination patch to a small SoA of particles. | |
Protected Member Functions | |
| void | setupGrownGrids () |
| Build the grown grids (buffer-particle layout): boxes grown by the refinement factor. | |
| MoverPool | gatherToPool (AMRParticlesSoA< P, Traits > &a_source, const Vector< DisjointBoxLayout > &a_sourceGrids) |
| Gather every particle of a source holder into a per-rank, per-destination-patch pool. | |
| MoverPool | gatherMoversToPool () |
| Mask fast path for remap(): pool ONLY the movers, leaving stayers in place. | |
| MoverPool | gatherGhostsFromMasks (const AMRParticleGhostMask &a_maskSame, const AMRParticleGhostMask &a_maskCoarToFine, const AMRParticleGhostMask &a_maskFineToCoar) |
| Gather ghost copies into a per-rank pool using prebuilt particle ghost masks. | |
| void | distributeFromPool (MoverPool &a_pool, const bool a_setOwnerToReceiver) |
| Assign a pool into the valid holders: local appends + MPI scatter. | |
| IntVect | cellIndex (const int a_lvl, const RealVect &a_pos) const |
| Cell index containing a position on a given level (floor((x - probLo)/dx)). | |
| bool | inValidBox (const int a_lvl, const Box &a_box, const RealVect &a_pos) const |
| True if a position's cell lies inside a (grid) box on a given level. | |
Protected Attributes | |
| Vector< DisjointBoxLayout > | m_grids |
| Per-level AMR grids. | |
| Vector< ProblemDomain > | m_domains |
| Per-level problem domains. | |
| Vector< RealVect > | m_dx |
| Per-level grid spacing (isotropic, stored as RealVect). | |
| Vector< int > | m_refRat |
| Per-level refinement ratios (entry l is the ratio between level l and l+1). | |
| Vector< RefCountedPtr< LevelTiles > > | m_levelTiles |
| Per-level tile-ownership maps (cell tile -> owning grid index / rank), used by remap(). | |
| RealVect | m_probLo |
| Lower-left corner of the physical domain. | |
| int | m_minBlockSize |
| Grid blocking factor (tile size). | |
| int | m_finestLevel |
| Finest AMR level index. | |
| unsigned long long | m_numOutcastLocal |
| Particles dropped off-domain by the most recent remap() (local count). | |
| std::string | m_realm |
| Realm label (diagnostics only). | |
| const Vector< RefCountedPtr< LevelData< BaseFab< bool > > > > * | m_validCells = nullptr |
| Optional alias to the realm's valid-cell mask (true = cell not covered by a finer level). | |
| bool | m_isDefined |
| Whether define() has been called. | |
| bool | m_isOrganizedByCell |
| Whether the valid leaves are currently cell-sorted. | |
| AMRParticlesSoA< P, Traits > | m_particles |
| Valid particles: one ParticleSoA leaf per box, per level. | |
| AMRParticlesSoA< P, Traits > | m_cacheParticles |
| Regrid cache: the pre-regrid valid holders, kept alive over the old layout by preRegrid(). | |
| Vector< DisjointBoxLayout > | m_cacheGrids |
| The old (pre-regrid) grids the cache holders are defined on (for iterating the cache). | |
| AMRParticlesSoA< P, Traits > | m_maskParticles |
| Halo/mask particles per level. | |
| AMRParticlesSoA< P, Traits > | m_bufferParticles |
| Grown-grid buffer particles per level (on m_grownGrids; filled during halo deposition). | |
| Vector< BoxLayout > | m_grownGrids |
| Per-level grown grids (boxes grown by the refinement factor on finer levels) for the buffer. | |
AMR-hierarchy container of computational particles, stored per patch in Struct-of-Arrays form.
ParticleContainer owns particles distributed across an AMR hierarchy. For every level it holds one LayoutData<ParticleSoA<P>> indexed by DataIndex over that level's DisjointBoxLayout, so the particles of a single patch are reached as container[lvl][din] and stored contiguously in Struct-of-Arrays form (see ParticleSoA). Each particle carries a position and a weight (owned by the leaf) plus the user payload P, which contributes the extra per-particle columns.
Three parallel sets of per-level leaves are maintained:
The per-level holders are shared RefCountedPtr, so the container is move-only: copy construction and copy assignment are deleted (a copy would alias the holders). Construct an empty container, then call define() with the grids and AMR metadata before any other use; isDefined() reports readiness.
A particle belongs to the patch on the finest level whose cell contains its position. After particles move, remap() routes each one back to its owning patch – across MPI ranks and across levels as needed. On a regrid, call preRegrid() before the grids change and regrid() afterwards to carry the particles onto the new layout. Particles that leave the domain are dropped and reported by getNumberOfOutcastParticlesLocal() / getNumberOfOutcastParticlesGlobal().
A leaf stores its particles in arbitrary (append) order by default. organizeParticlesByCell() sorts each valid leaf so that the particles of a cell occupy a contiguous range (queried through the leaf's CSR cell offsets); organizeParticlesByPatch() returns to the unsorted view. isOrganizedByCell() reports the current state.
| P | User payload struct contributing the per-particle payload columns; defaults to NoPayload. |
| Traits | Column descriptor for the payload; defaults to ParticleTraits |
.
|
inline |
Add a free-standing buffer of particles to the container, routing each to its owner.
The buffer (e.g. filled by ParticleManagement::drawRandomParticles(ParticleSoA)) is catenated onto a local leaf – O(1) when that leaf is empty – and then remap() routes every particle (including across ranks and levels) to the patch/level/rank that owns its position. a_particles is left empty. Assumes this rank owns at least one box (true whenever level 0 covers the domain). Unlike addParticlesLocal(), the positions need not already belong to this rank.
| [in,out] | a_particles | Buffer of particles to ingest (emptied on return). |
|
inlineprotected |
Cell index containing a position on a given level (floor((x - probLo)/dx)).
| [in] | a_lvl | Level index. |
| [in] | a_pos | Position. |
|
inline |
Claim ownership of this rank's particles by stamping their owner rank (rankID = procID()).
Ghost particles (isGhost()) are always left untouched, so a ghost keeps the owner rank it carries. For non-ghost particles: when a_onlyValidRegion is true, only those whose cell lies inside the leaf's own grid box are claimed and out-of-box strays are left untouched; when false, every non-ghost particle is claimed. The region test is purely geometric on the ungrown patch box (it does not consider finer-level coverage or GhostType). No MPI communication.
| [in] | a_onlyValidRegion | Restrict to non-ghost particles inside the leaf's grid box. |
|
inline |
Remove every ghost particle (any non-Valid GhostType) from all levels and patches.
Owned (Valid) particles are left untouched. Removal is by swap-and-pop, so particle order within a leaf is not preserved. Keeps leaf capacity.
|
inline |
Copy the valid particles whose cell the mask marks true into the mask holder, one level.
Clears the level's mask leaves, then COPIES (keeps in the valid holder) every valid particle whose cell is true in the mask. Ids/rank are preserved.
| [in] | a_level | Level to fill. |
| [in] | a_mask | Per-cell boolean mask over that level's valid grids (box == grid box). |
|
inline |
Copy the valid particles selected by a per-cell mask into the mask holder, all levels.
| [in] | a_mask | Per-level cell masks (skipped where null). |
|
inline |
Allocate the per-level holders and the per-level tile-ownership maps over the AMR grids.
Allocates one empty Leaf per box for the valid, mask, and buffer holders on every level in [0, a_finestLevel], and builds a LevelTiles per level (from the grids + blocking factor) used by remap() to map a particle to its owning patch/rank. The mask and buffer holders start empty; they are populated on demand by copyMaskParticles()/transferMaskParticles() and the deposition routines. Must be called once before any other operation.
| [in] | a_grids | Per-level DisjointBoxLayouts. |
| [in] | a_domains | Per-level problem domains. |
| [in] | a_dx | Per-level (isotropic) grid spacing. |
| [in] | a_refRat | Per-level refinement ratio (entry l is the ratio between level l and l+1). |
| [in] | a_probLo | Lower-left corner of the physical domain. |
| [in] | a_minBlockSize | Grid blocking factor (tile size); the grids must be unions of minBlockSize-sized boxes for the tile ownership to be exact. |
| [in] | a_levelTiles | The owning Realm's per-level tile->box maps, aliased (never built locally) as the patch-locating structure used by remap(). Must correspond to a_grids. Not owned; must outlive this container. |
| [in] | a_finestLevel | Finest AMR level index. |
| [in] | a_realm | Realm label (diagnostics only). |
| [in] | a_validCells | Optional alias to the realm's valid-cell mask (true = cell not covered by a finer level), enabling remap()'s stayer fast path. Pass nullptr to always re-pool every particle. Not owned; must outlive this container. |
|
inlineprotected |
Assign a pool into the valid holders: local appends + MPI scatter.
| [in,out] | a_pool | Per-rank pool (consumed). Same-rank bins are catenated into the destination leaf; cross-rank bins are linearized and Alltoallv'd. |
| [in] | a_setOwnerToReceiver | If true, every cross-rank particle's rankID is set to the receiving rank (remap/regrid ownership). If false, the rankID carried in the pool is preserved (ghost particles keep their owner). |
|
inline |
Fill each patch's ghost halo from prebuilt Realm particle ghost masks.
A ghost particle is a transient, non-owned copy of a particle that lives in an adjacent region (a neighbouring patch on the same level, the next-coarser level, or the next-finer level) and overlaps this patch's ghosted box. For every valid particle, this scatters a copy to each destination patch listed by the masks for the particle's cell: same-level targets from a_maskSame, next-finer targets from a_maskCoarToFine, and next-coarser targets from a_maskFineToCoar. Copies are appended into the destination leaf (same-rank directly, cross-rank via MPI), tagged with the GhostType from the receiver's view (SameLevel / Coarse / Fine) so consumers can tell them from owned particles via ParticleSoA::isGhost(), and keep the source's particleID. clearGhostParticles() is called first so it is safe to refill; ghosts are transient (remap()/preRegrid()/regrid() drop them). Pass AmrMesh::getTrivialParticleGhostMask() for a direction that should not scatter. The masks must have been built on the same grids as this container (see AmrMesh::registerParticleGhostMask and AmrMesh::getParticleGhostMask(realm, width)). Periodic domains are not supported (mask construction aborts on them).
| [in] | a_maskSame | Same-level ghost mask (source cell -> same-level target boxes). |
| [in] | a_maskCoarToFine | Coarse-to-fine ghost mask (source cell -> next-finer target boxes). |
| [in] | a_maskFineToCoar | Fine-to-coarse ghost mask (source cell -> next-coarser target boxes). |
|
inline |
Map a position to its owning (level, grid index, rank) via the finest containing tile.
Thin wrapper over the shared LevelTiles::findDestination point->block core, passing this container's aliased grid metadata (probLo, dx, minBlockSize, level tiles). Public because the distributed nearest-neighbor particle merge (ParticleManagement::mergeNearestNeighborsTree) locates each newly created merged particle's owning patch/rank through the SAME tile-hash query remap() uses internally, rather than a linear scan over patches – see PositionLocator in CD_NearestNeighborParticleMerge.H.
| [in] | a_pos | Particle position. |
|
inlineprotected |
Gather ghost copies into a per-rank pool using prebuilt particle ghost masks.
For each valid particle, reads its cell's target boxes from the three masks and bins a copy per (destination level, grid index, rank) with the GhostType from the receiver's view (SameLevel / Coarse / Fine); particleID preserved, rankID set to this rank (the owner). Distribute the returned pool with a_setOwnerToReceiver == false. A trivial (empty) mask contributes nothing.
| [in] | a_maskSame | Same-level mask. |
| [in] | a_maskCoarToFine | Coarse-to-fine mask (targets on the next-finer level). |
| [in] | a_maskFineToCoar | Fine-to-coarse mask (targets on the next-coarser level). |
|
inlineprotected |
Mask fast path for remap(): pool ONLY the movers, leaving stayers in place.
Scans m_particles in place; a particle still inside its box AND in a cell flagged valid by m_validCells (not covered by a finer level) is a stayer and is left untouched. Every other particle is a mover: it is copied into the returned pool (ids preserved, rankID set to the new owner) and swap-popped out of its leaf. Off-domain movers are counted into m_numOutcastLocal (reset here). Requires m_validCells to be non-null and sized to m_finestLevel+1 (the caller checks this).
|
inlineprotected |
Gather every particle of a source holder into a per-rank, per-destination-patch pool.
Reads each particle, resolves its owning (level, grid index, rank) on the CURRENT tile maps, and copies it into the pool (ids preserved, rankID set to the new owner). Off-domain particles are counted into m_numOutcastLocal (which this resets).
| [in] | a_source | Source holders (e.g. the valid particles, or the regrid cache). |
| [in] | a_sourceGrids | The DisjointBoxLayouts the source holders are defined on. |
|
inline |
The grown-grid buffer particles on all levels.
|
inline |
The grown-grid buffer particles on all levels (const).
|
inline |
Per-level grid spacing.
|
inline |
Finest AMR level index.
|
inline |
Per-level AMR grids.
|
inline |
Per-level grown grids that the buffer particles live on.
|
inline |
The halo/mask particles on all levels.
|
inline |
The halo/mask particles on all levels (const).
|
inline |
Number of particles dropped off-domain by the most recent remap(), across all ranks.
|
inline |
Number of particles dropped off-domain by the most recent remap() on this rank.
|
inline |
Number of valid particles across all ranks.
|
inline |
Number of valid particles owned by this rank.
Ghost particles (any non-Valid GhostType) are excluded – only owned, valid particles are counted, even if a transient ghost halo is currently present in the leaves.
|
inline |
The valid particles on all levels.
|
inline |
The valid particles on all levels (const).
|
inline |
Lower-left corner of the physical domain.
|
inline |
Realm label.
|
inlineprotected |
True if a position's cell lies inside a (grid) box on a given level.
Purely geometric valid-region test shared by claimOwnership/resetParticleIDs – the box is the leaf's ungrown patch box, so a particle in its patch's ghost shell tests false.
| [in] | a_lvl | Level index. |
| [in] | a_box | Box (typically the leaf's grid box). |
| [in] | a_pos | Position. |
|
inline |
Whether define() has been called.
|
inline |
Whether the valid leaves are currently cell-sorted.
|
delete |
Copy assignment is deleted (move-only ownership).
|
inline |
Valid particles on one level (index by DataIndex to reach a patch's Leaf).
Chain a second index by DataIndex to reach the patch's ParticleSoA leaf:
| [in] | a_lvl | Level index. |
|
inline |
Valid particles on one level (const).
| [in] | a_lvl | Level index. |
|
inline |
Cell-sort every valid leaf (counting sort into Fortran cell order + CSR cell offsets).
After this, each leaf is isSorted() and cell c owns the contiguous particle range [cellStart(c), cellStart(c+1)) (query via the leaf accessors). Sets isOrganizedByCell().
|
inline |
Return to a by-patch view (the leaves remain a single contiguous array per patch).
Clears isOrganizedByCell(); the CSR cell offsets are no longer to be relied upon. There is no data movement – the leaf already holds all particles of a patch contiguously.
|
inline |
|
inline |
Rebuild over a new AMR layout and redistribute the preRegrid()-cached particles onto it.
Re-allocates the per-level holders and tile maps over the new grids (all levels), then runs the same pool->map->scatter as remap() but sourced from the cache. Positions are unchanged; each cached particle is routed to the patch/level/rank owning its cell on the NEW layout, with ids preserved. Off-domain particles are counted in getNumberOfOutcastParticles*(). Must follow a preRegrid().
| [in] | a_grids | New per-level DisjointBoxLayouts. |
| [in] | a_domains | New per-level problem domains. |
| [in] | a_dx | New per-level (isotropic) grid spacing. |
| [in] | a_refRat | New per-level refinement ratios. |
| [in] | a_minBlockSize | Grid blocking factor (tile size) for the new grids. |
| [in] | a_levelTiles | The owning Realm's per-level tile->box maps for the new grids, aliased (never built locally). Must correspond to a_grids. |
| [in] | a_newFinestLevel | New finest AMR level index. |
|
inline |
Redistribute every valid particle to the patch/level/rank that owns its cell.
Pool model: collect all valid particles, map each to its destination via the finest-level tile that contains it (LevelTiles), append same-rank movers into the destination leaf and scatter cross-rank movers with MPI. Particles whose cell is not owned by any tile on any level (off-domain) are dropped and counted in getNumberOfOutcastParticles*(). Invalidates any cell-sort. Particle ids are preserved; rankID is set to the new owning rank.
|
inline |
Assign globally-unique, contiguous particle IDs to the owned particles.
Ghost particles (isGhost()) are always left untouched, so a ghost keeps the source's id. A non-ghost particle qualifies for a new id iff a_onlyValidRegion is false OR its cell lies inside the leaf's own grid box; a non-ghost that does not qualify (an out-of-box stray, only possible when a_onlyValidRegion is true) is set to ParticleSoA::s_invalidID. Qualifying particles receive contiguous ids in rank order (rank 0 first) starting at a_startID, made unique across ranks via an all-gather of the per-rank counts and an exclusive prefix. The region test is purely geometric on the ungrown patch box. Note: the assigned ids are a numbering snapshot, not a persistent identity – they depend on the rank/box ordering and change across regrids and different rank counts.
| [in] | a_onlyValidRegion | Restrict new ids to non-ghost particles inside the leaf's grid box. |
| [in] | a_startID | Global id of the first assigned particle; ids occupy [a_startID, a_startID + return). |
|
inline |
Move the valid particles whose cell the mask marks true into the mask holder, one level.
Like copyMaskParticles but MOVES (removes from the valid holder via swap-and-pop, which does not preserve order). Does not clear the mask holder first (accumulates). Ids/rank preserved.
| [in] | a_level | Level to fill. |
| [in] | a_mask | Per-cell boolean mask over that level's valid grids (box == grid box). |
|
inline |
Move the valid particles selected by a per-cell mask into the mask holder, all levels.
| [in] | a_mask | Per-level cell masks (skipped where null). |
|
inline |
Move all particles from another holder (on the same valid grids) into the valid holder.
Per level/patch, catenates the source leaf into the valid leaf (a per-column bulk move preserving ids/rank, or an O(1) arena swap when the valid leaf is empty), leaving the source empty. Used to return halo/mask particles to the valid holder after a HaloNGP deposition. Assumes a_source is defined over this container's valid grids.
| [in,out] | a_source | Holder to drain into the valid particles. |
|
protected |
Optional alias to the realm's valid-cell mask (true = cell not covered by a finer level).
Used by remap() to leave "stayer" particles in place: a particle still inside its box and in a cell not covered by a finer grid cannot change owner, so it need not be re-pooled. Null (or a stale size) makes remap() fall back to re-pooling every particle. Aliases a stable Realm member that is rebuilt each regrid; set at define(), never owned here.