DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
ArrayEigenMatrix.hpp
Go to the documentation of this file.
1#pragma once
2/// @file ArrayEigenMatrix.hpp
3/// @brief Eigen-matrix array: each row is an Eigen::Map<Matrix> over contiguous real storage.
4/// @par Unit Test Coverage (test_ArrayDerived.cpp, MPI np=1,2,4)
5/// - Static sizes (ArrayEigenMatrix<3,4>): Resize, Size, MatRowSize, MatColSize, operator[]
6/// - Dynamic sizes (ArrayEigenMatrix<DynamicSize,DynamicSize>): Resize with runtime dims
7/// - NonUniform row dimensions: ResizeMat per row, Compress, verify
8/// - Ghost communication via ArrayEigenMatrixPair
9/// @par Not Yet Tested
10/// - GetDerivedArraySignature, SignatureIsCompatible
11/// - WriteSerializer / ReadSerializer override
12/// - Device views
13
14#include "../ArrayTransformer.hpp"
16#include "DNDS/Defines.hpp"
18
19namespace DNDS
20{
21
22 /**
23 * @brief `ParArray<real>` whose `operator[]` returns an `Eigen::Map<Matrix<real, Ni, Nj>>`.
24 *
25 * @details Each row stores an `Ni x Nj` matrix contiguously (column-major,
26 * matching Eigen's default). The row count in the underlying @ref DNDS::ParArray "ParArray"
27 * equals `Ni * Nj`. Used for per-cell Jacobians, gradient matrices, and
28 * (via @ref DNDS::ArrayDof "ArrayDof") solver state containers.
29 *
30 * Supports three configurations for each of the two matrix dimensions:
31 * - compile-time fixed (`Ni >= 0`);
32 * - runtime uniform (@ref DynamicSize + a `_max`);
33 * - per-row variable (@ref NonUniformSize + a `_max`, which yields a
34 * `TABLE_StaticMax` / `TABLE_Max` storage layout).
35 *
36 * The variable-row case carries an extra per-row-sizes vector
37 * `_mat_nRows`; all the other layouts have no extra data beyond @ref DNDS::ParArray "ParArray".
38 *
39 * @tparam _mat_ni Row dimension of the stored matrix.
40 * @tparam _mat_nj Column dimension.
41 * @tparam _mat_ni_max Max row dimension (used when variable).
42 * @tparam _mat_nj_max Max column dimension.
43 */
44 template <rowsize _mat_ni = 1, rowsize _mat_nj = 1,
45 rowsize _mat_ni_max = _mat_ni, rowsize _mat_nj_max = _mat_nj, rowsize _align = NoAlign>
46 class ArrayEigenMatrix : public ParArray<real,
47 __OneMatGetRowSize<_mat_ni, _mat_nj>(),
48 __OneMatGetRowSize<_mat_ni_max, _mat_nj_max>(),
49 _align>
50 {
51 public:
58 _align>;
59 using t_base::t_base;
60 // using t_pRowSizes = typename t_base::t_pRowSizes;
62
64 using t_EigenMap = Eigen::Map<t_EigenMatrix, Eigen::Unaligned>; // default no buffer align and stride
65 using t_EigenMap_const = Eigen::Map<const t_EigenMatrix, Eigen::Unaligned>; // default no buffer align and stride
66
68
69 private:
70 using t_base::Resize;
72 using t_base::operator();
73 t_pRowSizes _mat_nRows; //! extra data
74 rowsize _mat_nRow_dynamic = 0; //! extra data
75
76 public:
77 size_t FullSizeBytes() const
78 {
79 size_t b = this->t_base::FullSizeBytes();
80 if (_mat_nRows)
81 b += _mat_nRows->size() * sizeof(rowsize);
82 return b;
83 }
84
85 // default copy
86 ArrayEigenMatrix(const t_self &R) = default;
87 t_self &operator=(const t_self &R) = default;
88 // operator= handled automatically
89
90 void clone(const t_self &R)
91 {
92 this->operator=(R);
93 }
94
96 {
97 if constexpr (_mat_ni >= 0)
99 if constexpr (_mat_nj >= 0)
101 if constexpr (_mat_ni_max >= 0)
103 if constexpr (_mat_nj_max >= 0)
105
106 if constexpr (_mat_ni == NonUniformSize)
107 _mat_nRows = std::make_shared<host_device_vector<rowsize>>(nSize, nSizeRowDynamic);
108 else if constexpr (_mat_ni == DynamicSize)
109 _mat_nRow_dynamic = nSizeRowDynamic;
110
112 }
113
115 {
116 if constexpr (_mat_ni >= 0)
117 return _mat_ni;
118 if constexpr (_mat_ni == NonUniformSize)
119 return _mat_nRows->at(iMat);
120 if constexpr (_mat_ni == DynamicSize)
121 return _mat_nRow_dynamic;
122 return UnInitRowsize; // invalid branch
123 }
124
126 {
127 if constexpr (_mat_nj >= 0)
128 return _mat_nj;
129 if constexpr (_mat_nj == NonUniformSize)
130 return this->t_base::RowSize(iMat) / this->MatRowSize(iMat);
131 if constexpr (_mat_nj == DynamicSize)
132 return this->t_base::RowSize(iMat) / this->MatRowSize(iMat);
133 return UnInitRowsize; // invalid branch
134 }
135
140
142 {
143 if constexpr (_mat_ni == NonUniformSize)
144 this->t_base::ResizeRow(iMat, nSizeRow * nSizeCol), (*_mat_nRows)[iMat] = nSizeRow;
145 else if constexpr (_mat_ni == DynamicSize)
146 DNDS_check_throw_info(false, "Invalid call");
147 }
148
149 std::conditional_t<_mat_ni == 1 && _mat_nj == 1,
150 real &, void>
152 {
153 if constexpr (_mat_ni == 1 && _mat_nj == 1)
154 return *t_base::operator[](iRow);
155 }
156
157 std::conditional_t<_mat_ni == 1 && _mat_nj == 1,
158 real, void>
159 operator()(index iRow) const
160 {
161 if constexpr (_mat_ni == 1 && _mat_nj == 1)
162 return *t_base::operator[](iRow);
163 }
164
165 std::conditional_t<_mat_ni == 1 || _mat_nj == 1,
166 real &, void>
168 {
169 if constexpr (_mat_ni == 1 || _mat_nj == 1)
170 return t_base::operator()(iRow, j);
171 }
172
173 std::conditional_t<_mat_ni == 1 || _mat_nj == 1,
174 real, void>
176 {
177 if constexpr (_mat_ni == 1 || _mat_nj == 1)
178 return t_base::operator()(iRow, j);
179 }
180
183 {
185 if constexpr (_mat_ni == NonUniformSize)
186 c_nRow = (*_mat_nRows)[i];
187 else if constexpr (_mat_ni == DynamicSize)
188 c_nRow = _mat_nRow_dynamic;
189 else
190 c_nRow = _mat_ni;
191 // std::cout << c_nRow << " " << t_base::RowSize(i) << std::endl;
192
193 return t_EigenMap(t_base::operator[](i), c_nRow, t_base::RowSize(i) / c_nRow); // need static dispatch?
194 }
195
198 {
200 if constexpr (_mat_ni == NonUniformSize)
201 c_nRow = (*_mat_nRows)[i];
202 else if constexpr (_mat_ni == DynamicSize)
203 c_nRow = _mat_nRow_dynamic;
204 else
205 c_nRow = _mat_ni;
206 // std::cout << c_nRow << " " << t_base::RowSize(i) << std::endl;
207
208 return t_EigenMap_const(t_base::operator[](i), c_nRow, t_base::RowSize(i) / c_nRow); // need static dispatch?
209 }
210
211 static std::string GetDerivedArraySignature()
212 {
213 std::array<char, 1024> buf;
214 std::sprintf(buf.data(), "ArrayEigenMatrix__%d_%d_%d_%d", _mat_ni, _mat_nj, _mat_ni_max, _mat_nj_max);
215 return buf.data();
216 }
217
218 static std::tuple<int, int, int, int> GetDerivedArraySignatureInts(const std::string &v)
219 { // TODO: check here!
220 auto strings = splitSStringClean(v, '_');
221 DNDS_check_throw(strings.size() == 5 || strings.size() == 6);
222 auto sz = strings.size();
223 return std::make_tuple(std::stoi(strings[sz - 4]), std::stoi(strings[sz - 3]), std::stoi(strings[sz - 2]), std::stoi(strings[sz - 1]));
224 }
225
226 bool SignatureIsCompatible(const std::string &v)
227 { // TODO: check here!
229 // std::cout << fmt::format(" {} {} {} {}", v_mat_ni, v_mat_nj, v_mat_ni_max, v_mat_nj_max) << std::endl;
230 // std::cout << fmt::format(" {} {} {} {}", _mat_ni, _mat_nj, _mat_ni_max, _mat_nj_max) << std::endl;
231 if (v_mat_ni >= 0 && _mat_ni >= 0 && v_mat_ni != _mat_ni)
232 return false;
233 if (v_mat_nj >= 0 && _mat_nj >= 0 && v_mat_nj != _mat_nj)
234 return false;
235 if (v_mat_ni_max >= 0 && _mat_ni_max >= 0 && v_mat_ni_max != _mat_ni_max)
236 return false;
237 if (v_mat_nj_max >= 0 && _mat_nj_max >= 0 && v_mat_nj_max != _mat_nj_max)
238 return false;
239 return true;
240 }
241
242 /**
243 * @brief
244 *
245 * @param serializerP
246 * @param name
247 * @warning need to take care of createGlobalMapping if resized
248 */
250 {
251 auto cwd = serializerP->GetCurrentPath();
252 serializerP->CreatePath(name);
253 serializerP->GoToPath(name);
254
255 this->t_base::WriteSerializer(serializerP, "array", offset);
256 serializerP->WriteString("DerivedType", GetDerivedArraySignature());
257 serializerP->WriteInt("mat_nRow_dynamic", _mat_nRow_dynamic);
258 if constexpr (_mat_ni == NonUniformSize)
259 serializerP->WriteSharedRowsizeVector("mat_nRows", _mat_nRows, offset);
260
261 serializerP->GoToPath(cwd);
262 }
263
265 {
266 auto cwd = serializerP->GetCurrentPath();
267 // serializerP->CreatePath(name); //!remember no create path
268 serializerP->GoToPath(name);
269
270 this->t_base::ReadSerializer(serializerP, "array", offset);
271
272 std::string readDerivedType;
273 serializerP->ReadString("DerivedType", readDerivedType);
276 readDerivedType + ", i am: " + this->GetDerivedArraySignature() + fmt::format(" {} {} {} {}", v_mat_ni, v_mat_nj, v_mat_ni_max, v_mat_nj_max));
277 serializerP->ReadInt("mat_nRow_dynamic", _mat_nRow_dynamic);
278 if (_mat_ni == DynamicSize && v_mat_ni >= 0)
279 _mat_nRow_dynamic = v_mat_ni;
280 if (v_mat_ni == NonUniformSize) // TODO: complete here!
281 {
282
283 if constexpr (_mat_ni == NonUniformSize)
284 serializerP->ReadSharedRowsizeVector("mat_nRows", _mat_nRows, offset); // TODO: multiple write to offset, check?
285 else
286 {
288 serializerP->ReadSharedRowsizeVector("mat_nRows", v_mat_nRows, offset);
289 int c_mat_nRow_dynamic = v_mat_nRows->size() ? 0 : v_mat_nRows->at(0);
290 for (auto i = 0; i < v_mat_nRows->size(); ++i)
292 _mat_nRow_dynamic = c_mat_nRow_dynamic;
293 }
294 }
295 else // TODO: complete here!
296 {
297 if constexpr (_mat_ni == NonUniformSize)
298 _mat_nRows = std::make_shared<host_device_vector<rowsize>>(this->Size(), v_mat_ni >= 0 ? v_mat_ni : _mat_nRow_dynamic);
299 }
300
301 serializerP->GoToPath(cwd);
302 }
303
304 struct ReadSerializerMetaResult : t_base::ReadSerializerMetaResult
305 {
306 std::string derived_type;
308 };
309
311 {
312 auto cwd = serializerP->GetCurrentPath();
313 serializerP->GoToPath(name);
314
318 serializerP->ReadString("DerivedType", result.derived_type);
319 serializerP->ReadInt("mat_nRow_dynamic", result.mat_nRow_dynamic);
320
321 serializerP->GoToPath(cwd);
322 return result;
323 }
324
325 template <DeviceBackend B>
327 template <DeviceBackend B>
329
330 template <DeviceBackend B>
332 {
333 auto base_view = t_base::template deviceView<B>();
335 // do more delicate dispatching for extensions?
336 _mat_nRows ? (B == DeviceBackend::Host ? _mat_nRows->data() : _mat_nRows->dataDevice())
337 : nullptr,
338 _mat_nRow_dynamic);
339 }
340
341 template <DeviceBackend B>
342 auto deviceView() const
343 {
344 auto base_view = t_base::template deviceView<B>();
346 // do more delicate dispatching for extensions?
347 _mat_nRows ? (B == DeviceBackend::Host ? _mat_nRows->data() : _mat_nRows->dataDevice())
348 : nullptr,
349 _mat_nRow_dynamic);
350 }
351
352 using t_base::to_host; // we only copy primary data back (no structure modification allowed from device)
353
355 {
356 this->t_base::to_device(backend);
357 if (_mat_nRows)
358 _mat_nRows->to_device(backend);
359 }
360
361 /// @brief Element iterator for ArrayEigenMatrix, yielding Eigen::Map<Matrix> per row.
362 template <DeviceBackend B, bool is_const = false>
363 class iterator : public ArrayIteratorBase<iterator<B>>
364 {
365 public:
366 using view_type = std::conditional_t<is_const, t_deviceViewConst<B>, t_deviceView<B>>;
370
371 using value_type = typename view_type::t_EigenView;
372 using reference = typename view_type::t_EigenView;
373 static_assert(std::is_signed_v<typename iterator::difference_type>);
374
375 protected:
377
378 public:
379 DNDS_DEVICE_CALLABLE auto getView() const { return view; }
380
382
387
388 DNDS_DEVICE_CALLABLE reference operator*() { return view.MatView(this->iRow); }
389
390 DNDS_DEVICE_CALLABLE reference operator*() const { return const_cast<iterator *>(this)->view.MatView(this->iRow); }
391
392 // DNDS_DEVICE_CALLABLE reference operator[](index n) { return view.MatView(this->iRow + n); }
393
394 // DNDS_DEVICE_CALLABLE reference operator[](index n) const { return const_cast<iterator *>(this)->view.MatView(this->iRow + n); }
395 std::string to_string()
396 {
397 return fmt::format("ArrayEigenMatrix::iterator<> iRow[{}] Size[{}]", this->iRow, this->view.Size());
398 }
399 };
400
401 template <DeviceBackend B>
403 {
404 return iterator<B>{deviceView<B>(), 0};
405 }
406
407 template <DeviceBackend B>
409 {
410 return iterator<B>{deviceView<B>(), this->Size()};
411 }
412 };
413}
Device-callable view for ArrayEigenMatrix. operator[] returns an Eigen::Map<Matrix<real,...
Core type aliases, constants, and metaprogramming utilities for the DNDS framework.
#define DNDS_DEVICE_CALLABLE
Definition Defines.hpp:76
#define DNDS_DEVICE_TRIVIAL_COPY_DEFINE_NO_EMPTY_CTOR(T, T_Self)
Definition Defines.hpp:91
Device memory abstraction layer with backend-specific storage and factory creation.
#define DNDS_check_throw_info(expr, info)
Same as DNDS_check_throw but attaches a user-supplied info message to the thrown std::runtime_error.
Definition Errors.hpp:96
#define DNDS_HD_assert(cond)
Host-only expansion of DNDS_HD_assert (equivalent to DNDS_assert).
Definition Errors.hpp:189
#define DNDS_check_throw(expr)
Runtime check active in both debug and release builds. Throws std::runtime_error if expr evaluates to...
Definition Errors.hpp:89
Non-owning device-callable view of an Array, specialised per DeviceBackend.
Device-callable view onto ArrayEigenMatrix rows.
Element iterator for ArrayEigenMatrix, yielding Eigen::Map<Matrix> per row.
DNDS_DEVICE_CALLABLE auto getView() const
std::conditional_t< is_const, t_deviceViewConst< B >, t_deviceView< B > > view_type
DNDS_DEVICE_CALLABLE reference operator*() const
DNDS_DEVICE_CALLABLE reference operator*()
ParArray<real> whose operator[] returns an Eigen::Map<Matrix<real, Ni, Nj>>.
std::conditional_t< _mat_ni==1||_mat_nj==1, real &, void > operator()(index iRow, rowsize j)
std::conditional_t< _mat_ni==1 &&_mat_nj==1, real &, void > operator()(index iRow)
ArrayEigenMatrixDeviceView< B, real, _mat_ni, _mat_nj, _mat_ni_max, _mat_nj_max, _align > t_deviceView
void WriteSerializer(Serializer::SerializerBaseSSP serializerP, const std::string &name, Serializer::ArrayGlobalOffset offset)
void ResizeRow(index iMat, rowsize nSizeRow, rowsize nSizeCol)
rowsize MatColSize(index iMat=0) const
Eigen::Matrix< real, RowSize_To_EigenSize(_mat_ni), RowSize_To_EigenSize(_mat_nj)> t_EigenMatrix
std::conditional_t< _mat_ni==1||_mat_nj==1, real, void > operator()(index iRow, rowsize j) const
static std::string GetDerivedArraySignature()
ArrayEigenMatrix(const t_self &R)=default
void ResizeMat(index iMat, rowsize nSizeRow, rowsize nSizeCol)
t_EigenMap operator[](index i)
size_t FullSizeBytes() const
extra data
void to_device(DeviceBackend backend)
Eigen::Map< t_EigenMatrix, Eigen::Unaligned > t_EigenMap
bool SignatureIsCompatible(const std::string &v)
void Resize(index nSize, rowsize nSizeRowDynamic, rowsize nSizeColDynamic)
static std::tuple< int, int, int, int > GetDerivedArraySignatureInts(const std::string &v)
void clone(const t_self &R)
t_EigenMap_const operator[](index i) const
rowsize MatRowSize(index iMat=0) const
t_self & operator=(const t_self &R)=default
std::conditional_t< _mat_ni==1 &&_mat_nj==1, real, void > operator()(index iRow) const
Eigen::Map< const t_EigenMatrix, Eigen::Unaligned > t_EigenMap_const
static const rowsize _row_size_max
void ReadSerializer(Serializer::SerializerBaseSSP serializerP, const std::string &name, Serializer::ArrayGlobalOffset &offset)
ReadSerializerMetaResult ReadSerializerMeta(Serializer::SerializerBaseSSP serializerP, const std::string &name)
static const rowsize _row_size
CRTP base for row-granularity iterators over an Array / ArrayView.
const T & at(index iRow, rowsize iCol) const
Bounds-checked element read (not device-callable because CSR decompressed uses std::vector::at which ...
DNDS_DEVICE_CALLABLE T * data()
Raw pointer to the start of the flat data buffer.
void to_device(DeviceBackend backend=DeviceBackend::Host)
Mirror the flat/structural buffers to a target device (e.g. CUDA).
Definition Array.hpp:1213
void Resize(index nSize, rowsize nRow_size_dynamic)
Resize the array, setting a uniform or maximum row width.
Definition Array.hpp:395
size_t FullSizeBytes() const
Total footprint in bytes including structural arrays.
Definition Array.hpp:735
rowsize RowSize() const
Uniform row width for fixed layouts (no row index needed).
Definition Array.hpp:176
void to_host()
Mirror the flat/structural buffers back to host memory.
Definition Array.hpp:1200
ReadSerializerMetaResult ReadSerializerMeta(Serializer::SerializerBaseSSP serializerP, const std::string &name)
Reads only metadata from a serialized array without reading data.
Definition Array.hpp:1104
void ResizeRow(index iRow, rowsize nRowSize)
Change the width of a single row.
Definition Array.hpp:504
index Size() const
Number of rows currently stored. O(1).
Definition Array.hpp:171
MPI-aware Array: adds a communicator, rank, and global index mapping.
void WriteSerializer(Serializer::SerializerBaseSSP serializerP, const std::string &name, Serializer::ArrayGlobalOffset offset)
Serialize (write) the parallel array with MPI-aware metadata.
void ReadSerializer(Serializer::SerializerBaseSSP serializerP, const std::string &name, Serializer::ArrayGlobalOffset &offset)
Deserialize (read) the parallel array with MPI-aware metadata.
Describes one rank's window into a globally-distributed dataset.
ssp< SerializerBase > SerializerBaseSSP
the host side operators are provided as implemented
DeviceBackend
Enumerates the backends a DeviceStorage / Array can live on.
@ Host
Plain CPU memory.
DNDS_CONSTANT const rowsize NoAlign
Alignment flag: no padding applied to rows (the only currently-supported value).
Definition Defines.hpp:282
constexpr int RowSize_To_EigenSize(rowsize rs)
Convert a rowsize constant to the corresponding Eigen compile-time size. Fixed >= 0 -> the value; Dyn...
Definition Defines.hpp:286
int32_t rowsize
Row-width / per-row element-count type (signed 32-bit).
Definition Defines.hpp:109
DNDS_CONSTANT const rowsize DynamicSize
Template parameter flag: "row width is set at runtime but uniform".
Definition Defines.hpp:277
DNDS_CONSTANT const rowsize NonUniformSize
Template parameter flag: "each row has an independent width".
Definition Defines.hpp:279
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
Definition Defines.hpp:107
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
Definition Defines.hpp:105
std::vector< std::string > splitSStringClean(const std::string &str, char delim)
Definition Defines.hpp:790
DNDS_CONSTANT const rowsize UnInitRowsize
Sentinel "not initialised" rowsize value (= INT32_MIN).
Definition Defines.hpp:179
Result type for ReadSerializerMeta.
Definition Array.hpp:1084
Eigen::Matrix< real, 5, 1 > v
tVec b(NCells)
auto result