DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
ArrayEigenUniMatrixBatch.hpp
Go to the documentation of this file.
1#pragma once
2/// @file ArrayEigenUniMatrixBatch.hpp
3/// @brief Batch of uniform-sized Eigen matrices per row, with variable batch count.
4/// @par Unit Test Coverage (test_ArrayDerived.cpp, MPI np=1,2,4)
5/// - Static sizes (ArrayEigenUniMatrixBatch<2,3>) and dynamic sizes
6/// - Resize, ResizeBatch, BatchSize, Rows, Cols, MSize, Compress
7/// - Element access: operator()(i,j) returning Eigen::Map
8/// @par Not Yet Tested
9/// - GetDerivedArraySignature, WriteSerializer / ReadSerializer
10/// - Device views
11
12#include "../ArrayTransformer.hpp"
13#include "DNDS/ArrayBasic.hpp"
15
16namespace DNDS
17{
18 /**
19 * @brief CSR array whose rows store a *batch* of identically-sized Eigen matrices.
20 *
21 * @details Each row holds `BatchSize(i)` matrices of shape `_n_row x _n_col`,
22 * contiguous in memory. The raw CSR row width is `BatchSize(i) * _n_row * _n_col`,
23 * but the public API exposes batched semantics: @ref BatchSize reports the matrix
24 * count, `operator()(i, j)` returns the `j`-th matrix in row `i`'s batch.
25 *
26 * Used heavily by @ref FiniteVolume and @ref VariationalReconstruction to store
27 * per-quadrature-point Jacobians and basis-function coefficients: each cell
28 * contributes one row, each quadrature point contributes one matrix.
29 *
30 * @tparam _n_row Row count of each stored matrix (compile time or `Eigen::Dynamic`).
31 * @tparam _n_col Column count of each stored matrix.
32 */
33 template <int _n_row, int _n_col>
34 class ArrayEigenUniMatrixBatch : public ParArray<real, NonUniformSize, NonUniformSize, NoAlign> // use CSR array
35 {
36 static_assert(_n_row >= 0 || _n_row == Eigen::Dynamic, "invalid _n_row");
37 static_assert(_n_col >= 0 || _n_col == Eigen::Dynamic, "invalid _n_col");
38
39 public:
42 using t_base::t_base;
43
44 using t_EigenMatrix = Eigen::Matrix<real, _n_row, _n_col,
45 Eigen::AutoAlign |
46 ((_n_row == 1 && _n_col != 1) ? Eigen ::RowMajor : (_n_col == 1 && _n_row != 1) ? Eigen ::ColMajor // ColMajor except for row-vector
47 : Eigen ::ColMajor)>;
48 using t_EigenMap = Eigen::Map<t_EigenMatrix, Eigen::Unaligned>; // default no buffer align and stride
49 using t_EigenMap_const = Eigen::Map<const t_EigenMatrix, Eigen::Unaligned>; // default no buffer align and stride
50
51 private:
52 int _row_dynamic = _n_row > 0 ? _n_row : 0;
53 int _col_dynamic = _n_col > 0 ? _n_col : 0;
54 int _m_size = this->Rows() * this->Cols(); //! extra data!
55
56 private:
57 using t_base::Resize;
58 using t_base::ResizeRow; // privatize basic resizing
59 using t_base::operator();
60 using t_base::RowSize;
61 // void Resize(index, rowsize) = delete;
62 // void ResizeRow(index iRow, rowsize nRowSize) = delete;
63 public:
64 // default copy
66 t_self &operator=(const t_self &R) = default;
67 // operator= handled automatically
68
69 void clone(const t_self &R)
70 {
71 this->operator=(R);
72 }
73
74 /**
75 * @brief resizes all matrices to be used;
76 * -1 means no change
77 * @param r
78 * @param c
79 */
80 void ResizeMatrix(int r = -1, int c = -1)
81 {
82 if constexpr (_n_row >= 0)
83 DNDS_assert(r == -1 || r == _n_row);
84 if constexpr (_n_col >= 0)
85 DNDS_assert(c == -1 || c == _n_col);
86 if (r >= 0)
87 _row_dynamic = r;
88 if (c >= 0)
89 _col_dynamic = c;
90 // TODO: multiplication overflow detect
91 _m_size = this->Rows() * this->Cols();
92 this->t_base::Resize(0);
93 }
94
95 void Resize(index n_size, int r, int c)
96 {
97 this->ResizeMatrix(r, c);
98 this->t_base::Resize(n_size);
99 }
100
102 {
103 if constexpr (_n_row > 0 && _n_col > 0)
104 this->Resize(n_size, -1, -1);
105 else
106 DNDS_assert_info(false, "invalid call");
107 }
108
109 template <class TFRowSize>
110 void Resize(index n_size, int r, int c, TFRowSize &&rsf)
111 {
112 this->ResizeMatrix(r, c);
113 this->t_base::Resize(n_size, [&](index i)
114 { return rsf(i) * this->MSize(); });
115 }
116
117 public:
118 auto view()
119 {
121 t_base::view(), _row_dynamic, _col_dynamic, _m_size};
122 }
123
124 [[nodiscard]] int Rows() const { return _n_row > 0 ? _n_row : _row_dynamic; }
125 [[nodiscard]] int Cols() const { return _n_col > 0 ? _n_col : _col_dynamic; }
126 [[nodiscard]] int MSize() const
127 {
128 if constexpr (_n_row >= 0 && _n_col >= 0)
129 return _n_row * _n_col;
130 else
131 return _m_size;
132 }
133
135 {
136 this->t_base::ResizeRow(i, b_size * MSize());
137 }
138
140 {
141 this->t_base::ResizeRow(i, b_size * MSize());
142 }
143
145 {
146 return this->RowSize(i);
147 }
148
150 {
152 DNDS_assert(MSize() != 0 && row_size_c % MSize() == 0);
153 return row_size_c / MSize();
154 }
155
157 {
158 DNDS_assert(j >= 0 && j < this->RowSize(i));
159 // if constexpr (_n_row >= 0 && _n_col >= 0)
160 return {this->t_base::operator[](i) + MSize() * j, Rows(), Cols()};
161 }
162
164 {
165 DNDS_assert(j >= 0 && j < this->RowSize(i));
166 // if constexpr (_n_row >= 0 && _n_col >= 0)
167 return {this->t_base::operator[](i) + MSize() * j, Rows(), Cols()};
168 }
169
170 std::vector<t_EigenMap> operator[](index i)
171 {
172 std::vector<t_EigenMap> ret;
173 ret.reserve(this->BatchSize(i));
174 for (rowsize j = 0; j < this->BatchSize(i); j++)
175 ret.emplace_back(this->t_base::operator[](i) + MSize() * j, Rows(), Cols());
176 return ret;
177 }
178
179 // TODO: getting sub matrix ?
180
181 static std::string GetDerivedArraySignature()
182 {
183 return "ArrayEigenUniMatrixBatch__" + std::to_string(_n_row) +
184 "_" + std::to_string(_n_col);
185 }
186
188 {
189 auto cwd = serializerP->GetCurrentPath();
190 serializerP->CreatePath(name);
191 serializerP->GoToPath(name);
192
193 serializerP->WriteString("DerivedType", GetDerivedArraySignature());
194 serializerP->WriteInt("row_dynamic", _row_dynamic);
195 serializerP->WriteInt("col_dynamic", _col_dynamic);
196 serializerP->WriteInt("m_size", _m_size);
197 this->t_base::WriteSerializer(serializerP, "array", offset);
198
199 serializerP->GoToPath(cwd);
200 }
201
203 {
204 auto cwd = serializerP->GetCurrentPath();
205 // serializerP->CreatePath(name); //!remember no create path
206 serializerP->GoToPath(name);
207
208 std::string readDerivedType;
209 serializerP->ReadString("DerivedType", readDerivedType);
211 serializerP->ReadInt("row_dynamic", _row_dynamic);
212 serializerP->ReadInt("col_dynamic", _col_dynamic);
213 serializerP->ReadInt("m_size", _m_size);
214 this->t_base::ReadSerializer(serializerP, "array", offset);
215
216 serializerP->GoToPath(cwd);
217 }
218
226
228 {
229 auto cwd = serializerP->GetCurrentPath();
230 serializerP->GoToPath(name);
231
235 serializerP->ReadString("DerivedType", result.derived_type);
236 serializerP->ReadInt("row_dynamic", result.row_dynamic);
237 serializerP->ReadInt("col_dynamic", result.col_dynamic);
238 serializerP->ReadInt("m_size", result.m_size);
239
240 serializerP->GoToPath(cwd);
241 return result;
242 }
243
244 template <DeviceBackend B>
246
247 template <DeviceBackend B>
249
250 template <DeviceBackend B>
252 {
253 return t_deviceView<B>{t_base::template deviceView<B>(), _row_dynamic, _col_dynamic, _m_size};
254 }
255
256 template <DeviceBackend B>
257 auto deviceView() const
258 {
259 return t_deviceView<B>{t_base::template deviceView<B>(), _row_dynamic, _col_dynamic, _m_size};
260 }
261
262 using t_base::to_device;
263 using t_base::to_host;
264
265 /// @brief Non-owning view of one row's matrix batch in ArrayEigenUniMatrixBatch.
266 template <DeviceBackend B>
268 {
269 protected:
270 t_deviceView<B> view; // todo: optimize so that no need to store whole arrayview?
273
274 public:
279
281 {
282 DNDS_assert(j >= 0 && j < row_size);
283 return view.operator()(iRow, j);
284 }
285
287 {
288 DNDS_assert(j >= 0 && j < row_size);
289 return view.operator()(iRow, j);
290 }
291 };
292
293 /// @brief Element iterator for ArrayEigenUniMatrixBatch, yielding UniMatrixRowView per row.
294 template <DeviceBackend B>
295 class iterator : public ArrayIteratorBase<iterator<B>>
296 {
297 public:
302 using iterator_category = std::random_access_iterator_tag;
303
304 protected:
306
307 public:
308 auto getView() const { return view; }
314
316 {
317 return {view, this->iRow, this->RowSize(this->iRow)};
318 }
319 };
320
321 template <DeviceBackend B>
323 {
324 return {deviceView<B>(), 0};
325 }
326
327 template <DeviceBackend B>
329 {
330 return {deviceView<B>(), this->Size()};
331 }
332 };
333}
Array layout descriptors, non-owning views, row views, and iterator base.
Device-callable view for ArrayEigenUniMatrixBatch (rows of identically-shaped matrix batches,...
#define DNDS_DEVICE_CALLABLE
Definition Defines.hpp:76
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
Definition Errors.hpp:113
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Definition Errors.hpp:108
Non-owning device-callable view of an Array, specialised per DeviceBackend.
Device-callable view onto ArrayEigenUniMatrixBatch rows.
Non-owning view of one row's matrix batch in ArrayEigenUniMatrixBatch.
DNDS_DEVICE_CALLABLE UniMatrixRowView(const t_deviceView< B > &n_view, index n_iRow, rowsize n_row_size)
DNDS_DEVICE_CALLABLE t_EigenMap_const operator[](rowsize j) const
DNDS_DEVICE_CALLABLE t_EigenMap operator[](rowsize j)
Element iterator for ArrayEigenUniMatrixBatch, yielding UniMatrixRowView per row.
DNDS_DEVICE_CALLABLE ~iterator()=default
DNDS_DEVICE_CALLABLE iterator(const view_type &n_view, index n_iRow)
DNDS_DEVICE_CALLABLE iterator(const iterator &)=default
CSR array whose rows store a batch of identically-sized Eigen matrices.
Eigen::Map< const t_EigenMatrix, Eigen::Unaligned > t_EigenMap_const
void Resize(index n_size, int r, int c)
std::vector< t_EigenMap > operator[](index i)
t_EigenMap_const operator()(index i, rowsize j) const
ArrayEigenUniMatrixBatchDeviceView< B, real, _n_row, _n_col > t_deviceView
Eigen::Map< t_EigenMatrix, Eigen::Unaligned > t_EigenMap
void ResizeRow(index i, rowsize b_size)
t_EigenMap operator()(index i, rowsize j)
void ResizeMatrix(int r=-1, int c=-1)
resizes all matrices to be used; -1 means no change
ArrayEigenUniMatrixBatch(const t_self &R)=default
t_self & operator=(const t_self &R)=default
void WriteSerializer(Serializer::SerializerBaseSSP serializerP, const std::string &name, Serializer::ArrayGlobalOffset offset)
void Resize(index n_size, int r, int c, TFRowSize &&rsf)
void ResizeBatch(index i, rowsize b_size)
void ReadSerializer(Serializer::SerializerBaseSSP serializerP, const std::string &name, Serializer::ArrayGlobalOffset &offset)
Eigen::Matrix< real, _n_row, _n_col, Eigen::AutoAlign|((_n_row==1 &&_n_col !=1) ? Eigen ::RowMajor :(_n_col==1 &&_n_row !=1) ? Eigen ::ColMajor :Eigen ::ColMajor)> t_EigenMatrix
ReadSerializerMetaResult ReadSerializerMeta(Serializer::SerializerBaseSSP serializerP, const std::string &name)
CRTP base for row-granularity iterators over an Array / ArrayView.
DNDS_DEVICE_CALLABLE index RowSize() const
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
T * operator[](index iRow)
Return a raw pointer to the start of row iRow.
Definition Array.hpp:630
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
t_View view()
Produce a lightweight, device-agnostic view onto the array.
Definition Array.hpp:559
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
int32_t rowsize
Row-width / per-row element-count type (signed 32-bit).
Definition Defines.hpp:109
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
Result type for ReadSerializerMeta.
Definition Array.hpp:1084
tVec r(NCells)
auto result