chombo-discharge
Loading...
Searching...
No Matches
CD_ParticleSoA.H
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021-2026 SINTEF Energy Research
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
116#ifndef CD_PARTICLESOA_H
117#define CD_PARTICLESOA_H
118
119// Std includes
120#include <algorithm>
121#include <array>
122#include <cstddef>
123#include <cstdint>
124#include <cstdlib>
125#include <cstring>
126#include <limits>
127#include <tuple>
128#include <type_traits>
129#include <utility>
130#include <vector>
131
132// Chombo includes (kept minimal -- only the grid-interop geometry types; storage uses
133// fundamental C++ types so the container is not tied to Chombo's Real precision).
134#include <SPACE.H>
135#include <RealVect.H>
136#include <IntVect.H>
137#include <Box.H>
138
139// Our includes
140#include <CD_ParticleMemory.H>
141#include <CD_NamespaceHeader.H>
142
149#ifndef CD_PARTICLE_REAL
150#define CD_PARTICLE_REAL double
151#endif
152
157
161using ParticleID = std::int64_t;
162
166using RankID = std::int32_t;
167
176enum class GhostType : std::uint8_t
177{
178 Valid = 0,
179 SameLevel = 1,
180 Coarse = 2,
181 Fine = 3
182};
183
191template <typename P>
193
212namespace H5Part {
213
218template <typename M>
219struct Scalar
220{
224 static constexpr bool s_isVector = false;
225
229 const char* name;
230
235};
236
241template <typename M>
242Scalar(const char*, M) -> Scalar<M>;
243
248template <typename... Ms>
249struct Vector
250{
254 static constexpr bool s_isVector = true;
255
259 const char* name;
260
264 std::tuple<Ms...> members;
265
271 constexpr Vector(const char* a_name, Ms... a_members) noexcept : name(a_name), members(a_members...)
272 {}
273};
274
280template <typename... Ms>
281Vector(const char*, Ms...) -> Vector<Ms...>;
282
283} // namespace H5Part
284
289{
290};
291
295template <>
297{
301 static constexpr auto columns = std::make_tuple();
302};
303
304namespace detail {
305
310template <typename M>
312
318template <typename C, typename T>
320{
324 using ClassType = C;
328 using ValueType = T;
329};
330
337template <typename A, typename B>
338constexpr bool
339eqMember(A, B) noexcept
340{
341 return false;
342}
343
351template <typename A>
352constexpr bool
353eqMember(A a_lhs, A a_rhs) noexcept
354{
355 return a_lhs == a_rhs;
356}
357
364template <typename Tup, typename M>
365constexpr std::size_t
366indexOfImpl(const Tup&, M, std::index_sequence<>) noexcept
367{
368 return std::tuple_size<Tup>::value;
369}
370
381template <typename Tup, typename M, std::size_t I, std::size_t... Rest>
382constexpr std::size_t
383indexOfImpl(const Tup& a_t, M a_target, std::index_sequence<I, Rest...>) noexcept
384{
385 return eqMember(std::get<I>(a_t), a_target) ? I : indexOfImpl(a_t, a_target, std::index_sequence<Rest...>{});
386}
387
396template <typename Tup, typename M>
397constexpr std::size_t
398indexOf(const Tup& a_t, M a_target) noexcept
399{
400 return indexOfImpl(a_t, a_target, std::make_index_sequence<std::tuple_size<Tup>::value>{});
401}
402
408template <typename T, std::size_t N>
410{
414 template <std::size_t>
415 using Always = T;
416
422 template <std::size_t... I>
423 static std::tuple<Always<I>...> make(std::index_sequence<I...>);
424
428 using Type = decltype(make(std::make_index_sequence<N>{}));
429};
430
435template <typename Tuple>
437
442template <typename... Ms>
443struct ValueTuple<std::tuple<Ms...>>
444{
448 using Type = std::tuple<typename MemberPointerTraits<Ms>::ValueType...>;
449};
450
455constexpr std::size_t
456sumSizes() noexcept
457{
458 return 0;
459}
460
468template <typename... Rest>
469constexpr std::size_t
470sumSizes(std::size_t a_first, Rest... a_rest) noexcept
471{
472 return a_first + sumSizes(a_rest...);
473}
474
479template <typename Tuple>
481
486template <typename... Ts>
487struct SumSizeof<std::tuple<Ts...>>
488{
492 static constexpr std::size_t s_value = sumSizes(sizeof(Ts)...);
493};
494
499template <typename Tuple>
501
506template <typename... Ts>
507struct AllTriviallyCopyable<std::tuple<Ts...>>
508{
512 static constexpr bool s_value = (std::is_trivially_copyable<Ts>::value && ...);
513};
514
519template <typename...>
521{
525 using Type = void;
526};
527
531template <typename... Ts>
532using Void = typename MakeVoid<Ts...>::Type;
533
542template <typename Traits, std::size_t... I>
543constexpr std::index_sequence<indexOf(Traits::columns, std::get<I>(Traits::h5Columns))...>
544deriveH5Seq([[maybe_unused]] std::index_sequence<I...> a_seq) noexcept
545{
546 return {};
547}
548
555template <typename Traits, typename Fallback, typename = void>
557{
561 using Type = Fallback;
562};
563
569template <typename Traits, typename Fallback>
570struct H5ColumnSubset<Traits, Fallback, Void<decltype(Traits::h5Columns)>>
571{
575 using H5Tuple = std::remove_cv_t<std::remove_reference_t<decltype(Traits::h5Columns)>>;
579 using Type = decltype(deriveH5Seq<Traits>(std::make_index_sequence<std::tuple_size<H5Tuple>::value>{}));
580};
581
588template <typename T>
589inline void
590pushBytes(unsigned char*& a_buf, const T& a_value) noexcept
591{
592 static_assert(std::is_trivially_copyable<T>::value, "SoA columns must be trivially copyable");
593 std::memcpy(a_buf, &a_value, sizeof(T));
594 a_buf += sizeof(T);
595}
596
603template <typename T>
604inline void
605pullBytes(const unsigned char*& a_buf, T& a_value) noexcept
606{
607 static_assert(std::is_trivially_copyable<T>::value, "SoA columns must be trivially copyable");
608 std::memcpy(&a_value, a_buf, sizeof(T));
609 a_buf += sizeof(T);
610}
611
612} // namespace detail
613
653template <typename P = NoPayload, typename Traits = ParticleTraits<P>>
655{
656public:
661
665 using PayloadColumns = std::remove_cv_t<std::remove_reference_t<decltype(Traits::columns)>>;
666
670 static constexpr std::size_t s_numPayloadColumns = std::tuple_size<PayloadColumns>::value;
671
675 static constexpr std::size_t s_weightCol = SpaceDim;
676
680 static constexpr std::size_t s_idCol = SpaceDim + 1;
681
685 static constexpr std::size_t s_rankCol = SpaceDim + 2;
686
690 static constexpr std::size_t s_ghostCol = SpaceDim + 3;
691
695 static constexpr std::size_t s_payloadBegin = SpaceDim + 4;
696
700 static constexpr std::size_t s_numColumns = s_payloadBegin + s_numPayloadColumns;
701
705 static constexpr std::size_t s_align = 64;
706
708
709private:
713 using PositionValues = typename detail::RepeatTuple<double, SpaceDim>::Type;
714
718 using MandatoryValues = decltype(std::tuple_cat(std::declval<PositionValues>(),
719 std::declval<std::tuple<double, ParticleID, RankID, GhostType>>()));
720
724 using PayloadValues = typename detail::ValueTuple<PayloadColumns>::Type;
725
726public:
731
735 using ColumnValueTuple = decltype(std::tuple_cat(std::declval<MandatoryValues>(), std::declval<PayloadValues>()));
736
740 template <std::size_t K>
741 using ColumnType = std::tuple_element_t<K, ColumnValueTuple>;
742
749 template <typename M>
750 static constexpr std::size_t
751 columnIndex(const M a_member) noexcept
752 {
753 return s_payloadBegin + detail::indexOf(Traits::columns, a_member);
754 }
755
760
762
763 // ----- Sanity checks ------------------------------------------------------
764 static_assert(std::is_default_constructible<P>::value, "payload type P must be default-constructible");
766 "every particle column must be trivially copyable for MPI/HDF5");
767
772
776 ParticleSoA() = default;
777
787
791 ParticleSoA(const ParticleSoA&) = delete;
792
798 operator=(const ParticleSoA&) = delete;
799
804 ParticleSoA(ParticleSoA&& a_other) noexcept
805 {
806 this->steal(a_other);
807 }
808
815 operator=(ParticleSoA&& a_other) noexcept
816 {
817 if (this != &a_other) {
819
820 std::free(m_buffer);
821 this->steal(a_other);
822 }
823 return *this;
824 }
825
834 [[nodiscard]] ParticleSoA
835 deepCopy() const;
836
846 void
847 deepCopyTo(ParticleSoA& a_dst) const;
848
855 void
856 swap(ParticleSoA& a_other) noexcept
857 {
858 std::swap(m_buffer, a_other.m_buffer);
859 std::swap(m_bytes, a_other.m_bytes);
860 std::swap(m_capacity, a_other.m_capacity);
861 std::swap(m_size, a_other.m_size);
862 std::swap(m_sorted, a_other.m_sorted);
863 std::swap(m_colPtrs, a_other.m_colPtrs);
864 m_cellStart.swap(a_other.m_cellStart);
865 std::swap(m_sortBox, a_other.m_sortBox);
866 std::swap(m_sortDx, a_other.m_sortDx);
867 std::swap(m_sortProbLo, a_other.m_sortProbLo);
868 }
869
871
876
881 std::size_t
882 size() const noexcept
883 {
884 return m_size;
885 }
886
891 std::size_t
892 capacity() const noexcept
893 {
894 return m_capacity;
895 }
896
901 bool
902 empty() const noexcept
903 {
904 return m_size == 0;
905 }
906
914 void
915 clear() noexcept
916 {
917 if (m_size > 0) {
918 m_sorted = false;
919 }
920
921 m_size = 0;
922 }
923
928 void
929 reserve(const std::size_t a_capacity);
930
935 void
936 resize(const std::size_t a_count);
937
944 void
945 shrinkToFit();
946
948
953
961 void
962 append(const RealVect& a_position, const double a_weight)
963 {
964 this->append(a_position, a_weight, P{});
965 }
966
975 void
976 append(const RealVect& a_position, const double a_weight, const P& a_payload);
977
986 void
987 append(const ParticleSoA& a_other);
988
997 void
998 appendParticle(const ParticleSoA& a_src, const std::size_t a_index);
999
1008 void
1010 {
1011 if (this == &a_other || a_other.m_size == 0) {
1012 return;
1013 }
1014 if (m_size == 0) {
1015 this->swap(a_other); // zero-copy steal into an empty destination
1016 return;
1017 }
1018 this->append(a_other); // bulk per-column copy
1019 a_other.clear(); // move semantics: leave the source empty
1020 }
1021
1027 P
1028 gather(const std::size_t a_index) const
1029 {
1030 CH_assert(a_index < m_size);
1031
1032 return this->gatherPayload(a_index, std::make_index_sequence<s_numPayloadColumns>{});
1033 }
1034
1039 void
1040 remove(const std::size_t a_index) noexcept
1041 {
1042 CH_assert(a_index < m_size);
1043
1044 this->removeImpl(a_index, std::make_index_sequence<s_numColumns>{});
1045 m_size--;
1046 m_sorted = false;
1047 }
1048
1050
1055
1061 template <std::size_t K>
1062 ColumnType<K>*
1063 columnByIndex() noexcept
1064 {
1065 return reinterpret_cast<ColumnType<K>*>(m_colPtrs[K]);
1066 }
1067
1073 template <std::size_t K>
1074 const ColumnType<K>*
1075 columnByIndex() const noexcept
1076 {
1077 return reinterpret_cast<const ColumnType<K>*>(m_colPtrs[K]);
1078 }
1079
1085 template <auto Member>
1086 auto*
1087 column() noexcept
1088 {
1089 return this->template columnByIndex<columnIndex(Member)>();
1090 }
1091
1097 template <auto Member>
1098 const auto*
1099 column() const noexcept
1100 {
1101 return this->template columnByIndex<columnIndex(Member)>();
1102 }
1103
1110 template <auto Member>
1111 auto&
1112 get(const std::size_t a_index) noexcept
1113 {
1114 CH_assert(a_index < m_size);
1115
1116 return this->template columnByIndex<columnIndex(Member)>()[a_index];
1117 }
1118
1125 template <auto Member>
1126 const auto&
1127 get(const std::size_t a_index) const noexcept
1128 {
1129 CH_assert(a_index < m_size);
1130
1131 return this->template columnByIndex<columnIndex(Member)>()[a_index];
1132 }
1133
1143 double*
1144 positionColumn(const int a_dir) noexcept
1145 {
1146 m_sorted = false;
1147
1148 return reinterpret_cast<double*>(m_colPtrs[a_dir]);
1149 }
1150
1156 const double*
1157 positionColumn(const int a_dir) const noexcept
1158 {
1159 return reinterpret_cast<const double*>(m_colPtrs[a_dir]);
1160 }
1161
1166 double*
1167 weightColumn() noexcept
1168 {
1169 return this->template columnByIndex<s_weightCol>();
1170 }
1171
1176 const double*
1177 weightColumn() const noexcept
1178 {
1179 return this->template columnByIndex<s_weightCol>();
1180 }
1181
1183
1188
1194 RealVect
1195 position(const std::size_t a_index) const noexcept
1196 {
1197 CH_assert(a_index < m_size);
1198
1199 RealVect x;
1200 for (int dir = 0; dir < SpaceDim; dir++) {
1201 x[dir] = this->positionColumn(dir)[a_index];
1202 }
1203 return x;
1204 }
1205
1212 void
1213 setPosition(const std::size_t a_index, const RealVect& a_position) noexcept
1214 {
1215 CH_assert(a_index < m_size);
1216
1217 // Writes through the non-const positionColumn(), which clears m_sorted.
1218 for (int dir = 0; dir < SpaceDim; dir++) {
1219 this->positionColumn(dir)[a_index] = a_position[dir];
1220 }
1221 }
1222
1228 double&
1229 weight(const std::size_t a_index) noexcept
1230 {
1231 CH_assert(a_index < m_size);
1232
1233 return this->template columnByIndex<s_weightCol>()[a_index];
1234 }
1235
1241 const double&
1242 weight(const std::size_t a_index) const noexcept
1243 {
1244 CH_assert(a_index < m_size);
1245
1246 return this->template columnByIndex<s_weightCol>()[a_index];
1247 }
1248
1252 static constexpr ParticleID s_invalidID = -1;
1253
1259 ParticleID&
1260 particleID(const std::size_t a_index) noexcept
1261 {
1262 CH_assert(a_index < m_size);
1263
1264 return this->template columnByIndex<s_idCol>()[a_index];
1265 }
1266
1272 const ParticleID&
1273 particleID(const std::size_t a_index) const noexcept
1274 {
1275 CH_assert(a_index < m_size);
1276
1277 return this->template columnByIndex<s_idCol>()[a_index];
1278 }
1279
1285 RankID&
1286 rankID(const std::size_t a_index) noexcept
1287 {
1288 CH_assert(a_index < m_size);
1289
1290 return this->template columnByIndex<s_rankCol>()[a_index];
1291 }
1292
1298 const RankID&
1299 rankID(const std::size_t a_index) const noexcept
1300 {
1301 CH_assert(a_index < m_size);
1302
1303 return this->template columnByIndex<s_rankCol>()[a_index];
1304 }
1305
1311 GhostType&
1312 ghost(const std::size_t a_index) noexcept
1313 {
1314 CH_assert(a_index < m_size);
1315
1316 return this->template columnByIndex<s_ghostCol>()[a_index];
1317 }
1318
1324 const GhostType&
1325 ghost(const std::size_t a_index) const noexcept
1326 {
1327 CH_assert(a_index < m_size);
1328
1329 return this->template columnByIndex<s_ghostCol>()[a_index];
1330 }
1331
1337 bool
1338 isGhost(const std::size_t a_index) const noexcept
1339 {
1340 return this->ghost(a_index) != GhostType::Valid;
1341 }
1342
1344
1349
1354 static constexpr std::size_t
1359
1365 void
1366 linearizeParticle(void* a_buffer, const std::size_t a_index) const noexcept;
1367
1372 void
1373 delinearizeAndAppend(const void* a_buffer);
1374
1376
1381
1386 static constexpr std::size_t
1388 {
1389 return (SpaceDim + 1) * sizeof(double) + h5PayloadSize(H5PayloadColumns{});
1390 }
1391
1397 void
1398 h5LinearizeParticle(void* a_buffer, const std::size_t a_index) const noexcept;
1399
1405 void
1406 h5DelinearizeAndAppend(const void* a_buffer);
1407
1409
1414
1419 const void*
1420 data() const noexcept
1421 {
1422 return m_buffer;
1423 }
1424
1429 void*
1430 data() noexcept
1431 {
1432 return m_buffer;
1433 }
1434
1439 std::size_t
1440 byteSpan() const noexcept
1441 {
1442 if (m_size == 0) {
1443 return 0;
1444 }
1445 return this->byteSpanImpl(std::make_index_sequence<s_numColumns>{});
1446 }
1447
1449
1454
1472 void
1473 sortByCell(const Box& a_box, const RealVect& a_dx, const RealVect& a_probLo);
1474
1479 bool
1480 isSorted() const noexcept
1481 {
1482 return m_sorted;
1483 }
1484
1494 bool
1495 isSortedAgainst(const Box& a_box, const RealVect& a_dx, const RealVect& a_probLo) const noexcept
1496 {
1497 return m_sorted && m_sortBox == a_box && m_sortDx == a_dx && m_sortProbLo == a_probLo;
1498 }
1499
1504 std::size_t
1505 numCells() const noexcept
1506 {
1507 return m_cellStart.empty() ? 0 : m_cellStart.size() - 1;
1508 }
1509
1515 std::size_t
1516 cellStart(const std::size_t a_cell) const noexcept
1517 {
1518 CH_assert(m_sorted);
1519 CH_assert(a_cell <= this->numCells());
1520
1521 return m_cellStart[a_cell];
1522 }
1523
1529 std::size_t
1530 particlesInCell(const std::size_t a_cell) const noexcept
1531 {
1532 CH_assert(m_sorted);
1533 CH_assert(a_cell < this->numCells());
1534
1535 return m_cellStart[a_cell + 1] - m_cellStart[a_cell];
1536 }
1537
1545 std::pair<std::size_t, std::size_t>
1546 cellRange(const std::size_t a_cell) const noexcept
1547 {
1548 CH_assert(m_sorted);
1549 CH_assert(a_cell < this->numCells());
1550
1551 return {m_cellStart[a_cell], m_cellStart[a_cell + 1]};
1552 }
1553
1565 void
1566 extractCell(const std::size_t a_cell, ParticleSoA& a_out) const
1567 {
1568 CH_assert(m_sorted);
1569
1570 a_out.clear();
1571
1572 const std::pair<std::size_t, std::size_t> range = this->cellRange(a_cell);
1573 for (std::size_t i = range.first; i < range.second; i++) {
1574 a_out.appendParticle(*this, i);
1575 }
1576 }
1577
1585 const std::vector<std::size_t>&
1586 cellOffsets() const noexcept
1587 {
1588 CH_assert(m_sorted);
1589
1590 return m_cellStart;
1591 }
1592
1607 void
1608 adoptCellSort(const Box& a_box,
1609 const RealVect& a_dx,
1610 const RealVect& a_probLo,
1611 std::vector<std::size_t> a_cellStart) noexcept
1612 {
1613 CH_assert(a_cellStart.size() == static_cast<std::size_t>(a_box.numPts()) + 1);
1614 CH_assert(a_cellStart.back() == m_size);
1615
1616 m_cellStart = std::move(a_cellStart);
1617 m_sortBox = a_box;
1618 m_sortDx = a_dx;
1619 m_sortProbLo = a_probLo;
1620 m_sorted = true;
1621
1622 CH_assert(this->checkCellSort(a_box, a_dx, a_probLo));
1623 }
1624
1626
1627protected:
1631 void* m_buffer = nullptr;
1632
1636 std::size_t m_capacity = 0;
1637
1646 std::size_t m_bytes = 0;
1647
1651 std::size_t m_size = 0;
1652
1656 bool m_sorted = false;
1657
1661 std::array<void*, s_numColumns> m_colPtrs{};
1662
1666 std::vector<std::size_t> m_cellStart;
1667
1672
1676 RealVect m_sortDx = RealVect::Zero;
1677
1681 RealVect m_sortProbLo = RealVect::Zero;
1682
1693 std::size_t
1694 cellKey(const std::size_t a_index, const Box& a_box, const RealVect& a_dx, const RealVect& a_probLo) const noexcept
1695 {
1696 const IntVect loEnd = a_box.smallEnd();
1697 const IntVect boxSize = a_box.size();
1698 const RealVect x = this->position(a_index);
1699
1700 std::size_t lin = 0;
1701 std::size_t stride = 1;
1702 for (int d = 0; d < SpaceDim; d++) {
1703 int c = static_cast<int>(std::floor((x[d] - a_probLo[d]) / a_dx[d])) - loEnd[d];
1704 if (c < 0) {
1705 c = 0;
1706 }
1707 if (c >= boxSize[d]) {
1708 c = boxSize[d] - 1;
1709 }
1710 lin += static_cast<std::size_t>(c) * stride;
1711 stride *= static_cast<std::size_t>(boxSize[d]);
1712 }
1713
1714 return lin;
1715 }
1716
1728 bool
1729 checkCellSort(const Box& a_box, const RealVect& a_dx, const RealVect& a_probLo) const noexcept
1730 {
1731 if (!m_sorted) {
1732 return false;
1733 }
1734 if (m_cellStart.size() != static_cast<std::size_t>(a_box.numPts()) + 1) {
1735 return false;
1736 }
1737 if (m_cellStart.back() != m_size) {
1738 return false;
1739 }
1740
1741 for (std::size_t c = 0; c < this->numCells(); c++) {
1742 if (m_cellStart[c] > m_cellStart[c + 1]) {
1743 return false;
1744 }
1745
1746 for (std::size_t i = m_cellStart[c]; i < m_cellStart[c + 1]; i++) {
1747 if (this->cellKey(i, a_box, a_dx, a_probLo) != c) {
1748 return false;
1749 }
1750 }
1751 }
1752
1753 return true;
1754 }
1755
1761 static std::size_t
1762 alignUp(const std::size_t a_x) noexcept
1763 {
1764 return (a_x + (s_align - 1)) / s_align * s_align;
1765 }
1766
1771 void
1772 steal(ParticleSoA& a_o) noexcept
1773 {
1774 m_buffer = a_o.m_buffer;
1775 m_capacity = a_o.m_capacity;
1776 m_bytes = a_o.m_bytes;
1777 m_size = a_o.m_size;
1778 m_sorted = a_o.m_sorted;
1779 m_sortBox = a_o.m_sortBox;
1780 m_sortDx = a_o.m_sortDx;
1781 m_sortProbLo = a_o.m_sortProbLo;
1782 m_colPtrs = a_o.m_colPtrs;
1783 m_cellStart = std::move(a_o.m_cellStart);
1784 a_o.m_buffer = nullptr;
1785 a_o.m_capacity = 0;
1786 a_o.m_bytes = 0;
1787 a_o.m_size = 0;
1788 a_o.m_sorted = false;
1789 a_o.m_colPtrs = {};
1790 }
1791
1809 void
1810 growTo(const std::size_t a_needed)
1811 {
1812 if (a_needed <= m_capacity) {
1813 return;
1814 }
1815
1816 // Saturating geometric growth: 2 * m_capacity overflows std::size_t once m_capacity exceeds
1817 // SIZE_MAX/2, and reserve()'s "a_capacity <= m_capacity" guard would then silently no-op.
1818 const std::size_t doubled = (m_capacity == 0) ? 16
1819 : (m_capacity <= std::numeric_limits<std::size_t>::max() / 2
1820 ? 2 * m_capacity
1821 : std::numeric_limits<std::size_t>::max());
1822
1823 this->reserve(std::max(a_needed, doubled));
1824 }
1825
1829 void
1831 {
1832 if (m_size == m_capacity) {
1833 this->growTo(m_size + 1);
1834 }
1835 }
1836
1844 template <std::size_t... I>
1845 std::size_t
1846 computeOffsets(const std::size_t a_capacity,
1847 std::array<std::size_t, s_numColumns>& a_off,
1848 std::index_sequence<I...>) const noexcept
1849 {
1850 std::size_t running = 0;
1851 using expander = int[];
1852 (void)expander{0, (a_off[I] = running, running += alignUp(a_capacity * sizeof(ColumnType<I>)), 0)...};
1853 return running;
1854 }
1855
1861 template <std::size_t... I>
1862 void
1863 setColPtrs(const std::array<std::size_t, s_numColumns>& a_off, std::index_sequence<I...>) noexcept
1864 {
1865 using expander = int[];
1866 (void)expander{0, (m_colPtrs[I] = static_cast<char*>(m_buffer) + a_off[I], 0)...};
1867 }
1868
1875 template <std::size_t... I>
1876 void
1877 moveColumns(void* a_newBuf, const std::array<std::size_t, s_numColumns>& a_off, std::index_sequence<I...>) noexcept
1878 {
1879 using expander = int[];
1880 (void)expander{
1881 0,
1882 (std::memcpy(static_cast<char*>(a_newBuf) + a_off[I], m_colPtrs[I], m_size * sizeof(ColumnType<I>)), 0)...};
1883 }
1884
1892 template <std::size_t... I>
1893 void
1894 copyLiveColumnsTo(ParticleSoA& a_dst, std::index_sequence<I...>) const noexcept
1895 {
1896 using expander = int[];
1897 (void)expander{0, (std::memcpy(a_dst.m_colPtrs[I], m_colPtrs[I], m_size * sizeof(ColumnType<I>)), 0)...};
1898 }
1899
1909 template <std::size_t... I>
1910 void
1911 appendColumnsFrom(const ParticleSoA& a_other, const std::size_t a_at, std::index_sequence<I...>) noexcept
1912 {
1913 using expander = int[];
1914 (void)expander{0,
1915 (std::memcpy(static_cast<char*>(m_colPtrs[I]) + a_at * sizeof(ColumnType<I>),
1916 a_other.m_colPtrs[I],
1917 a_other.m_size * sizeof(ColumnType<I>)),
1918 0)...};
1919 }
1920
1930 template <std::size_t... I>
1931 void
1933 const std::size_t a_srcIdx,
1934 const std::size_t a_dstIdx,
1935 std::index_sequence<I...>) noexcept
1936 {
1937 using expander = int[];
1938 (void)expander{0,
1939 (this->template columnByIndex<I>()[a_dstIdx] = a_src.template columnByIndex<I>()[a_srcIdx], 0)...};
1940 }
1941
1946 void
1947 reallocate(const std::size_t a_capacity);
1948
1953 void
1954 permute(const std::vector<std::size_t>& a_dest);
1955
1963 template <std::size_t K>
1964 void
1965 scatterColumn(void* a_newBuf, const std::size_t a_off, const std::vector<std::size_t>& a_dest) noexcept
1966 {
1967 const ColumnType<K>* src = this->template columnByIndex<K>();
1968 ColumnType<K>* dst = reinterpret_cast<ColumnType<K>*>(static_cast<char*>(a_newBuf) + a_off);
1969 for (std::size_t i = 0; i < m_size; i++) {
1970 dst[a_dest[i]] = src[i];
1971 }
1972 }
1973
1981 template <std::size_t... I>
1982 void
1983 scatterColumns(void* a_newBuf,
1984 const std::array<std::size_t, s_numColumns>& a_off,
1985 const std::vector<std::size_t>& a_dest,
1986 std::index_sequence<I...>) noexcept
1987 {
1988 using expander = int[];
1989 (void)expander{0, ((void)this->template scatterColumn<I>(a_newBuf, a_off[I], a_dest), 0)...};
1990 }
1991
1997 template <std::size_t... J>
1998 void
1999 writePayload(const P& a_p, std::index_sequence<J...>) noexcept
2000 {
2001 constexpr auto cols = Traits::columns;
2002 using expander = int[];
2003 (void)expander{0,
2004 ((void)(this->template columnByIndex<s_payloadBegin + J>()[m_size] = a_p.*std::get<J>(cols)), 0)...};
2005 }
2006
2013 template <std::size_t... J>
2014 P
2015 gatherPayload(const std::size_t a_index, std::index_sequence<J...>) const
2016 {
2017 constexpr auto cols = Traits::columns;
2018 P p;
2019 using expander = int[];
2020 (void)expander{0,
2021 ((void)(p.*std::get<J>(cols) = this->template columnByIndex<s_payloadBegin + J>()[a_index]), 0)...};
2022 return p;
2023 }
2024
2030 template <std::size_t... I>
2031 void
2032 removeImpl(const std::size_t a_index, std::index_sequence<I...>) noexcept
2033 {
2034 using expander = int[];
2035 (void)expander{
2036 0,
2037 ((void)(this->template columnByIndex<I>()[a_index] = this->template columnByIndex<I>()[m_size - 1]), 0)...};
2038 }
2039
2046 template <std::size_t... I>
2047 void
2048 linearizeImpl(unsigned char* a_buf, const std::size_t a_index, std::index_sequence<I...>) const noexcept
2049 {
2050 using expander = int[];
2051 (void)expander{0, ((void)detail::pushBytes(a_buf, this->template columnByIndex<I>()[a_index]), 0)...};
2052 }
2053
2059 template <std::size_t... I>
2060 void
2061 delinearizeImpl(const unsigned char* a_buf, std::index_sequence<I...>) noexcept
2062 {
2063 using expander = int[];
2064 (void)expander{0, ((void)this->template pullColumn<I>(a_buf), 0)...};
2065 }
2066
2072 template <std::size_t K>
2073 void
2074 pullColumn(const unsigned char*& a_buf) noexcept
2075 {
2076 detail::pullBytes(a_buf, this->template columnByIndex<K>()[m_size]);
2077 }
2078
2084 template <std::size_t... J>
2085 static constexpr std::size_t
2086 h5PayloadSize(std::index_sequence<J...>) noexcept
2087 {
2088 return detail::sumSizes(sizeof(ColumnType<s_payloadBegin + J>)...);
2089 }
2090
2097 template <std::size_t... J>
2098 void
2099 h5LinearizePayload(unsigned char*& a_buf, const std::size_t a_index, std::index_sequence<J...>) const noexcept
2100 {
2101 using expander = int[];
2102 (void)expander{0,
2103 ((void)detail::pushBytes(a_buf, this->template columnByIndex<s_payloadBegin + J>()[a_index]), 0)...};
2104 }
2105
2111 template <std::size_t... J>
2112 void
2113 h5DelinearizePayload(const unsigned char*& a_buf, std::index_sequence<J...>) noexcept
2114 {
2115 using expander = int[];
2116 (void)expander{0,
2117 ((void)detail::pullBytes(a_buf, this->template columnByIndex<s_payloadBegin + J>()[m_size]), 0)...};
2118 }
2119
2125 template <std::size_t... I>
2126 std::size_t
2127 byteSpanImpl(std::index_sequence<I...>) const noexcept
2128 {
2129 std::size_t span = 0;
2130 using expander = int[];
2131 (void)expander{0,
2132 (span = (span > (static_cast<std::size_t>(static_cast<const char*>(m_colPtrs[I]) -
2133 static_cast<const char*>(m_buffer)) +
2134 m_size * sizeof(ColumnType<I>)))
2135 ? span
2136 : (static_cast<std::size_t>(static_cast<const char*>(m_colPtrs[I]) -
2137 static_cast<const char*>(m_buffer)) +
2138 m_size * sizeof(ColumnType<I>)),
2139 0)...};
2140 return span;
2141 }
2142};
2143
2144#include <CD_NamespaceFooter.H>
2145
2146#include <CD_ParticleSoAImplem.H>
2147
2148#endif
Process-wide accounting of the memory held by particle data.
Implementation of CD_ParticleSoA.H.
constexpr bool eqMember(A, B) noexcept
Type-mismatched overload of the pointer-to-member equality (always false).
Definition CD_ParticleSoA.H:339
#define CD_PARTICLE_REAL
Compile-time precision of particle PAYLOAD data. Defaults to double; define CD_PARTICLE_REAL (e....
Definition CD_ParticleSoA.H:150
void pushBytes(unsigned char *&a_buf, const T &a_value) noexcept
memcpy one trivially-copyable value onto a byte buffer and advance the buffer pointer.
Definition CD_ParticleSoA.H:590
constexpr std::size_t indexOf(const Tup &a_t, M a_target) noexcept
Compile-time index of a member pointer within a tuple (tuple size if absent).
Definition CD_ParticleSoA.H:398
constexpr std::size_t indexOfImpl(const Tup &, M, std::index_sequence<>) noexcept
Base case of the compile-time member-pointer index search (empty sequence).
Definition CD_ParticleSoA.H:366
typename MakeVoid< Ts... >::Type Void
Alias yielding void for any type pack (SFINAE helper, like std::void_t).
Definition CD_ParticleSoA.H:532
std::int32_t RankID
Owning-rank identifier type (container-owned metadata column; fixed-width for I/O).
Definition CD_ParticleSoA.H:166
GhostType
Ghost designation of a particle (container-owned metadata column).
Definition CD_ParticleSoA.H:177
@ SameLevel
Ghost from an adjacent patch on the same level.
@ Coarse
Ghost from the next-coarser level (level l-1).
@ Valid
Owned, valid particle of this patch (not a ghost).
@ Fine
Ghost from the next-finer level (level l+1).
constexpr std::index_sequence< indexOf(Traits::columns, std::get< I >(Traits::h5Columns))... > deriveH5Seq(std::index_sequence< I... > a_seq) noexcept
Turn a tuple of HDF5 payload member pointers into a std::index_sequence of DERIVED payload-column ind...
Definition CD_ParticleSoA.H:544
void pullBytes(const unsigned char *&a_buf, T &a_value) noexcept
memcpy one trivially-copyable value off a byte buffer and advance the buffer pointer.
Definition CD_ParticleSoA.H:605
CD_PARTICLE_REAL ParticleReal
Floating-point type a user may use for payload columns.
Definition CD_ParticleSoA.H:156
constexpr std::size_t sumSizes() noexcept
Base case of the variadic constexpr size sum (no arguments).
Definition CD_ParticleSoA.H:456
std::int64_t ParticleID
Global particle identifier type (container-owned metadata column; fixed-width for I/O).
Definition CD_ParticleSoA.H:161
Arena-backed Struct-of-Arrays particle container for a single grid patch.
Definition CD_ParticleSoA.H:655
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.
Definition CD_ParticleSoA.H:2113
static constexpr std::size_t s_weightCol
Column index of the weight (immediately after the SpaceDim position columns).
Definition CD_ParticleSoA.H:675
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 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.
Definition CD_ParticleSoA.H:2099
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
RankID & rankID(const std::size_t a_index) noexcept
Owning rank of particle i (container-owned metadata).
Definition CD_ParticleSoA.H:1286
void append(const RealVect &a_position, const double a_weight)
Append one particle with a default-constructed payload.
Definition CD_ParticleSoA.H:962
const ParticleID & particleID(const std::size_t a_index) const noexcept
Const global id of particle i.
Definition CD_ParticleSoA.H:1273
ColumnType< K > * columnByIndex() noexcept
Typed base pointer of column K (low-level).
Definition CD_ParticleSoA.H:1063
void shrinkToFit()
Reclaim unused capacity by reallocating the arena down to the current size.
Definition CD_ParticleSoAImplem.H:187
double * weightColumn() noexcept
Raw weight column (double*).
Definition CD_ParticleSoA.H:1167
bool m_sorted
Whether m_cellStart is valid.
Definition CD_ParticleSoA.H:1656
bool isGhost(const std::size_t a_index) const noexcept
Whether particle i is a ghost particle (any non-Valid designation).
Definition CD_ParticleSoA.H:1338
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 removeImpl(const std::size_t a_index, std::index_sequence< I... >) noexcept
Swap-and-pop slot a_index in every column.
Definition CD_ParticleSoA.H:2032
const std::vector< std::size_t > & cellOffsets() const noexcept
The raw CSR start offsets (valid after sortByCell(); a_box.numPts()+1 entries).
Definition CD_ParticleSoA.H:1586
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
const double & weight(const std::size_t a_index) const noexcept
Const weight of particle i.
Definition CD_ParticleSoA.H:1242
const auto * column() const noexcept
Const whole payload column selected by member pointer.
Definition CD_ParticleSoA.H:1099
decltype(std::tuple_cat(std::declval< MandatoryValues >(), std::declval< PayloadValues >())) ColumnValueTuple
The value types of every column, in storage order.
Definition CD_ParticleSoA.H:735
std::size_t particlesInCell(const std::size_t a_cell) const noexcept
Number of particles in cell c (valid after sortByCell).
Definition CD_ParticleSoA.H:1530
auto & get(const std::size_t a_index) noexcept
One particle's payload field selected by member pointer.
Definition CD_ParticleSoA.H:1112
void steal(ParticleSoA &a_o) noexcept
Steal another container's arena (move helper).
Definition CD_ParticleSoA.H:1772
std::size_t m_capacity
Capacity in particles.
Definition CD_ParticleSoA.H:1636
RealVect position(const std::size_t a_index) const noexcept
Position of particle i as a RealVect (by value, assembled from the scalar columns).
Definition CD_ParticleSoA.H:1195
GhostType & ghost(const std::size_t a_index) noexcept
Ghost designation of particle i (container-owned metadata).
Definition CD_ParticleSoA.H:1312
double & weight(const std::size_t a_index) noexcept
Weight of particle i.
Definition CD_ParticleSoA.H:1229
std::size_t numCells() const noexcept
Number of cells in the CSR sort (0 if not sorted).
Definition CD_ParticleSoA.H:1505
static constexpr std::size_t bytesPerParticle() noexcept
Byte count of one fully-linearized particle (all columns, for MPI).
Definition CD_ParticleSoA.H:1355
void deepCopyTo(ParticleSoA &a_dst) const
Deep copy into an existing destination, reusing its arena when possible.
Definition CD_ParticleSoAImplem.H:130
static constexpr std::size_t s_align
Cache-line alignment for each column (also enables aligned SIMD).
Definition CD_ParticleSoA.H:705
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.
Definition CD_ParticleSoA.H:1863
const void * data() const noexcept
Raw arena pointer (column-major); a compact container's whole data span.
Definition CD_ParticleSoA.H:1420
static constexpr std::size_t h5PayloadSize(std::index_sequence< J... >) noexcept
Compile-time byte size of the HDF5 payload subset.
Definition CD_ParticleSoA.H:2086
std::size_t size() const noexcept
Number of particles currently stored.
Definition CD_ParticleSoA.H:882
void setPosition(const std::size_t a_index, const RealVect &a_position) noexcept
Set the position of particle i.
Definition CD_ParticleSoA.H:1213
static constexpr std::size_t s_numColumns
Total number of columns (SpaceDim position + weight + id + rank + ghost + payload).
Definition CD_ParticleSoA.H:700
static constexpr std::size_t s_numPayloadColumns
Number of user-declared payload columns.
Definition CD_ParticleSoA.H:670
std::size_t m_size
Live particle count.
Definition CD_ParticleSoA.H:1651
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
std::size_t byteSpanImpl(std::index_sequence< I... >) const noexcept
Byte span of the live data: max over columns of (offset + used bytes).
Definition CD_ParticleSoA.H:2127
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.
Definition CD_ParticleSoA.H:1846
double * positionColumn(const int a_dir) noexcept
Raw position component column dir (double*, for SIMD kernels).
Definition CD_ParticleSoA.H:1144
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.
Definition CD_ParticleSoA.H:1894
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.
Definition CD_ParticleSoA.H:1911
~ParticleSoA()
Destructor (frees the arena).
Definition CD_ParticleSoA.H:781
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 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.
Definition CD_ParticleSoA.H:1566
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 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).
Definition CD_ParticleSoA.H:2048
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.
Definition CD_ParticleSoA.H:2074
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].
Definition CD_ParticleSoA.H:1965
static constexpr std::size_t h5BytesPerParticle() noexcept
Bytes for one HDF5-linearized particle (position + weight + h5 payload subset).
Definition CD_ParticleSoA.H:1387
std::array< void *, s_numColumns > m_colPtrs
Cached column base pointers into m_buffer.
Definition CD_ParticleSoA.H:1661
P gather(const std::size_t a_index) const
Gather particle i's payload back into the AoS payload view.
Definition CD_ParticleSoA.H:1028
void * m_buffer
The single arena allocation.
Definition CD_ParticleSoA.H:1631
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).
Definition CD_ParticleSoA.H:2061
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
void writePayload(const P &a_p, std::index_sequence< J... >) noexcept
Write the payload columns of slot m_size from a payload struct.
Definition CD_ParticleSoA.H:1999
std::size_t m_bytes
Byte size of the arena at m_buffer (zero when m_buffer is null).
Definition CD_ParticleSoA.H:1646
std::size_t capacity() const noexcept
Allocated capacity in particles.
Definition CD_ParticleSoA.H:892
static std::size_t alignUp(const std::size_t a_x) noexcept
Round a_x up to the next multiple of s_align.
Definition CD_ParticleSoA.H:1762
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.
Definition CD_ParticleSoA.H:1983
const GhostType & ghost(const std::size_t a_index) const noexcept
Const ghost designation of particle i.
Definition CD_ParticleSoA.H:1325
ParticleID & particleID(const std::size_t a_index) noexcept
Global id of particle i (container-owned metadata).
Definition CD_ParticleSoA.H:1260
const ColumnType< K > * columnByIndex() const noexcept
Const typed base pointer of column K (low-level).
Definition CD_ParticleSoA.H:1075
ParticleSoA & operator=(const ParticleSoA &)=delete
Copy assignment is deleted (move-only).
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).
Definition CD_ParticleSoA.H:1546
static constexpr std::size_t s_rankCol
Column index of the container-owned rankID.
Definition CD_ParticleSoA.H:685
std::vector< std::size_t > m_cellStart
CSR cell offsets (size numCells+1 when sorted).
Definition CD_ParticleSoA.H:1666
void catenate(ParticleSoA &a_other)
Move every particle of another container into this one, leaving a_other empty (catenate).
Definition CD_ParticleSoA.H:1009
std::remove_cv_t< std::remove_reference_t< decltype(Traits::columns)> > PayloadColumns
The payload columns descriptor tuple type (tuple of pointer-to-member).
Definition CD_ParticleSoA.H:665
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.
Definition CD_ParticleSoA.H:1694
RealVect m_sortDx
Grid spacing the CSR mapping was built against (meaningful only when m_sorted).
Definition CD_ParticleSoA.H:1676
void adoptCellSort(const Box &a_box, const RealVect &a_dx, const RealVect &a_probLo, std::vector< std::size_t > a_cellStart) noexcept
Declare the container cell-sorted against (a_box, a_dx, a_probLo) with a caller-supplied CSR.
Definition CD_ParticleSoA.H:1608
void remove(const std::size_t a_index) noexcept
Remove particle i using swap-and-pop (O(1), does NOT preserve order).
Definition CD_ParticleSoA.H:1040
static constexpr ParticleID s_invalidID
Sentinel for an unassigned/invalid global particle id.
Definition CD_ParticleSoA.H:1252
void swap(ParticleSoA &a_other) noexcept
Swap the entire state (arena, size, capacity, sort) with another container in O(1).
Definition CD_ParticleSoA.H:856
bool empty() const noexcept
Whether the container holds no particles.
Definition CD_ParticleSoA.H:902
static constexpr std::size_t s_payloadBegin
Index of the first payload column.
Definition CD_ParticleSoA.H:695
void * data() noexcept
Mutable raw arena pointer (e.g. zero-copy MPI receive into the arena).
Definition CD_ParticleSoA.H:1430
void growTo(const std::size_t a_needed)
Grow the arena to hold at least a_needed particles, geometrically.
Definition CD_ParticleSoA.H:1810
ParticleSoA & operator=(ParticleSoA &&a_other) noexcept
Move assignment (steals the arena).
Definition CD_ParticleSoA.H:815
void growIfFull()
Grow geometrically if the container is full (called before writing slot m_size).
Definition CD_ParticleSoA.H:1830
RealVect m_sortProbLo
Lower domain corner the CSR mapping was built against (meaningful only when m_sorted).
Definition CD_ParticleSoA.H:1681
P gatherPayload(const std::size_t a_index, std::index_sequence< J... >) const
Read the payload columns of slot a_index into a payload struct.
Definition CD_ParticleSoA.H:2015
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].
Definition CD_ParticleSoA.H:1932
auto * column() noexcept
Whole payload column selected by member pointer (raw pointer, vectorizable).
Definition CD_ParticleSoA.H:1087
const auto & get(const std::size_t a_index) const noexcept
Const overload of get<&P::field>(i).
Definition CD_ParticleSoA.H:1127
Box m_sortBox
Patch box the CSR mapping in m_cellStart was built against (meaningful only when m_sorted).
Definition CD_ParticleSoA.H:1671
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.
Definition CD_ParticleSoA.H:1495
ParticleSoA(const ParticleSoA &)=delete
Copy construction is deleted (move-only).
const double * positionColumn(const int a_dir) const noexcept
Const raw position component column dir.
Definition CD_ParticleSoA.H:1157
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.
Definition CD_ParticleSoA.H:1877
static constexpr std::size_t columnIndex(const M a_member) noexcept
Derive the column index of a PAYLOAD member pointer (reorder-safe selector).
Definition CD_ParticleSoA.H:751
std::size_t byteSpan() const noexcept
Byte span of the live data (for a compact container, one contiguous memcpy/MPI_Send).
Definition CD_ParticleSoA.H:1440
ParticleSoA(ParticleSoA &&a_other) noexcept
Move constructor (steals the arena).
Definition CD_ParticleSoA.H:804
static constexpr std::size_t s_idCol
Column index of the container-owned particleID.
Definition CD_ParticleSoA.H:680
void clear() noexcept
Drop all particles (keeps the arena; invalidates the cell sort unless there was nothing to drop).
Definition CD_ParticleSoA.H:915
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
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.
Definition CD_ParticleSoA.H:1729
bool isSorted() const noexcept
Whether the container is currently cell-sorted (false after append/remove).
Definition CD_ParticleSoA.H:1480
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
ParticleSoA()=default
Construct an empty container.
const double * weightColumn() const noexcept
Const raw weight column.
Definition CD_ParticleSoA.H:1177
static constexpr std::size_t s_ghostCol
Column index of the container-owned ghost designation.
Definition CD_ParticleSoA.H:690
std::size_t cellStart(const std::size_t a_cell) const noexcept
CSR start offset of cell c (valid after sortByCell; requires c <= numCells()).
Definition CD_ParticleSoA.H:1516
const RankID & rankID(const std::size_t a_index) const noexcept
Const owning rank of particle i.
Definition CD_ParticleSoA.H:1299
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
std::tuple_element_t< K, ColumnValueTuple > ColumnType
Value type of column K.
Definition CD_ParticleSoA.H:741
Declarative descriptors for selecting which particle PAYLOAD columns are written to H5Part (visualiza...
Definition CD_ParticleSoA.H:212
void removeBytes(const Kind a_kind, const std::size_t a_bytes) noexcept
Record a release.
Definition CD_ParticleMemory.H:140
@ Container
ParticleSoA arenas: capacity a rank is holding.
Descriptor of a single scalar payload column written to one H5Part dataset.
Definition CD_ParticleSoA.H:220
const char * name
H5Part dataset name.
Definition CD_ParticleSoA.H:229
M member
Pointer-to-member selecting the payload column.
Definition CD_ParticleSoA.H:234
static constexpr bool s_isVector
Tag identifying this descriptor as a scalar (single-component) column.
Definition CD_ParticleSoA.H:224
Descriptor of a SpaceDim-component vector payload column, written as name-x/name-y/name-z.
Definition CD_ParticleSoA.H:250
const char * name
H5Part dataset base name (datasets are name-x/name-y/name-z).
Definition CD_ParticleSoA.H:259
static constexpr bool s_isVector
Tag identifying this descriptor as a vector (multi-component) column.
Definition CD_ParticleSoA.H:254
std::tuple< Ms... > members
Pointers-to-member selecting the per-component payload columns.
Definition CD_ParticleSoA.H:264
constexpr Vector(const char *a_name, Ms... a_members) noexcept
Constructor.
Definition CD_ParticleSoA.H:271
Empty payload: ParticleSoA<> is a position+weight+metadata point particle.
Definition CD_ParticleSoA.H:289
Traits class that a user specializes to describe the PAYLOAD columns of a particle type....
Definition CD_ParticleSoA.H:192
Primary template for "every type in a value tuple is trivially copyable".
Definition CD_ParticleSoA.H:500
decltype(deriveH5Seq< Traits >(std::make_index_sequence< std::tuple_size< H5Tuple >::value >{})) Type
Derived payload-column index subset.
Definition CD_ParticleSoA.H:579
std::remove_cv_t< std::remove_reference_t< decltype(Traits::h5Columns)> > H5Tuple
The declared h5Columns tuple type.
Definition CD_ParticleSoA.H:575
Primary template resolving the HDF5 payload column subset; defaults to all columns.
Definition CD_ParticleSoA.H:557
Fallback Type
The resolved subset (all payload columns).
Definition CD_ParticleSoA.H:561
Stand-in for std::void_t (maps any type pack to void).
Definition CD_ParticleSoA.H:521
void Type
Always void.
Definition CD_ParticleSoA.H:525
T ValueType
Value type of the member.
Definition CD_ParticleSoA.H:328
C ClassType
Class that owns the member.
Definition CD_ParticleSoA.H:324
Primary template that extracts the class and value type from a pointer-to-member type.
Definition CD_ParticleSoA.H:311
std::tuple of N copies of T (used to build the SpaceDim position columns).
Definition CD_ParticleSoA.H:410
static std::tuple< Always< I >... > make(std::index_sequence< I... >)
Deduce the repeated-tuple type from an index sequence (declaration only).
decltype(make(std::make_index_sequence< N >{})) Type
The resulting std::tuple type.
Definition CD_ParticleSoA.H:428
T Always
Helper alias that maps any index to T.
Definition CD_ParticleSoA.H:415
Primary template for the compile-time sum of sizeof() over a value tuple.
Definition CD_ParticleSoA.H:480
std::tuple< typename MemberPointerTraits< Ms >::ValueType... > Type
Tuple of member value types.
Definition CD_ParticleSoA.H:448
Primary template mapping a tuple of pointer-to-member to the tuple of value types.
Definition CD_ParticleSoA.H:436