13#ifndef CD_PARTICLESOAIMPLEM_H
14#define CD_PARTICLESOAIMPLEM_H
25#include <CD_NamespaceHeader.H>
27template <
typename P,
typename Traits>
31 std::array<std::size_t, s_numColumns> off{};
32 const std::size_t total = this->computeOffsets(a_capacity, off, std::make_index_sequence<s_numColumns>{});
34 const std::size_t bytes = alignUp(total);
36 void*
const newBuf = std::aligned_alloc(s_align, bytes);
38 if (newBuf ==
nullptr) {
39 MayDay::Abort(
"ParticleSoA::reallocate - std::aligned_alloc returned null (out of memory)");
43 this->moveColumns(newBuf, off, std::make_index_sequence<s_numColumns>{});
52 m_capacity = a_capacity;
55 this->setColPtrs(off, std::make_index_sequence<s_numColumns>{});
58template <
typename P,
typename Traits>
62 std::array<std::size_t, s_numColumns> off{};
63 const std::size_t total = this->computeOffsets(m_capacity, off, std::make_index_sequence<s_numColumns>{});
65 const std::size_t bytes = alignUp(total);
67 void*
const newBuf = std::aligned_alloc(s_align, bytes);
69 if (newBuf ==
nullptr) {
70 MayDay::Abort(
"ParticleSoA::permute - std::aligned_alloc returned null (out of memory)");
73 this->scatterColumns(newBuf, off, a_dest, std::make_index_sequence<s_numColumns>{});
83 this->setColPtrs(off, std::make_index_sequence<s_numColumns>{});
86template <
typename P,
typename Traits>
90 if (a_capacity <= m_capacity) {
94 this->reallocate(a_capacity);
97template <
typename P,
typename Traits>
101 this->reserve(a_count);
107template <
typename P,
typename Traits>
115 std::memcpy(dst.
m_buffer, m_buffer, this->byteSpan());
128template <
typename P,
typename Traits>
132 if (
this == &a_dst) {
140 this->copyLiveColumnsTo(a_dst, std::make_index_sequence<s_numColumns>{});
151template <
typename P,
typename Traits>
155 const std::size_t n = a_other.
m_size;
161 const std::size_t oldSize = m_size;
163 this->growTo(oldSize + n);
164 this->appendColumnsFrom(a_other, oldSize, std::make_index_sequence<s_numColumns>{});
166 m_size = oldSize + n;
170template <
typename P,
typename Traits>
174 CH_assert(a_index < a_src.
m_size);
176 const std::size_t at = m_size;
178 this->growTo(m_size + 1);
179 this->copyParticleColumns(a_src, a_index, at, std::make_index_sequence<s_numColumns>{});
185template <
typename P,
typename Traits>
189 if (m_capacity <= m_size) {
202 m_colPtrs.fill(
nullptr);
206 this->reallocate(m_size);
209template <
typename P,
typename Traits>
215 for (
int dir = 0; dir < SpaceDim; dir++) {
216 this->positionColumn(dir)[m_size] = a_position[dir];
219 this->
template columnByIndex<s_weightCol>()[m_size] = a_weight;
220 this->
template columnByIndex<s_idCol>()[m_size] = s_invalidID;
221 this->
template columnByIndex<s_rankCol>()[m_size] =
static_cast<RankID>(-1);
223 this->writePayload(a_payload, std::make_index_sequence<s_numPayloadColumns>{});
230template <
typename P,
typename Traits>
234 CH_assert(a_index < m_size);
236 auto* p =
static_cast<unsigned char*
>(a_buffer);
238 this->linearizeImpl(p, a_index, std::make_index_sequence<s_numColumns>{});
241template <
typename P,
typename Traits>
247 const auto* p =
static_cast<const unsigned char*
>(a_buffer);
249 this->delinearizeImpl(p, std::make_index_sequence<s_numColumns>{});
256template <
typename P,
typename Traits>
260 CH_assert(a_index < m_size);
262 auto* p =
static_cast<unsigned char*
>(a_buffer);
264 for (
int dir = 0; dir < SpaceDim; dir++) {
265 detail::pushBytes(p, this->positionColumn(dir)[a_index]);
268 detail::pushBytes(p, this->
template columnByIndex<s_weightCol>()[a_index]);
273template <
typename P,
typename Traits>
279 const auto* p =
static_cast<const unsigned char*
>(a_buffer);
281 for (
int dir = 0; dir < SpaceDim; dir++) {
282 detail::pullBytes(p, this->positionColumn(dir)[m_size]);
285 detail::pullBytes(p, this->
template columnByIndex<s_weightCol>()[m_size]);
287 this->
template columnByIndex<s_idCol>()[m_size] = s_invalidID;
288 this->
template columnByIndex<s_rankCol>()[m_size] =
static_cast<RankID>(-1);
294 this->writePayload(def, std::make_index_sequence<s_numPayloadColumns>{});
301template <
typename P,
typename Traits>
311 if (this->isSortedAgainst(a_box, a_dx, a_probLo)) {
312 CH_assert(this->checkCellSort(a_box, a_dx, a_probLo));
317 const std::size_t nCells = a_box.numPts();
321 m_sortProbLo = a_probLo;
323 m_cellStart.assign(nCells + 1, 0);
330 std::vector<std::size_t> key(m_size);
331 for (std::size_t i = 0; i < m_size; i++) {
332 const std::size_t lin = this->cellKey(i, a_box, a_dx, a_probLo);
335 m_cellStart[lin + 1]++;
339 for (std::size_t c = 1; c <= nCells; c++) {
340 m_cellStart[c] += m_cellStart[c - 1];
344 std::vector<std::size_t> cursor(m_cellStart.begin(), m_cellStart.begin() + nCells);
345 std::vector<std::size_t> dest(m_size);
347 for (std::size_t i = 0; i < m_size; i++) {
348 dest[i] = cursor[key[i]]++;
356#include <CD_NamespaceFooter.H>
Declaration of ParticleSoA, an arena-backed Struct-of-Arrays particle container.
std::int32_t RankID
Owning-rank identifier type (container-owned metadata column; fixed-width for I/O).
Definition CD_ParticleSoA.H:166
@ Valid
Owned, valid particle of this patch (not a ghost).
Arena-backed Struct-of-Arrays particle container for a single grid patch.
Definition CD_ParticleSoA.H:655
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).
Definition CD_ParticleSoAImplem.H:60
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.
Definition CD_ParticleSoAImplem.H:303
void append(const RealVect &a_position, const double a_weight)
Append one particle with a default-constructed payload.
Definition CD_ParticleSoA.H:955
void shrinkToFit()
Reclaim unused capacity by reallocating the arena down to the current size.
Definition CD_ParticleSoAImplem.H:187
bool m_sorted
Whether m_cellStart is valid.
Definition CD_ParticleSoA.H:1602
void delinearizeAndAppend(const void *a_buffer)
Append a particle delinearized from a byte buffer (all columns, for MPI receive).
Definition CD_ParticleSoAImplem.H:243
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).
Definition CD_ParticleSoAImplem.H:232
void deepCopyTo(ParticleSoA &a_dst) const
Deep copy into an existing destination, reusing its arena when possible.
Definition CD_ParticleSoAImplem.H:130
std::size_t m_size
Live particle count.
Definition CD_ParticleSoA.H:1597
typename detail::H5ColumnSubset< Traits, std::make_index_sequence< s_numPayloadColumns > >::Type H5PayloadColumns
The HDF5 payload column subset (indices into the payload columns).
Definition CD_ParticleSoA.H:759
ParticleSoA deepCopy() const
Explicit deep copy: a new container with a private arena duplicating every particle.
Definition CD_ParticleSoAImplem.H:109
void h5DelinearizeAndAppend(const void *a_buffer)
Append a particle whose HDF5-checkpointed columns come from a buffer.
Definition CD_ParticleSoAImplem.H:275
void h5LinearizeParticle(void *a_buffer, const std::size_t a_index) const noexcept
Linearize the HDF5-checkpointed columns of particle i (no id/rank).
Definition CD_ParticleSoAImplem.H:258
void * m_buffer
The single arena allocation.
Definition CD_ParticleSoA.H:1577
void resize(const std::size_t a_count)
Set the particle count (grows capacity if needed; new slots are uninitialized).
Definition CD_ParticleSoAImplem.H:99
std::vector< std::size_t > m_cellStart
CSR cell offsets (size numCells+1 when sorted).
Definition CD_ParticleSoA.H:1612
RealVect m_sortDx
Grid spacing the CSR mapping was built against (meaningful only when m_sorted).
Definition CD_ParticleSoA.H:1622
RealVect m_sortProbLo
Lower domain corner the CSR mapping was built against (meaningful only when m_sorted).
Definition CD_ParticleSoA.H:1627
Box m_sortBox
Patch box the CSR mapping in m_cellStart was built against (meaningful only when m_sorted).
Definition CD_ParticleSoA.H:1617
void clear() noexcept
Drop all particles (keeps the arena; invalidates the cell sort).
Definition CD_ParticleSoA.H:911
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.
Definition CD_ParticleSoAImplem.H:172
void reallocate(const std::size_t a_capacity)
Allocate a new arena and reallocate/move the columns into it (growth path).
Definition CD_ParticleSoAImplem.H:29
void reserve(const std::size_t a_capacity)
Ensure capacity for at least a_capacity particles (reallocates + moves on growth).
Definition CD_ParticleSoAImplem.H:88
void removeBytes(const Kind a_kind, const std::size_t a_bytes) noexcept
Record a release.
Definition CD_ParticleMemory.H:140
void addBytes(const Kind a_kind, const std::size_t a_bytes) noexcept
Record an allocation.
Definition CD_ParticleMemory.H:124
@ Container
ParticleSoA arenas: capacity a rank is holding.