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
910 void
911 clear() noexcept
912 {
913 m_size = 0;
914 m_sorted = false;
915 }
916
921 void
922 reserve(const std::size_t a_capacity);
923
928 void
929 resize(const std::size_t a_count);
930
937 void
938 shrinkToFit();
939
941
946
954 void
955 append(const RealVect& a_position, const double a_weight)
956 {
957 this->append(a_position, a_weight, P{});
958 }
959
968 void
969 append(const RealVect& a_position, const double a_weight, const P& a_payload);
970
979 void
980 append(const ParticleSoA& a_other);
981
990 void
991 appendParticle(const ParticleSoA& a_src, const std::size_t a_index);
992
1001 void
1003 {
1004 if (this == &a_other || a_other.m_size == 0) {
1005 return;
1006 }
1007 if (m_size == 0) {
1008 this->swap(a_other); // zero-copy steal into an empty destination
1009 return;
1010 }
1011 this->append(a_other); // bulk per-column copy
1012 a_other.clear(); // move semantics: leave the source empty
1013 }
1014
1020 P
1021 gather(const std::size_t a_index) const
1022 {
1023 CH_assert(a_index < m_size);
1024
1025 return this->gatherPayload(a_index, std::make_index_sequence<s_numPayloadColumns>{});
1026 }
1027
1032 void
1033 remove(const std::size_t a_index) noexcept
1034 {
1035 CH_assert(a_index < m_size);
1036
1037 this->removeImpl(a_index, std::make_index_sequence<s_numColumns>{});
1038 m_size--;
1039 m_sorted = false;
1040 }
1041
1043
1048
1054 template <std::size_t K>
1055 ColumnType<K>*
1056 columnByIndex() noexcept
1057 {
1058 return reinterpret_cast<ColumnType<K>*>(m_colPtrs[K]);
1059 }
1060
1066 template <std::size_t K>
1067 const ColumnType<K>*
1068 columnByIndex() const noexcept
1069 {
1070 return reinterpret_cast<const ColumnType<K>*>(m_colPtrs[K]);
1071 }
1072
1078 template <auto Member>
1079 auto*
1080 column() noexcept
1081 {
1082 return this->template columnByIndex<columnIndex(Member)>();
1083 }
1084
1090 template <auto Member>
1091 const auto*
1092 column() const noexcept
1093 {
1094 return this->template columnByIndex<columnIndex(Member)>();
1095 }
1096
1103 template <auto Member>
1104 auto&
1105 get(const std::size_t a_index) noexcept
1106 {
1107 CH_assert(a_index < m_size);
1108
1109 return this->template columnByIndex<columnIndex(Member)>()[a_index];
1110 }
1111
1118 template <auto Member>
1119 const auto&
1120 get(const std::size_t a_index) const noexcept
1121 {
1122 CH_assert(a_index < m_size);
1123
1124 return this->template columnByIndex<columnIndex(Member)>()[a_index];
1125 }
1126
1136 double*
1137 positionColumn(const int a_dir) noexcept
1138 {
1139 m_sorted = false;
1140
1141 return reinterpret_cast<double*>(m_colPtrs[a_dir]);
1142 }
1143
1149 const double*
1150 positionColumn(const int a_dir) const noexcept
1151 {
1152 return reinterpret_cast<const double*>(m_colPtrs[a_dir]);
1153 }
1154
1159 double*
1160 weightColumn() noexcept
1161 {
1162 return this->template columnByIndex<s_weightCol>();
1163 }
1164
1169 const double*
1170 weightColumn() const noexcept
1171 {
1172 return this->template columnByIndex<s_weightCol>();
1173 }
1174
1176
1181
1187 RealVect
1188 position(const std::size_t a_index) const noexcept
1189 {
1190 CH_assert(a_index < m_size);
1191
1192 RealVect x;
1193 for (int dir = 0; dir < SpaceDim; dir++) {
1194 x[dir] = this->positionColumn(dir)[a_index];
1195 }
1196 return x;
1197 }
1198
1205 void
1206 setPosition(const std::size_t a_index, const RealVect& a_position) noexcept
1207 {
1208 CH_assert(a_index < m_size);
1209
1210 // Writes through the non-const positionColumn(), which clears m_sorted.
1211 for (int dir = 0; dir < SpaceDim; dir++) {
1212 this->positionColumn(dir)[a_index] = a_position[dir];
1213 }
1214 }
1215
1221 double&
1222 weight(const std::size_t a_index) noexcept
1223 {
1224 CH_assert(a_index < m_size);
1225
1226 return this->template columnByIndex<s_weightCol>()[a_index];
1227 }
1228
1234 const double&
1235 weight(const std::size_t a_index) const noexcept
1236 {
1237 CH_assert(a_index < m_size);
1238
1239 return this->template columnByIndex<s_weightCol>()[a_index];
1240 }
1241
1245 static constexpr ParticleID s_invalidID = -1;
1246
1252 ParticleID&
1253 particleID(const std::size_t a_index) noexcept
1254 {
1255 CH_assert(a_index < m_size);
1256
1257 return this->template columnByIndex<s_idCol>()[a_index];
1258 }
1259
1265 const ParticleID&
1266 particleID(const std::size_t a_index) const noexcept
1267 {
1268 CH_assert(a_index < m_size);
1269
1270 return this->template columnByIndex<s_idCol>()[a_index];
1271 }
1272
1278 RankID&
1279 rankID(const std::size_t a_index) noexcept
1280 {
1281 CH_assert(a_index < m_size);
1282
1283 return this->template columnByIndex<s_rankCol>()[a_index];
1284 }
1285
1291 const RankID&
1292 rankID(const std::size_t a_index) const noexcept
1293 {
1294 CH_assert(a_index < m_size);
1295
1296 return this->template columnByIndex<s_rankCol>()[a_index];
1297 }
1298
1304 GhostType&
1305 ghost(const std::size_t a_index) noexcept
1306 {
1307 CH_assert(a_index < m_size);
1308
1309 return this->template columnByIndex<s_ghostCol>()[a_index];
1310 }
1311
1317 const GhostType&
1318 ghost(const std::size_t a_index) const noexcept
1319 {
1320 CH_assert(a_index < m_size);
1321
1322 return this->template columnByIndex<s_ghostCol>()[a_index];
1323 }
1324
1330 bool
1331 isGhost(const std::size_t a_index) const noexcept
1332 {
1333 return this->ghost(a_index) != GhostType::Valid;
1334 }
1335
1337
1342
1347 static constexpr std::size_t
1352
1358 void
1359 linearizeParticle(void* a_buffer, const std::size_t a_index) const noexcept;
1360
1365 void
1366 delinearizeAndAppend(const void* a_buffer);
1367
1369
1374
1379 static constexpr std::size_t
1381 {
1382 return (SpaceDim + 1) * sizeof(double) + h5PayloadSize(H5PayloadColumns{});
1383 }
1384
1390 void
1391 h5LinearizeParticle(void* a_buffer, const std::size_t a_index) const noexcept;
1392
1398 void
1399 h5DelinearizeAndAppend(const void* a_buffer);
1400
1402
1407
1412 const void*
1413 data() const noexcept
1414 {
1415 return m_buffer;
1416 }
1417
1422 void*
1423 data() noexcept
1424 {
1425 return m_buffer;
1426 }
1427
1432 std::size_t
1433 byteSpan() const noexcept
1434 {
1435 if (m_size == 0) {
1436 return 0;
1437 }
1438 return this->byteSpanImpl(std::make_index_sequence<s_numColumns>{});
1439 }
1440
1442
1447
1465 void
1466 sortByCell(const Box& a_box, const RealVect& a_dx, const RealVect& a_probLo);
1467
1472 bool
1473 isSorted() const noexcept
1474 {
1475 return m_sorted;
1476 }
1477
1487 bool
1488 isSortedAgainst(const Box& a_box, const RealVect& a_dx, const RealVect& a_probLo) const noexcept
1489 {
1490 return m_sorted && m_sortBox == a_box && m_sortDx == a_dx && m_sortProbLo == a_probLo;
1491 }
1492
1497 std::size_t
1498 numCells() const noexcept
1499 {
1500 return m_cellStart.empty() ? 0 : m_cellStart.size() - 1;
1501 }
1502
1508 std::size_t
1509 cellStart(const std::size_t a_cell) const noexcept
1510 {
1511 CH_assert(m_sorted);
1512 CH_assert(a_cell <= this->numCells());
1513
1514 return m_cellStart[a_cell];
1515 }
1516
1522 std::size_t
1523 particlesInCell(const std::size_t a_cell) const noexcept
1524 {
1525 CH_assert(m_sorted);
1526 CH_assert(a_cell < this->numCells());
1527
1528 return m_cellStart[a_cell + 1] - m_cellStart[a_cell];
1529 }
1530
1538 std::pair<std::size_t, std::size_t>
1539 cellRange(const std::size_t a_cell) const noexcept
1540 {
1541 CH_assert(m_sorted);
1542 CH_assert(a_cell < this->numCells());
1543
1544 return {m_cellStart[a_cell], m_cellStart[a_cell + 1]};
1545 }
1546
1558 void
1559 extractCell(const std::size_t a_cell, ParticleSoA& a_out) const
1560 {
1561 CH_assert(m_sorted);
1562
1563 a_out.clear();
1564
1565 const std::pair<std::size_t, std::size_t> range = this->cellRange(a_cell);
1566 for (std::size_t i = range.first; i < range.second; i++) {
1567 a_out.appendParticle(*this, i);
1568 }
1569 }
1570
1572
1573protected:
1577 void* m_buffer = nullptr;
1578
1582 std::size_t m_capacity = 0;
1583
1592 std::size_t m_bytes = 0;
1593
1597 std::size_t m_size = 0;
1598
1602 bool m_sorted = false;
1603
1607 std::array<void*, s_numColumns> m_colPtrs{};
1608
1612 std::vector<std::size_t> m_cellStart;
1613
1618
1622 RealVect m_sortDx = RealVect::Zero;
1623
1627 RealVect m_sortProbLo = RealVect::Zero;
1628
1639 std::size_t
1640 cellKey(const std::size_t a_index, const Box& a_box, const RealVect& a_dx, const RealVect& a_probLo) const noexcept
1641 {
1642 const IntVect loEnd = a_box.smallEnd();
1643 const IntVect boxSize = a_box.size();
1644 const RealVect x = this->position(a_index);
1645
1646 std::size_t lin = 0;
1647 std::size_t stride = 1;
1648 for (int d = 0; d < SpaceDim; d++) {
1649 int c = static_cast<int>(std::floor((x[d] - a_probLo[d]) / a_dx[d])) - loEnd[d];
1650 if (c < 0) {
1651 c = 0;
1652 }
1653 if (c >= boxSize[d]) {
1654 c = boxSize[d] - 1;
1655 }
1656 lin += static_cast<std::size_t>(c) * stride;
1657 stride *= static_cast<std::size_t>(boxSize[d]);
1658 }
1659
1660 return lin;
1661 }
1662
1674 bool
1675 checkCellSort(const Box& a_box, const RealVect& a_dx, const RealVect& a_probLo) const noexcept
1676 {
1677 if (!m_sorted) {
1678 return false;
1679 }
1680 if (m_cellStart.size() != static_cast<std::size_t>(a_box.numPts()) + 1) {
1681 return false;
1682 }
1683 if (m_cellStart.back() != m_size) {
1684 return false;
1685 }
1686
1687 for (std::size_t c = 0; c < this->numCells(); c++) {
1688 if (m_cellStart[c] > m_cellStart[c + 1]) {
1689 return false;
1690 }
1691
1692 for (std::size_t i = m_cellStart[c]; i < m_cellStart[c + 1]; i++) {
1693 if (this->cellKey(i, a_box, a_dx, a_probLo) != c) {
1694 return false;
1695 }
1696 }
1697 }
1698
1699 return true;
1700 }
1701
1707 static std::size_t
1708 alignUp(const std::size_t a_x) noexcept
1709 {
1710 return (a_x + (s_align - 1)) / s_align * s_align;
1711 }
1712
1717 void
1718 steal(ParticleSoA& a_o) noexcept
1719 {
1720 m_buffer = a_o.m_buffer;
1721 m_capacity = a_o.m_capacity;
1722 m_bytes = a_o.m_bytes;
1723 m_size = a_o.m_size;
1724 m_sorted = a_o.m_sorted;
1725 m_sortBox = a_o.m_sortBox;
1726 m_sortDx = a_o.m_sortDx;
1727 m_sortProbLo = a_o.m_sortProbLo;
1728 m_colPtrs = a_o.m_colPtrs;
1729 m_cellStart = std::move(a_o.m_cellStart);
1730 a_o.m_buffer = nullptr;
1731 a_o.m_capacity = 0;
1732 a_o.m_bytes = 0;
1733 a_o.m_size = 0;
1734 a_o.m_sorted = false;
1735 a_o.m_colPtrs = {};
1736 }
1737
1755 void
1756 growTo(const std::size_t a_needed)
1757 {
1758 if (a_needed <= m_capacity) {
1759 return;
1760 }
1761
1762 // Saturating geometric growth: 2 * m_capacity overflows std::size_t once m_capacity exceeds
1763 // SIZE_MAX/2, and reserve()'s "a_capacity <= m_capacity" guard would then silently no-op.
1764 const std::size_t doubled = (m_capacity == 0) ? 16
1765 : (m_capacity <= std::numeric_limits<std::size_t>::max() / 2
1766 ? 2 * m_capacity
1767 : std::numeric_limits<std::size_t>::max());
1768
1769 this->reserve(std::max(a_needed, doubled));
1770 }
1771
1775 void
1777 {
1778 if (m_size == m_capacity) {
1779 this->growTo(m_size + 1);
1780 }
1781 }
1782
1790 template <std::size_t... I>
1791 std::size_t
1792 computeOffsets(const std::size_t a_capacity,
1793 std::array<std::size_t, s_numColumns>& a_off,
1794 std::index_sequence<I...>) const noexcept
1795 {
1796 std::size_t running = 0;
1797 using expander = int[];
1798 (void)expander{0, (a_off[I] = running, running += alignUp(a_capacity * sizeof(ColumnType<I>)), 0)...};
1799 return running;
1800 }
1801
1807 template <std::size_t... I>
1808 void
1809 setColPtrs(const std::array<std::size_t, s_numColumns>& a_off, std::index_sequence<I...>) noexcept
1810 {
1811 using expander = int[];
1812 (void)expander{0, (m_colPtrs[I] = static_cast<char*>(m_buffer) + a_off[I], 0)...};
1813 }
1814
1821 template <std::size_t... I>
1822 void
1823 moveColumns(void* a_newBuf, const std::array<std::size_t, s_numColumns>& a_off, std::index_sequence<I...>) noexcept
1824 {
1825 using expander = int[];
1826 (void)expander{
1827 0,
1828 (std::memcpy(static_cast<char*>(a_newBuf) + a_off[I], m_colPtrs[I], m_size * sizeof(ColumnType<I>)), 0)...};
1829 }
1830
1838 template <std::size_t... I>
1839 void
1840 copyLiveColumnsTo(ParticleSoA& a_dst, std::index_sequence<I...>) const noexcept
1841 {
1842 using expander = int[];
1843 (void)expander{0, (std::memcpy(a_dst.m_colPtrs[I], m_colPtrs[I], m_size * sizeof(ColumnType<I>)), 0)...};
1844 }
1845
1855 template <std::size_t... I>
1856 void
1857 appendColumnsFrom(const ParticleSoA& a_other, const std::size_t a_at, std::index_sequence<I...>) noexcept
1858 {
1859 using expander = int[];
1860 (void)expander{0,
1861 (std::memcpy(static_cast<char*>(m_colPtrs[I]) + a_at * sizeof(ColumnType<I>),
1862 a_other.m_colPtrs[I],
1863 a_other.m_size * sizeof(ColumnType<I>)),
1864 0)...};
1865 }
1866
1876 template <std::size_t... I>
1877 void
1879 const std::size_t a_srcIdx,
1880 const std::size_t a_dstIdx,
1881 std::index_sequence<I...>) noexcept
1882 {
1883 using expander = int[];
1884 (void)expander{0,
1885 (this->template columnByIndex<I>()[a_dstIdx] = a_src.template columnByIndex<I>()[a_srcIdx], 0)...};
1886 }
1887
1892 void
1893 reallocate(const std::size_t a_capacity);
1894
1899 void
1900 permute(const std::vector<std::size_t>& a_dest);
1901
1909 template <std::size_t K>
1910 void
1911 scatterColumn(void* a_newBuf, const std::size_t a_off, const std::vector<std::size_t>& a_dest) noexcept
1912 {
1913 const ColumnType<K>* src = this->template columnByIndex<K>();
1914 ColumnType<K>* dst = reinterpret_cast<ColumnType<K>*>(static_cast<char*>(a_newBuf) + a_off);
1915 for (std::size_t i = 0; i < m_size; i++) {
1916 dst[a_dest[i]] = src[i];
1917 }
1918 }
1919
1927 template <std::size_t... I>
1928 void
1929 scatterColumns(void* a_newBuf,
1930 const std::array<std::size_t, s_numColumns>& a_off,
1931 const std::vector<std::size_t>& a_dest,
1932 std::index_sequence<I...>) noexcept
1933 {
1934 using expander = int[];
1935 (void)expander{0, ((void)this->template scatterColumn<I>(a_newBuf, a_off[I], a_dest), 0)...};
1936 }
1937
1943 template <std::size_t... J>
1944 void
1945 writePayload(const P& a_p, std::index_sequence<J...>) noexcept
1946 {
1947 constexpr auto cols = Traits::columns;
1948 using expander = int[];
1949 (void)expander{0,
1950 ((void)(this->template columnByIndex<s_payloadBegin + J>()[m_size] = a_p.*std::get<J>(cols)), 0)...};
1951 }
1952
1959 template <std::size_t... J>
1960 P
1961 gatherPayload(const std::size_t a_index, std::index_sequence<J...>) const
1962 {
1963 constexpr auto cols = Traits::columns;
1964 P p;
1965 using expander = int[];
1966 (void)expander{0,
1967 ((void)(p.*std::get<J>(cols) = this->template columnByIndex<s_payloadBegin + J>()[a_index]), 0)...};
1968 return p;
1969 }
1970
1976 template <std::size_t... I>
1977 void
1978 removeImpl(const std::size_t a_index, std::index_sequence<I...>) noexcept
1979 {
1980 using expander = int[];
1981 (void)expander{
1982 0,
1983 ((void)(this->template columnByIndex<I>()[a_index] = this->template columnByIndex<I>()[m_size - 1]), 0)...};
1984 }
1985
1992 template <std::size_t... I>
1993 void
1994 linearizeImpl(unsigned char* a_buf, const std::size_t a_index, std::index_sequence<I...>) const noexcept
1995 {
1996 using expander = int[];
1997 (void)expander{0, ((void)detail::pushBytes(a_buf, this->template columnByIndex<I>()[a_index]), 0)...};
1998 }
1999
2005 template <std::size_t... I>
2006 void
2007 delinearizeImpl(const unsigned char* a_buf, std::index_sequence<I...>) noexcept
2008 {
2009 using expander = int[];
2010 (void)expander{0, ((void)this->template pullColumn<I>(a_buf), 0)...};
2011 }
2012
2018 template <std::size_t K>
2019 void
2020 pullColumn(const unsigned char*& a_buf) noexcept
2021 {
2022 detail::pullBytes(a_buf, this->template columnByIndex<K>()[m_size]);
2023 }
2024
2030 template <std::size_t... J>
2031 static constexpr std::size_t
2032 h5PayloadSize(std::index_sequence<J...>) noexcept
2033 {
2034 return detail::sumSizes(sizeof(ColumnType<s_payloadBegin + J>)...);
2035 }
2036
2043 template <std::size_t... J>
2044 void
2045 h5LinearizePayload(unsigned char*& a_buf, const std::size_t a_index, std::index_sequence<J...>) const noexcept
2046 {
2047 using expander = int[];
2048 (void)expander{0,
2049 ((void)detail::pushBytes(a_buf, this->template columnByIndex<s_payloadBegin + J>()[a_index]), 0)...};
2050 }
2051
2057 template <std::size_t... J>
2058 void
2059 h5DelinearizePayload(const unsigned char*& a_buf, std::index_sequence<J...>) noexcept
2060 {
2061 using expander = int[];
2062 (void)expander{0,
2063 ((void)detail::pullBytes(a_buf, this->template columnByIndex<s_payloadBegin + J>()[m_size]), 0)...};
2064 }
2065
2071 template <std::size_t... I>
2072 std::size_t
2073 byteSpanImpl(std::index_sequence<I...>) const noexcept
2074 {
2075 std::size_t span = 0;
2076 using expander = int[];
2077 (void)expander{0,
2078 (span = (span > (static_cast<std::size_t>(static_cast<const char*>(m_colPtrs[I]) -
2079 static_cast<const char*>(m_buffer)) +
2080 m_size * sizeof(ColumnType<I>)))
2081 ? span
2082 : (static_cast<std::size_t>(static_cast<const char*>(m_colPtrs[I]) -
2083 static_cast<const char*>(m_buffer)) +
2084 m_size * sizeof(ColumnType<I>)),
2085 0)...};
2086 return span;
2087 }
2088};
2089
2090#include <CD_NamespaceFooter.H>
2091
2092#include <CD_ParticleSoAImplem.H>
2093
2094#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:2059
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:2045
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:1279
void append(const RealVect &a_position, const double a_weight)
Append one particle with a default-constructed payload.
Definition CD_ParticleSoA.H:955
const ParticleID & particleID(const std::size_t a_index) const noexcept
Const global id of particle i.
Definition CD_ParticleSoA.H:1266
ColumnType< K > * columnByIndex() noexcept
Typed base pointer of column K (low-level).
Definition CD_ParticleSoA.H:1056
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:1160
bool m_sorted
Whether m_cellStart is valid.
Definition CD_ParticleSoA.H:1602
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:1331
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:1978
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:1235
const auto * column() const noexcept
Const whole payload column selected by member pointer.
Definition CD_ParticleSoA.H:1092
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:1523
auto & get(const std::size_t a_index) noexcept
One particle's payload field selected by member pointer.
Definition CD_ParticleSoA.H:1105
void steal(ParticleSoA &a_o) noexcept
Steal another container's arena (move helper).
Definition CD_ParticleSoA.H:1718
std::size_t m_capacity
Capacity in particles.
Definition CD_ParticleSoA.H:1582
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:1188
GhostType & ghost(const std::size_t a_index) noexcept
Ghost designation of particle i (container-owned metadata).
Definition CD_ParticleSoA.H:1305
double & weight(const std::size_t a_index) noexcept
Weight of particle i.
Definition CD_ParticleSoA.H:1222
std::size_t numCells() const noexcept
Number of cells in the CSR sort (0 if not sorted).
Definition CD_ParticleSoA.H:1498
static constexpr std::size_t bytesPerParticle() noexcept
Byte count of one fully-linearized particle (all columns, for MPI).
Definition CD_ParticleSoA.H:1348
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:1809
const void * data() const noexcept
Raw arena pointer (column-major); a compact container's whole data span.
Definition CD_ParticleSoA.H:1413
static constexpr std::size_t h5PayloadSize(std::index_sequence< J... >) noexcept
Compile-time byte size of the HDF5 payload subset.
Definition CD_ParticleSoA.H:2032
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:1206
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: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
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:2073
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:1792
double * positionColumn(const int a_dir) noexcept
Raw position component column dir (double*, for SIMD kernels).
Definition CD_ParticleSoA.H:1137
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:1840
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:1857
~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:1559
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:1994
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:2020
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:1911
static constexpr std::size_t h5BytesPerParticle() noexcept
Bytes for one HDF5-linearized particle (position + weight + h5 payload subset).
Definition CD_ParticleSoA.H:1380
std::array< void *, s_numColumns > m_colPtrs
Cached column base pointers into m_buffer.
Definition CD_ParticleSoA.H:1607
P gather(const std::size_t a_index) const
Gather particle i's payload back into the AoS payload view.
Definition CD_ParticleSoA.H:1021
void * m_buffer
The single arena allocation.
Definition CD_ParticleSoA.H:1577
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:2007
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:1945
std::size_t m_bytes
Byte size of the arena at m_buffer (zero when m_buffer is null).
Definition CD_ParticleSoA.H:1592
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:1708
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:1929
const GhostType & ghost(const std::size_t a_index) const noexcept
Const ghost designation of particle i.
Definition CD_ParticleSoA.H:1318
ParticleID & particleID(const std::size_t a_index) noexcept
Global id of particle i (container-owned metadata).
Definition CD_ParticleSoA.H:1253
const ColumnType< K > * columnByIndex() const noexcept
Const typed base pointer of column K (low-level).
Definition CD_ParticleSoA.H:1068
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:1539
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:1612
void catenate(ParticleSoA &a_other)
Move every particle of another container into this one, leaving a_other empty (catenate).
Definition CD_ParticleSoA.H:1002
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:1640
RealVect m_sortDx
Grid spacing the CSR mapping was built against (meaningful only when m_sorted).
Definition CD_ParticleSoA.H:1622
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:1033
static constexpr ParticleID s_invalidID
Sentinel for an unassigned/invalid global particle id.
Definition CD_ParticleSoA.H:1245
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:1423
void growTo(const std::size_t a_needed)
Grow the arena to hold at least a_needed particles, geometrically.
Definition CD_ParticleSoA.H:1756
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:1776
RealVect m_sortProbLo
Lower domain corner the CSR mapping was built against (meaningful only when m_sorted).
Definition CD_ParticleSoA.H:1627
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:1961
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:1878
auto * column() noexcept
Whole payload column selected by member pointer (raw pointer, vectorizable).
Definition CD_ParticleSoA.H:1080
const auto & get(const std::size_t a_index) const noexcept
Const overload of get<&P::field>(i).
Definition CD_ParticleSoA.H:1120
Box m_sortBox
Patch box the CSR mapping in m_cellStart was built against (meaningful only when m_sorted).
Definition CD_ParticleSoA.H:1617
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:1488
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:1150
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:1823
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:1433
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).
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
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:1675
bool isSorted() const noexcept
Whether the container is currently cell-sorted (false after append/remove).
Definition CD_ParticleSoA.H:1473
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:1170
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:1509
const RankID & rankID(const std::size_t a_index) const noexcept
Const owning rank of particle i.
Definition CD_ParticleSoA.H:1292
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