chombo-discharge
Loading...
Searching...
No Matches
Protected Member Functions | Static Protected Member Functions | Protected Attributes | List of all members
ParticleSoA< P, Traits > Class Template Reference

Arena-backed Struct-of-Arrays particle container for a single grid patch. More...

#include <CD_ParticleSoA.H>

Inheritance diagram for ParticleSoA< P, Traits >:
Inheritance graph
[legend]

Public Member Functions

Construction and lifetime
 ParticleSoA ()=default
 Construct an empty container.
 
 ~ParticleSoA ()
 Destructor (frees the arena).
 
 ParticleSoA (const ParticleSoA &)=delete
 Copy construction is deleted (move-only).
 
ParticleSoAoperator= (const ParticleSoA &)=delete
 Copy assignment is deleted (move-only).
 
 ParticleSoA (ParticleSoA &&a_other) noexcept
 Move constructor (steals the arena).
 
ParticleSoAoperator= (ParticleSoA &&a_other) noexcept
 Move assignment (steals the arena).
 
ParticleSoA deepCopy () const
 Explicit deep copy: a new container with a private arena duplicating every particle.
 
void deepCopyTo (ParticleSoA &a_dst) const
 Deep copy into an existing destination, reusing its arena when possible.
 
void swap (ParticleSoA &a_other) noexcept
 Swap the entire state (arena, size, capacity, sort) with another container in O(1).
 
Size and capacity
std::size_t size () const noexcept
 Number of particles currently stored.
 
std::size_t capacity () const noexcept
 Allocated capacity in particles.
 
bool empty () const noexcept
 Whether the container holds no particles.
 
void clear () noexcept
 Drop all particles (keeps the arena; invalidates the cell sort).
 
void reserve (const std::size_t a_capacity)
 Ensure capacity for at least a_capacity particles (reallocates + moves on growth).
 
void resize (const std::size_t a_count)
 Set the particle count (grows capacity if needed; new slots are uninitialized).
 
void shrinkToFit ()
 Reclaim unused capacity by reallocating the arena down to the current size.
 
Population
void append (const RealVect &a_position, const double a_weight)
 Append one particle with a default-constructed payload.
 
void append (const RealVect &a_position, const double a_weight, const P &a_payload)
 Append one particle with the given payload.
 
void append (const ParticleSoA &a_other)
 Append every particle of another container (bulk catenate; all columns, incl. id/rank).
 
void appendParticle (const ParticleSoA &a_src, const std::size_t a_index)
 Append a single particle (all columns, incl. id/rank) copied from another container.
 
void catenate (ParticleSoA &a_other)
 Move every particle of another container into this one, leaving a_other empty (catenate).
 
gather (const std::size_t a_index) const
 Gather particle i's payload back into the AoS payload view.
 
void remove (const std::size_t a_index) noexcept
 Remove particle i using swap-and-pop (O(1), does NOT preserve order).
 
Column and field access
template<std::size_t K>
ColumnType< K > * columnByIndex () noexcept
 Typed base pointer of column K (low-level).
 
template<std::size_t K>
const ColumnType< K > * columnByIndex () const noexcept
 Const typed base pointer of column K (low-level).
 
template<auto Member>
auto * column () noexcept
 Whole payload column selected by member pointer (raw pointer, vectorizable).
 
template<auto Member>
const auto * column () const noexcept
 Const whole payload column selected by member pointer.
 
template<auto Member>
auto & get (const std::size_t a_index) noexcept
 One particle's payload field selected by member pointer.
 
template<auto Member>
const auto & get (const std::size_t a_index) const noexcept
 Const overload of get<&P::field>(i).
 
double * positionColumn (const int a_dir) noexcept
 Raw position component column dir (double*, for SIMD kernels).
 
const double * positionColumn (const int a_dir) const noexcept
 Const raw position component column dir.
 
double * weightColumn () noexcept
 Raw weight column (double*).
 
const double * weightColumn () const noexcept
 Const raw weight column.
 
Raw arena and bulk transfer
const void * data () const noexcept
 Raw arena pointer (column-major); a compact container's whole data span.
 
void * data () noexcept
 Mutable raw arena pointer (e.g. zero-copy MPI receive into the arena).
 
std::size_t byteSpan () const noexcept
 Byte span of the live data (for a compact container, one contiguous memcpy/MPI_Send).
 
Cell sorting (CSR)
void sortByCell (const Box &a_box, const RealVect &a_dx, const RealVect &a_probLo)
 Counting-sort the columns into Fortran cell order and build CSR cell offsets.
 
bool isSorted () const noexcept
 Whether the container is currently cell-sorted (false after append/remove).
 
bool isSortedAgainst (const Box &a_box, const RealVect &a_dx, const RealVect &a_probLo) const noexcept
 Whether the container is cell-sorted against exactly this cell domain.
 
std::size_t numCells () const noexcept
 Number of cells in the CSR sort (0 if not sorted).
 
std::size_t cellStart (const std::size_t a_cell) const noexcept
 CSR start offset of cell c (valid after sortByCell; requires c <= numCells()).
 
std::size_t particlesInCell (const std::size_t a_cell) const noexcept
 Number of particles in cell c (valid after sortByCell).
 
std::pair< std::size_t, std::size_t > cellRange (const std::size_t a_cell) const noexcept
 Half-open particle index range [begin, end) owned by cell c (valid after sortByCell).
 
void extractCell (const std::size_t a_cell, ParticleSoA &a_out) const
 Extract cell c's particles (the CSR range [cellStart(c), cellStart(c+1))) into a_out.
 

Protected Member Functions

std::size_t cellKey (const std::size_t a_index, const Box &a_box, const RealVect &a_dx, const RealVect &a_probLo) const noexcept
 Compute the Fortran (x-fastest) cell index of particle i within the sort domain.
 
bool checkCellSort (const Box &a_box, const RealVect &a_dx, const RealVect &a_probLo) const noexcept
 Verify that the CSR mapping really does describe the current particle positions.
 
void steal (ParticleSoA &a_o) noexcept
 Steal another container's arena (move helper).
 
void growTo (const std::size_t a_needed)
 Grow the arena to hold at least a_needed particles, geometrically.
 
void growIfFull ()
 Grow geometrically if the container is full (called before writing slot m_size).
 
template<std::size_t... I>
std::size_t computeOffsets (const std::size_t a_capacity, std::array< std::size_t, s_numColumns > &a_off, std::index_sequence< I... >) const noexcept
 Compute per-column byte offsets for a given capacity; returns the total bytes.
 
template<std::size_t... I>
void setColPtrs (const std::array< std::size_t, s_numColumns > &a_off, std::index_sequence< I... >) noexcept
 Cache the column base pointers from a fresh buffer + offsets.
 
template<std::size_t... I>
void moveColumns (void *a_newBuf, const std::array< std::size_t, s_numColumns > &a_off, std::index_sequence< I... >) noexcept
 Contiguously memcpy every column's live region into a freshly-allocated buffer.
 
template<std::size_t... I>
void copyLiveColumnsTo (ParticleSoA &a_dst, std::index_sequence< I... >) const noexcept
 Copy this container's m_size live elements of every column into another container.
 
template<std::size_t... I>
void appendColumnsFrom (const ParticleSoA &a_other, const std::size_t a_at, std::index_sequence< I... >) noexcept
 Bulk-append another container's live columns at slot a_at of this container's columns.
 
template<std::size_t... I>
void copyParticleColumns (const ParticleSoA &a_src, const std::size_t a_srcIdx, const std::size_t a_dstIdx, std::index_sequence< I... >) noexcept
 Copy one particle's every column from a_src[a_srcIdx] into this[a_dstIdx].
 
void reallocate (const std::size_t a_capacity)
 Allocate a new arena and reallocate/move the columns into it (growth path).
 
void permute (const std::vector< std::size_t > &a_dest)
 Reorder every column in place by a_dest (a_dest[i] = new slot of old particle i).
 
template<std::size_t K>
void scatterColumn (void *a_newBuf, const std::size_t a_off, const std::vector< std::size_t > &a_dest) noexcept
 Per-column scatter for permute(): newcol[dest[i]] = oldcol[i].
 
template<std::size_t... I>
void scatterColumns (void *a_newBuf, const std::array< std::size_t, s_numColumns > &a_off, const std::vector< std::size_t > &a_dest, std::index_sequence< I... >) noexcept
 Scatter every column for permute() into a freshly-allocated buffer.
 
template<std::size_t... J>
void writePayload (const P &a_p, std::index_sequence< J... >) noexcept
 Write the payload columns of slot m_size from a payload struct.
 
template<std::size_t... J>
gatherPayload (const std::size_t a_index, std::index_sequence< J... >) const
 Read the payload columns of slot a_index into a payload struct.
 
template<std::size_t... I>
void removeImpl (const std::size_t a_index, std::index_sequence< I... >) noexcept
 Swap-and-pop slot a_index in every column.
 
template<std::size_t... I>
void linearizeImpl (unsigned char *a_buf, const std::size_t a_index, std::index_sequence< I... >) const noexcept
 Push every column of particle a_index onto a byte buffer (MPI).
 
template<std::size_t... I>
void delinearizeImpl (const unsigned char *a_buf, std::index_sequence< I... >) noexcept
 Pull every column of one particle off a byte buffer into slot m_size (MPI).
 
template<std::size_t K>
void pullColumn (const unsigned char *&a_buf) noexcept
 Pull one column's value off a byte buffer into slot m_size and advance the pointer.
 
template<std::size_t... J>
void h5LinearizePayload (unsigned char *&a_buf, const std::size_t a_index, std::index_sequence< J... >) const noexcept
 Push the HDF5 payload subset of particle a_index onto a byte buffer.
 
template<std::size_t... J>
void h5DelinearizePayload (const unsigned char *&a_buf, std::index_sequence< J... >) noexcept
 Pull the HDF5 payload subset off a byte buffer into slot m_size.
 
template<std::size_t... I>
std::size_t byteSpanImpl (std::index_sequence< I... >) const noexcept
 Byte span of the live data: max over columns of (offset + used bytes).
 

Static Protected Member Functions

static std::size_t alignUp (const std::size_t a_x) noexcept
 Round a_x up to the next multiple of s_align.
 
template<std::size_t... J>
static constexpr std::size_t h5PayloadSize (std::index_sequence< J... >) noexcept
 Compile-time byte size of the HDF5 payload subset.
 

Protected Attributes

void * m_buffer = nullptr
 The single arena allocation.
 
std::size_t m_capacity = 0
 Capacity in particles.
 
std::size_t m_bytes = 0
 Byte size of the arena at m_buffer (zero when m_buffer is null).
 
std::size_t m_size = 0
 Live particle count.
 
bool m_sorted = false
 Whether m_cellStart is valid.
 
std::array< void *, s_numColumnsm_colPtrs {}
 Cached column base pointers into m_buffer.
 
std::vector< std::size_t > m_cellStart
 CSR cell offsets (size numCells+1 when sorted).
 
Box m_sortBox
 Patch box the CSR mapping in m_cellStart was built against (meaningful only when m_sorted).
 
RealVect m_sortDx = RealVect::Zero
 Grid spacing the CSR mapping was built against (meaningful only when m_sorted).
 
RealVect m_sortProbLo = RealVect::Zero
 Lower domain corner the CSR mapping was built against (meaningful only when m_sorted).
 

Compile-time layout (indices and sizes)

using PayloadColumns = std::remove_cv_t< std::remove_reference_t< decltype(Traits::columns)> >
 The payload columns descriptor tuple type (tuple of pointer-to-member).
 
static constexpr std::size_t s_numPayloadColumns = std::tuple_size<PayloadColumns>::value
 Number of user-declared payload columns.
 
static constexpr std::size_t s_weightCol = SpaceDim
 Column index of the weight (immediately after the SpaceDim position columns).
 
static constexpr std::size_t s_idCol = SpaceDim + 1
 Column index of the container-owned particleID.
 
static constexpr std::size_t s_rankCol = SpaceDim + 2
 Column index of the container-owned rankID.
 
static constexpr std::size_t s_ghostCol = SpaceDim + 3
 Column index of the container-owned ghost designation.
 
static constexpr std::size_t s_payloadBegin = SpaceDim + 4
 Index of the first payload column.
 
static constexpr std::size_t s_numColumns = s_payloadBegin + s_numPayloadColumns
 Total number of columns (SpaceDim position + weight + id + rank + ghost + payload).
 
static constexpr std::size_t s_align = 64
 Cache-line alignment for each column (also enables aligned SIMD).
 

Compile-time layout (value types)

using ColumnValueTuple = decltype(std::tuple_cat(std::declval< MandatoryValues >(), std::declval< PayloadValues >()))
 The value types of every column, in storage order.
 
template<std::size_t K>
using ColumnType = std::tuple_element_t< K, ColumnValueTuple >
 Value type of column K.
 
using H5PayloadColumns = typename detail::H5ColumnSubset< Traits, std::make_index_sequence< s_numPayloadColumns > >::Type
 The HDF5 payload column subset (indices into the payload columns).
 
template<typename M >
static constexpr std::size_t columnIndex (const M a_member) noexcept
 Derive the column index of a PAYLOAD member pointer (reorder-safe selector).
 

Mandatory-field accessors

static constexpr ParticleID s_invalidID = -1
 Sentinel for an unassigned/invalid global particle id.
 
RealVect position (const std::size_t a_index) const noexcept
 Position of particle i as a RealVect (by value, assembled from the scalar columns).
 
void setPosition (const std::size_t a_index, const RealVect &a_position) noexcept
 Set the position of particle i.
 
double & weight (const std::size_t a_index) noexcept
 Weight of particle i.
 
const double & weight (const std::size_t a_index) const noexcept
 Const weight of particle i.
 
ParticleIDparticleID (const std::size_t a_index) noexcept
 Global id of particle i (container-owned metadata).
 
const ParticleIDparticleID (const std::size_t a_index) const noexcept
 Const global id of particle i.
 
RankIDrankID (const std::size_t a_index) noexcept
 Owning rank of particle i (container-owned metadata).
 
const RankIDrankID (const std::size_t a_index) const noexcept
 Const owning rank of particle i.
 
GhostTypeghost (const std::size_t a_index) noexcept
 Ghost designation of particle i (container-owned metadata).
 
const GhostTypeghost (const std::size_t a_index) const noexcept
 Const ghost designation of particle i.
 
bool isGhost (const std::size_t a_index) const noexcept
 Whether particle i is a ghost particle (any non-Valid designation).
 

MPI linearization

static constexpr std::size_t bytesPerParticle () noexcept
 Byte count of one fully-linearized particle (all columns, for MPI).
 
void linearizeParticle (void *a_buffer, const std::size_t a_index) const noexcept
 Linearize particle i into a byte buffer (all columns, for MPI send).
 
void delinearizeAndAppend (const void *a_buffer)
 Append a particle delinearized from a byte buffer (all columns, for MPI receive).
 

HDF5 linearization

static constexpr std::size_t h5BytesPerParticle () noexcept
 Bytes for one HDF5-linearized particle (position + weight + h5 payload subset).
 
void h5LinearizeParticle (void *a_buffer, const std::size_t a_index) const noexcept
 Linearize the HDF5-checkpointed columns of particle i (no id/rank).
 
void h5DelinearizeAndAppend (const void *a_buffer)
 Append a particle whose HDF5-checkpointed columns come from a buffer.
 

Detailed Description

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
class ParticleSoA< P, Traits >

Arena-backed Struct-of-Arrays particle container for a single grid patch.

See the file-level documentation for the data model, the container-owned mandatory columns, and the recipe for defining a payload type.

Accessing data

Mutating the population

append(pos, weight, payload) adds a particle (grows geometrically); remove(i) deletes particle i by swap-and-pop (O(1), does NOT preserve order). The canonical remove loop does not advance i on a removal:

for (std::size_t i = 0; i < soa.size(); ) {
if (predicate(i)) soa.remove(i); else ++i;
}

append/remove/reserve invalidate raw pointers from column()/positionColumn(). Capacity never shrinks (clear() keeps it); the container is meant to be reused across steps.

Cell sorting

sortByCell(box,dx,probLo) counting-sorts the columns into Fortran cell order and builds a CSR offsets array, so cell c owns the contiguous range [cellStart(c), cellStart(c+1)). Append/remove invalidate the sort (isSorted()).

Communication & I/O

linearizeParticle()/delinearizeAndAppend() pack/unpack ALL columns (incl. id/rank) for MPI. h5LinearizeParticle()/h5DelinearizeAndAppend() handle the HDF5 subset (position + weight + the payload h5Columns; never id/rank). data()/byteSpan() expose the raw arena for a one-memcpy / zero-copy whole-container transfer.

Template Parameters
PUser payload struct (extra columns only); defaults to NoPayload.
TraitsColumn descriptor for the payload; defaults to ParticleTraits

.

Constructor & Destructor Documentation

◆ ParticleSoA()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
ParticleSoA< P, Traits >::ParticleSoA ( ParticleSoA< P, Traits > &&  a_other)
inlinenoexcept

Move constructor (steals the arena).

Parameters
[in,out]a_otherSource container, left empty after the move.

Member Function Documentation

◆ alignUp()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
static std::size_t ParticleSoA< P, Traits >::alignUp ( const std::size_t  a_x)
inlinestaticprotectednoexcept

Round a_x up to the next multiple of s_align.

Parameters
[in]a_xValue to round up.
Returns
a_x rounded up to a multiple of s_align.

◆ append() [1/3]

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::append ( const ParticleSoA< P, Traits > &  a_other)
inline

Append every particle of another container (bulk catenate; all columns, incl. id/rank).

Copies a_other's live particles onto the end of this container with a per-column memcpy (one reservation, then column-wise bulk copies). Unlike the single-particle append(), this PRESERVES the particleID/rankID metadata as well as position/weight/payload. Invalidates the cell sort. Appending a container to itself is supported.

Parameters
[in]a_otherSource container whose particles are appended.

◆ append() [2/3]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
void ParticleSoA< P, Traits >::append ( const RealVect &  a_position,
const double  a_weight 
)
inline

Append one particle with a default-constructed payload.

The metadata columns (id/rank) are set to s_invalidID/-1; assign them via particleID(i)/rankID(i) afterwards, or let the AMR layer / delinearize set them.

Parameters
[in]a_positionParticle position.
[in]a_weightParticle weight.

◆ append() [3/3]

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::append ( const RealVect &  a_position,
const double  a_weight,
const P &  a_payload 
)
inline

Append one particle with the given payload.

The metadata columns (id/rank) are set to s_invalidID/-1; assign them via particleID(i)/rankID(i) afterwards, or let the AMR layer / delinearize set them.

Parameters
[in]a_positionParticle position.
[in]a_weightParticle weight.
[in]a_payloadPayload columns for this particle.

◆ appendColumnsFrom()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
void ParticleSoA< P, Traits >::appendColumnsFrom ( const ParticleSoA< P, Traits > &  a_other,
const std::size_t  a_at,
std::index_sequence< I... >   
)
inlineprotectednoexcept

Bulk-append another container's live columns at slot a_at of this container's columns.

Per-column memcpy of a_other's m_size live elements into this container starting at element index a_at. This container must already have capacity >= a_at + a_other.size(). Disjoint source/destination (even when a_other == this, since the new slots lie past the existing ones).

Template Parameters
IColumn indices [0, s_numColumns).
Parameters
[in]a_otherSource container.
[in]a_atFirst destination element index (the size before appending).

◆ appendParticle()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::appendParticle ( const ParticleSoA< P, Traits > &  a_src,
const std::size_t  a_index 
)
inline

Append a single particle (all columns, incl. id/rank) copied from another container.

The single-particle analogue of append(const ParticleSoA&). Pair it with remove() on the source to move one particle between containers. Invalidates the cell sort. Appending from self is supported.

Parameters
[in]a_srcSource container to copy from.
[in]a_indexIndex of the particle in a_src to copy.

◆ byteSpan()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
std::size_t ParticleSoA< P, Traits >::byteSpan ( ) const
inlinenoexcept

Byte span of the live data (for a compact container, one contiguous memcpy/MPI_Send).

Returns
Byte span [data(), data()+byteSpan()).

◆ byteSpanImpl()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
std::size_t ParticleSoA< P, Traits >::byteSpanImpl ( std::index_sequence< I... >  ) const
inlineprotectednoexcept

Byte span of the live data: max over columns of (offset + used bytes).

Template Parameters
IColumn indices [0, s_numColumns).
Returns
Byte span of the live region of the arena.

◆ bytesPerParticle()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
static constexpr std::size_t ParticleSoA< P, Traits >::bytesPerParticle ( )
inlinestaticconstexprnoexcept

Byte count of one fully-linearized particle (all columns, for MPI).

Returns
Bytes per particle.

◆ capacity()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
std::size_t ParticleSoA< P, Traits >::capacity ( ) const
inlinenoexcept

Allocated capacity in particles.

Returns
The capacity in particles.

◆ catenate()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
void ParticleSoA< P, Traits >::catenate ( ParticleSoA< P, Traits > &  a_other)
inline

Move every particle of another container into this one, leaving a_other empty (catenate).

The move counterpart of append(const ParticleSoA&): appends all of a_other's particles (all columns, incl. id/rank) and then clears a_other. When this container is empty the two arenas are swapped instead, so the common "drain into an empty destination" case is O(1) with zero copy. Invalidates the cell sort. Catenating a container into itself is a no-op.

Parameters
[in,out]a_otherSource container, left empty afterwards.

◆ cellKey()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
std::size_t ParticleSoA< P, Traits >::cellKey ( const std::size_t  a_index,
const Box &  a_box,
const RealVect &  a_dx,
const RealVect &  a_probLo 
) const
inlineprotectednoexcept

Compute the Fortran (x-fastest) cell index of particle i within the sort domain.

Shared by sortByCell() and its debug-mode verifier so the two can never disagree about the mapping. Positions outside the box are clamped to the boundary cells.

Parameters
[in]a_indexParticle index.
[in]a_boxPatch box defining the cells.
[in]a_dxGrid spacing per direction.
[in]a_probLoPhysical coordinate of the lower domain corner.
Returns
Linearized cell index in [0, a_box.numPts()).

◆ cellRange()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
std::pair< std::size_t, std::size_t > ParticleSoA< P, Traits >::cellRange ( const std::size_t  a_cell) const
inlinenoexcept

Half-open particle index range [begin, end) owned by cell c (valid after sortByCell).

Convenience over cellStart(c)/cellStart(c+1); the cell's particles are the contiguous indices [first, second).

Parameters
[in]a_cellCell index.
Returns
The pair {cellStart(c), cellStart(c+1)}.

◆ cellStart()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
std::size_t ParticleSoA< P, Traits >::cellStart ( const std::size_t  a_cell) const
inlinenoexcept

CSR start offset of cell c (valid after sortByCell; requires c <= numCells()).

Parameters
[in]a_cellCell index.
Returns
Index of the first particle owned by cell a_cell.

◆ checkCellSort()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
bool ParticleSoA< P, Traits >::checkCellSort ( const Box &  a_box,
const RealVect &  a_dx,
const RealVect &  a_probLo 
) const
inlineprotectednoexcept

Verify that the CSR mapping really does describe the current particle positions.

The sort flag is only as good as the invalidation of every mutating path, so sortByCell() asserts on this whenever it takes its early-out: it recomputes each particle's cell key and checks that the particle sits in that cell's CSR range. O(N), and compiled out with the assertion in optimized builds. A failure here means some path moved particles without clearing m_sorted.

Parameters
[in]a_boxPatch box defining the cells.
[in]a_dxGrid spacing per direction.
[in]a_probLoPhysical coordinate of the lower domain corner.
Returns
True iff the CSR mapping is consistent with the current positions.

◆ column() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<auto Member>
const auto * ParticleSoA< P, Traits >::column ( ) const
inlinenoexcept

Const whole payload column selected by member pointer.

Template Parameters
MemberMember pointer selecting the payload column.
Returns
Const base pointer of the selected payload column.

◆ column() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<auto Member>
auto * ParticleSoA< P, Traits >::column ( )
inlinenoexcept

Whole payload column selected by member pointer (raw pointer, vectorizable).

Template Parameters
MemberMember pointer selecting the payload column.
Returns
Base pointer of the selected payload column.

◆ columnByIndex() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t K>
const ColumnType< K > * ParticleSoA< P, Traits >::columnByIndex ( ) const
inlinenoexcept

Const typed base pointer of column K (low-level).

Template Parameters
KColumn index.
Returns
Const base pointer of column K.

◆ columnByIndex() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t K>
ColumnType< K > * ParticleSoA< P, Traits >::columnByIndex ( )
inlinenoexcept

Typed base pointer of column K (low-level).

Template Parameters
KColumn index.
Returns
Base pointer of column K.

◆ columnIndex()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<typename M >
static constexpr std::size_t ParticleSoA< P, Traits >::columnIndex ( const M  a_member)
inlinestaticconstexprnoexcept

Derive the column index of a PAYLOAD member pointer (reorder-safe selector).

Template Parameters
MPointer-to-member type of the payload field.
Parameters
[in]a_memberMember pointer selecting the payload column.
Returns
The storage column index of the selected payload field.

◆ computeOffsets()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
std::size_t ParticleSoA< P, Traits >::computeOffsets ( const std::size_t  a_capacity,
std::array< std::size_t, s_numColumns > &  a_off,
std::index_sequence< I... >   
) const
inlineprotectednoexcept

Compute per-column byte offsets for a given capacity; returns the total bytes.

Template Parameters
IColumn indices [0, s_numColumns).
Parameters
[in]a_capacityCapacity (in particles) the columns are sized for.
[out]a_offFilled with the byte offset of each column.
Returns
Total byte size of the arena for this capacity.

◆ copyLiveColumnsTo()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
void ParticleSoA< P, Traits >::copyLiveColumnsTo ( ParticleSoA< P, Traits > &  a_dst,
std::index_sequence< I... >   
) const
inlineprotectednoexcept

Copy this container's m_size live elements of every column into another container.

Per-column copy (the two arenas may have different capacities, hence different layouts, so a single whole-arena memcpy is not valid). a_dst must already have capacity >= m_size.

Template Parameters
IColumn indices [0, s_numColumns).
Parameters
[in,out]a_dstDestination container (its column pointers are written).

◆ copyParticleColumns()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
void ParticleSoA< P, Traits >::copyParticleColumns ( const ParticleSoA< P, Traits > &  a_src,
const std::size_t  a_srcIdx,
const std::size_t  a_dstIdx,
std::index_sequence< I... >   
)
inlineprotectednoexcept

Copy one particle's every column from a_src[a_srcIdx] into this[a_dstIdx].

Per-column single-element copy. Both indices must be in range and this must have capacity for a_dstIdx.

Template Parameters
IColumn indices [0, s_numColumns).
Parameters
[in]a_srcSource container.
[in]a_srcIdxSource particle index.
[in]a_dstIdxDestination particle index in this container.

◆ data() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
const void * ParticleSoA< P, Traits >::data ( ) const
inlinenoexcept

Raw arena pointer (column-major); a compact container's whole data span.

Returns
Const pointer to the arena.

◆ data() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
void * ParticleSoA< P, Traits >::data ( )
inlinenoexcept

Mutable raw arena pointer (e.g. zero-copy MPI receive into the arena).

Returns
Pointer to the arena.

◆ deepCopy()

template<typename P , typename Traits >
ParticleSoA< P, Traits > ParticleSoA< P, Traits >::deepCopy ( ) const
inline

Explicit deep copy: a new container with a private arena duplicating every particle.

Copy construction and copy assignment are deleted (they would alias the single arena); call this when an independent copy of all the particles is genuinely wanted (rather than moving them). The cell-sort state (isSorted() + the CSR cell offsets) is preserved, so a cell-sorted container copies as cell-sorted.

Returns
An independent ParticleSoA owning a copy of every particle.

◆ deepCopyTo()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::deepCopyTo ( ParticleSoA< P, Traits > &  a_dst) const
inline

Deep copy into an existing destination, reusing its arena when possible.

Like deepCopy() but writes into a_dst instead of returning a new container. a_dst's existing allocation is reused when it is already large enough (grown only if it is too small), which avoids a malloc when copying repeatedly into the same destination. a_dst is overwritten with an independent copy of every particle, and its cell-sort state is set to match this container. Copying onto self is a no-op.

Parameters
[in,out]a_dstDestination container, overwritten with a copy of every particle.

◆ delinearizeAndAppend()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::delinearizeAndAppend ( const void *  a_buffer)
inline

Append a particle delinearized from a byte buffer (all columns, for MPI receive).

Parameters
[in]a_bufferBuffer with at least bytesPerParticle() bytes.

◆ delinearizeImpl()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
void ParticleSoA< P, Traits >::delinearizeImpl ( const unsigned char *  a_buf,
std::index_sequence< I... >   
)
inlineprotectednoexcept

Pull every column of one particle off a byte buffer into slot m_size (MPI).

Template Parameters
IColumn indices [0, s_numColumns).
Parameters
[in]a_bufBuffer holding one linearized particle.

◆ empty()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
bool ParticleSoA< P, Traits >::empty ( ) const
inlinenoexcept

Whether the container holds no particles.

Returns
True iff size() is zero.

◆ extractCell()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
void ParticleSoA< P, Traits >::extractCell ( const std::size_t  a_cell,
ParticleSoA< P, Traits > &  a_out 
) const
inline

Extract cell c's particles (the CSR range [cellStart(c), cellStart(c+1))) into a_out.

a_out is cleared first, then this cell's particles are appended (all columns, including id/rank). Requires the container to be cell-sorted. This is the building block of the per-cell extract->process->rebuild idiom that replaces the AoS BinFab<List<P>> per-cell pattern: extract a cell into a reusable scratch container, mutate it (append/remove), accumulate it into an output container via append(const ParticleSoA&), and finally swap() the output into the leaf. See ItoSolver::makeSuperparticles for the canonical use.

Parameters
[in]a_cellCell index.
[out]a_outDestination scratch container (cleared on entry; reuse it across cells).

◆ gather()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
P ParticleSoA< P, Traits >::gather ( const std::size_t  a_index) const
inline

Gather particle i's payload back into the AoS payload view.

Parameters
[in]a_indexParticle index.
Returns
The payload struct (mandatory fields are read via the dedicated accessors).

◆ gatherPayload()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... J>
P ParticleSoA< P, Traits >::gatherPayload ( const std::size_t  a_index,
std::index_sequence< J... >   
) const
inlineprotected

Read the payload columns of slot a_index into a payload struct.

Template Parameters
JPayload-column indices [0, s_numPayloadColumns).
Parameters
[in]a_indexParticle index.
Returns
The gathered payload struct.

◆ get() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<auto Member>
const auto & ParticleSoA< P, Traits >::get ( const std::size_t  a_index) const
inlinenoexcept

Const overload of get<&P::field>(i).

Template Parameters
MemberMember pointer selecting the payload column.
Parameters
[in]a_indexParticle index.
Returns
Const reference to the selected payload field of particle a_index.

◆ get() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<auto Member>
auto & ParticleSoA< P, Traits >::get ( const std::size_t  a_index)
inlinenoexcept

One particle's payload field selected by member pointer.

Template Parameters
MemberMember pointer selecting the payload column.
Parameters
[in]a_indexParticle index.
Returns
Reference to the selected payload field of particle a_index.

◆ ghost() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
const GhostType & ParticleSoA< P, Traits >::ghost ( const std::size_t  a_index) const
inlinenoexcept

Const ghost designation of particle i.

Parameters
[in]a_indexParticle index.
Returns
Const reference to the ghost designation.

◆ ghost() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
GhostType & ParticleSoA< P, Traits >::ghost ( const std::size_t  a_index)
inlinenoexcept

Ghost designation of particle i (container-owned metadata).

Parameters
[in]a_indexParticle index.
Returns
Reference to the ghost designation.

◆ growTo()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
void ParticleSoA< P, Traits >::growTo ( const std::size_t  a_needed)
inlineprotected

Grow the arena to hold at least a_needed particles, geometrically.

The growth policy for every append path, and deliberately NOT folded into reserve(): reserve() sets the capacity EXACTLY, and exactly one caller needs that for correctness. deepCopy() sizes the destination to the SOURCE's capacity and then flat-memcpy()s byteSpan() across in one go, which is only valid while both arenas compute the same per-column offsets – and those offsets are derived from the capacity. Rounding the capacity up there would silently copy the columns to the wrong places. The remaining exact-sizing callers do not depend on the layout: resize() and deepCopyTo() simply want the capacity they asked for rather than a doubled one, deepCopyTo() copying column by column and so needing only capacity >= m_size.

An append that called reserve(m_size + n) directly would leave capacity == size on return, so the very next append would reallocate and recopy the whole arena – turning the extract->mutate->accumulate idiom extractCell() documents as canonical into O(N^2) copying, since the accumulating container is grown one cell at a time.

Parameters
[in]a_neededNumber of particles the arena must be able to hold.

◆ h5BytesPerParticle()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
static constexpr std::size_t ParticleSoA< P, Traits >::h5BytesPerParticle ( )
inlinestaticconstexprnoexcept

Bytes for one HDF5-linearized particle (position + weight + h5 payload subset).

Returns
Bytes per HDF5-checkpointed particle.

◆ h5DelinearizeAndAppend()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::h5DelinearizeAndAppend ( const void *  a_buffer)
inline

Append a particle whose HDF5-checkpointed columns come from a buffer.

id/rank are set invalid and non-checkpointed payload columns default-constructed.

Parameters
[in]a_bufferBuffer with at least h5BytesPerParticle() bytes.

◆ h5DelinearizePayload()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... J>
void ParticleSoA< P, Traits >::h5DelinearizePayload ( const unsigned char *&  a_buf,
std::index_sequence< J... >   
)
inlineprotectednoexcept

Pull the HDF5 payload subset off a byte buffer into slot m_size.

Template Parameters
JPayload-column indices in the HDF5 subset.
Parameters
[in,out]a_bufBuffer pointer, advanced as columns are read.

◆ h5LinearizeParticle()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::h5LinearizeParticle ( void *  a_buffer,
const std::size_t  a_index 
) const
inlinenoexcept

Linearize the HDF5-checkpointed columns of particle i (no id/rank).

Parameters
[in,out]a_bufferBuffer with at least h5BytesPerParticle() bytes.
[in]a_indexParticle index.

◆ h5LinearizePayload()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... J>
void ParticleSoA< P, Traits >::h5LinearizePayload ( unsigned char *&  a_buf,
const std::size_t  a_index,
std::index_sequence< J... >   
) const
inlineprotectednoexcept

Push the HDF5 payload subset of particle a_index onto a byte buffer.

Template Parameters
JPayload-column indices in the HDF5 subset.
Parameters
[in,out]a_bufBuffer pointer, advanced as columns are written.
[in]a_indexParticle index.

◆ h5PayloadSize()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... J>
static constexpr std::size_t ParticleSoA< P, Traits >::h5PayloadSize ( std::index_sequence< J... >  )
inlinestaticconstexprprotectednoexcept

Compile-time byte size of the HDF5 payload subset.

Template Parameters
JPayload-column indices in the HDF5 subset.
Returns
Total bytes of the HDF5 payload subset.

◆ isGhost()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
bool ParticleSoA< P, Traits >::isGhost ( const std::size_t  a_index) const
inlinenoexcept

Whether particle i is a ghost particle (any non-Valid designation).

Parameters
[in]a_indexParticle index.
Returns
True if the particle is a ghost, false if it is a valid/owned particle.

◆ isSorted()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
bool ParticleSoA< P, Traits >::isSorted ( ) const
inlinenoexcept

Whether the container is currently cell-sorted (false after append/remove).

Returns
True iff the CSR cell offsets are valid.

◆ isSortedAgainst()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
bool ParticleSoA< P, Traits >::isSortedAgainst ( const Box &  a_box,
const RealVect &  a_dx,
const RealVect &  a_probLo 
) const
inlinenoexcept

Whether the container is cell-sorted against exactly this cell domain.

isSorted() only says that some CSR mapping is valid; this says it is the mapping the caller is about to index with. sortByCell() early-outs on precisely this condition.

Parameters
[in]a_boxPatch box defining the cells.
[in]a_dxGrid spacing per direction.
[in]a_probLoPhysical coordinate of the lower domain corner.
Returns
True iff the container is sorted against (a_box, a_dx, a_probLo).

◆ linearizeImpl()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
void ParticleSoA< P, Traits >::linearizeImpl ( unsigned char *  a_buf,
const std::size_t  a_index,
std::index_sequence< I... >   
) const
inlineprotectednoexcept

Push every column of particle a_index onto a byte buffer (MPI).

Template Parameters
IColumn indices [0, s_numColumns).
Parameters
[in,out]a_bufBuffer pointer, advanced as columns are written.
[in]a_indexParticle index.

◆ linearizeParticle()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::linearizeParticle ( void *  a_buffer,
const std::size_t  a_index 
) const
inlinenoexcept

Linearize particle i into a byte buffer (all columns, for MPI send).

Parameters
[in,out]a_bufferBuffer with at least bytesPerParticle() bytes.
[in]a_indexParticle index.

◆ moveColumns()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
void ParticleSoA< P, Traits >::moveColumns ( void *  a_newBuf,
const std::array< std::size_t, s_numColumns > &  a_off,
std::index_sequence< I... >   
)
inlineprotectednoexcept

Contiguously memcpy every column's live region into a freshly-allocated buffer.

Template Parameters
IColumn indices [0, s_numColumns).
Parameters
[out]a_newBufDestination arena buffer.
[in]a_offPer-column byte offsets into a_newBuf.

◆ numCells()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
std::size_t ParticleSoA< P, Traits >::numCells ( ) const
inlinenoexcept

Number of cells in the CSR sort (0 if not sorted).

Returns
The number of cells.

◆ operator=() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
ParticleSoA & ParticleSoA< P, Traits >::operator= ( const ParticleSoA< P, Traits > &  )
delete

Copy assignment is deleted (move-only).

Returns
Reference to this.

◆ operator=() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
ParticleSoA & ParticleSoA< P, Traits >::operator= ( ParticleSoA< P, Traits > &&  a_other)
inlinenoexcept

Move assignment (steals the arena).

Parameters
[in,out]a_otherSource container, left empty after the move.
Returns
Reference to this.

◆ particleID() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
const ParticleID & ParticleSoA< P, Traits >::particleID ( const std::size_t  a_index) const
inlinenoexcept

Const global id of particle i.

Parameters
[in]a_indexParticle index.
Returns
Const reference to the particle id.

◆ particleID() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
ParticleID & ParticleSoA< P, Traits >::particleID ( const std::size_t  a_index)
inlinenoexcept

Global id of particle i (container-owned metadata).

Parameters
[in]a_indexParticle index.
Returns
Reference to the particle id.

◆ particlesInCell()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
std::size_t ParticleSoA< P, Traits >::particlesInCell ( const std::size_t  a_cell) const
inlinenoexcept

Number of particles in cell c (valid after sortByCell).

Parameters
[in]a_cellCell index.
Returns
Particle count in cell a_cell.

◆ permute()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::permute ( const std::vector< std::size_t > &  a_dest)
inlineprotected

Reorder every column in place by a_dest (a_dest[i] = new slot of old particle i).

Parameters
[in]a_destDestination slot for each current particle.

◆ position()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
RealVect ParticleSoA< P, Traits >::position ( const std::size_t  a_index) const
inlinenoexcept

Position of particle i as a RealVect (by value, assembled from the scalar columns).

Parameters
[in]a_indexParticle index.
Returns
The particle position for cell lookup / Chombo interop.

◆ positionColumn() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
const double * ParticleSoA< P, Traits >::positionColumn ( const int  a_dir) const
inlinenoexcept

Const raw position component column dir.

Parameters
[in]a_dirSpatial direction in [0, SpaceDim).
Returns
Const base pointer of the position component column for direction a_dir.

◆ positionColumn() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
double * ParticleSoA< P, Traits >::positionColumn ( const int  a_dir)
inlinenoexcept

Raw position component column dir (double*, for SIMD kernels).

Handing out a writable position column invalidates the cell sort: the caller may move particles across cell boundaries, and the container cannot observe that. The sort flag is therefore cleared here rather than on the (unobservable) write, which is what lets sortByCell() trust the flag and skip a re-sort. Use the const overload for read-only kernels to keep the sort.

Parameters
[in]a_dirSpatial direction in [0, SpaceDim).
Returns
Base pointer of the position component column for direction a_dir.

◆ pullColumn()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t K>
void ParticleSoA< P, Traits >::pullColumn ( const unsigned char *&  a_buf)
inlineprotectednoexcept

Pull one column's value off a byte buffer into slot m_size and advance the pointer.

Template Parameters
KColumn index.
Parameters
[in,out]a_bufBuffer pointer, advanced by the column's byte size.

◆ rankID() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
const RankID & ParticleSoA< P, Traits >::rankID ( const std::size_t  a_index) const
inlinenoexcept

Const owning rank of particle i.

Parameters
[in]a_indexParticle index.
Returns
Const reference to the owning rank.

◆ rankID() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
RankID & ParticleSoA< P, Traits >::rankID ( const std::size_t  a_index)
inlinenoexcept

Owning rank of particle i (container-owned metadata).

Parameters
[in]a_indexParticle index.
Returns
Reference to the owning rank.

◆ reallocate()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::reallocate ( const std::size_t  a_capacity)
inlineprotected

Allocate a new arena and reallocate/move the columns into it (growth path).

Parameters
[in]a_capacityNew capacity in particles.

◆ remove()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
void ParticleSoA< P, Traits >::remove ( const std::size_t  a_index)
inlinenoexcept

Remove particle i using swap-and-pop (O(1), does NOT preserve order).

Parameters
[in]a_indexParticle index.

◆ removeImpl()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
void ParticleSoA< P, Traits >::removeImpl ( const std::size_t  a_index,
std::index_sequence< I... >   
)
inlineprotectednoexcept

Swap-and-pop slot a_index in every column.

Template Parameters
IColumn indices [0, s_numColumns).
Parameters
[in]a_indexParticle index to remove.

◆ reserve()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::reserve ( const std::size_t  a_capacity)
inline

Ensure capacity for at least a_capacity particles (reallocates + moves on growth).

Parameters
[in]a_capacityRequested capacity.

◆ resize()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::resize ( const std::size_t  a_count)
inline

Set the particle count (grows capacity if needed; new slots are uninitialized).

Parameters
[in]a_countNew particle count.

◆ scatterColumn()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t K>
void ParticleSoA< P, Traits >::scatterColumn ( void *  a_newBuf,
const std::size_t  a_off,
const std::vector< std::size_t > &  a_dest 
)
inlineprotectednoexcept

Per-column scatter for permute(): newcol[dest[i]] = oldcol[i].

Template Parameters
KColumn index to scatter.
Parameters
[out]a_newBufDestination arena buffer.
[in]a_offByte offset of column K in a_newBuf.
[in]a_destDestination slot for each current particle.

◆ scatterColumns()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
void ParticleSoA< P, Traits >::scatterColumns ( void *  a_newBuf,
const std::array< std::size_t, s_numColumns > &  a_off,
const std::vector< std::size_t > &  a_dest,
std::index_sequence< I... >   
)
inlineprotectednoexcept

Scatter every column for permute() into a freshly-allocated buffer.

Template Parameters
IColumn indices [0, s_numColumns).
Parameters
[out]a_newBufDestination arena buffer.
[in]a_offPer-column byte offsets into a_newBuf.
[in]a_destDestination slot for each current particle.

◆ setColPtrs()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... I>
void ParticleSoA< P, Traits >::setColPtrs ( const std::array< std::size_t, s_numColumns > &  a_off,
std::index_sequence< I... >   
)
inlineprotectednoexcept

Cache the column base pointers from a fresh buffer + offsets.

Template Parameters
IColumn indices [0, s_numColumns).
Parameters
[in]a_offPer-column byte offsets into m_buffer.

◆ setPosition()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
void ParticleSoA< P, Traits >::setPosition ( const std::size_t  a_index,
const RealVect &  a_position 
)
inlinenoexcept

Set the position of particle i.

Invalidates the cell sort – the new position may lie in a different cell.

Parameters
[in]a_indexParticle index.
[in]a_positionNew position.

◆ shrinkToFit()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::shrinkToFit ( )
inline

Reclaim unused capacity by reallocating the arena down to the current size.

A no-op when already compact (capacity == size). The arena does not shrink on its own (clear()/remove() keep the capacity for reuse); call this to return memory after a transient spike. Invalidates raw column pointers. The particle order and cell-sort state are preserved.

◆ size()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
std::size_t ParticleSoA< P, Traits >::size ( ) const
inlinenoexcept

Number of particles currently stored.

Returns
The live particle count.

◆ sortByCell()

template<typename P , typename Traits >
void ParticleSoA< P, Traits >::sortByCell ( const Box &  a_box,
const RealVect &  a_dx,
const RealVect &  a_probLo 
)
inline

Counting-sort the columns into Fortran cell order and build CSR cell offsets.

After this, cell c owns the contiguous particle range [cellStart(c), cellStart(c+1)). Particles must lie within a_box; out-of-range positions are clamped to the boundary cells.

This is idempotent: a container already sorted against the same (box, dx, probLo) returns immediately, because the sort it would produce is the one it already has. Callers that establish the sort defensively therefore cost nothing when an earlier caller already did it, which is the common case – the ItoKMC reaction path sorts the same leaves at three separate call sites. Any operation that can move a particle between cells (append, remove, resize, setPosition, or handing out a writable positionColumn()) clears the flag, so the early-out only fires when the CSR mapping is still the one this container computed. In debug builds the mapping is re-verified on every early-out; see checkCellSort().

Parameters
[in]a_boxPatch box defining the cells.
[in]a_dxGrid spacing per direction.
[in]a_probLoPhysical coordinate of the lower domain corner.

◆ steal()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
void ParticleSoA< P, Traits >::steal ( ParticleSoA< P, Traits > &  a_o)
inlineprotectednoexcept

Steal another container's arena (move helper).

Parameters
[in,out]a_oSource container, left empty afterwards.

◆ swap()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
void ParticleSoA< P, Traits >::swap ( ParticleSoA< P, Traits > &  a_other)
inlinenoexcept

Swap the entire state (arena, size, capacity, sort) with another container in O(1).

Exchanges the cached column pointers and metadata only – no particle data is moved. Useful for the build-then-swap idiom and for std::swap.

Parameters
[in,out]a_otherContainer to swap with.

◆ weight() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
const double & ParticleSoA< P, Traits >::weight ( const std::size_t  a_index) const
inlinenoexcept

Const weight of particle i.

Parameters
[in]a_indexParticle index.
Returns
Const reference to the weight.

◆ weight() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
double & ParticleSoA< P, Traits >::weight ( const std::size_t  a_index)
inlinenoexcept

Weight of particle i.

Parameters
[in]a_indexParticle index.
Returns
Reference to the weight.

◆ weightColumn() [1/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
const double * ParticleSoA< P, Traits >::weightColumn ( ) const
inlinenoexcept

Const raw weight column.

Returns
Const base pointer of the weight column.

◆ weightColumn() [2/2]

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
double * ParticleSoA< P, Traits >::weightColumn ( )
inlinenoexcept

Raw weight column (double*).

Returns
Base pointer of the weight column.

◆ writePayload()

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
template<std::size_t... J>
void ParticleSoA< P, Traits >::writePayload ( const P &  a_p,
std::index_sequence< J... >   
)
inlineprotectednoexcept

Write the payload columns of slot m_size from a payload struct.

Template Parameters
JPayload-column indices [0, s_numPayloadColumns).
Parameters
[in]a_pPayload struct to read from.

Member Data Documentation

◆ m_bytes

template<typename P = NoPayload, typename Traits = ParticleTraits<P>>
std::size_t ParticleSoA< P, Traits >::m_bytes = 0
protected

Byte size of the arena at m_buffer (zero when m_buffer is null).

Kept so a release can decrement ParticleMemory by exactly what the matching allocation added, without recomputing the column offsets. It therefore describes the arena rather than the container, and must travel with m_buffer through every ownership transfer – swap() and steal() both move it. A transfer that moves the arena but leaves this behind attributes the arena to a container that no longer holds it, and the accounting drifts from the first such transfer on.


The documentation for this class was generated from the following files: