KASKADE 7 development version
localMatrices.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2016-2022 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef LOCALMATRICES_HH
14#define LOCALMATRICES_HH
15
16#include <ostream>
17#include <vector>
18
20
21namespace Kaskade
22{
23
36 template <class Entry, bool diagonal, class SortedRowIdx, class SortedColIdx>
38 {
39 public:
40 static bool const lumped = diagonal; // backwards compatibility, remove once NumaBCRSMatrix::scatter has been updated
41
42 LocalMatrix(SortedRowIdx const& ridx, SortedColIdx const& cidx, Entry* data_)
43 : ridx_(ridx), cidx_(cidx), data(data_)
44 {
45 }
46
50 SortedRowIdx ridx() const { return ridx_; }
51
55 SortedColIdx cidx() const { return cidx_; }
56
63 size_t size() const
64 {
65 return diagonal? ridx().size(): ridx().size()*cidx().size();
66 }
67
71 void relocate(Entry* newData)
72 {
73 data = newData;
74 }
75
86 Entry& operator()(int row, int col)
87 {
88 // For diagonal matrix blocks, only the diagonal of local matrices are computed
89 // and accessed. Store these not as a diagonal of a full matrix, but in a
90 // contiguous vector.
91 if (diagonal)
92 {
93 assert(row==col);
94 return data[row];
95 }
96 else
97 // LAPACK dense storage scheme.
98 return data[row*cidx().size()+col];
99 }
100
101 Entry const& operator()(int row, int col) const
102 {
103 // For diagonal matrix blocks, only the diagonal of local matrices are computed
104 // and accessed. Store these not as a diagonal of a full matrix, but in a
105 // contiguous vector.
106 if (diagonal)
107 {
108 assert(row==col);
109 return data[row];
110 }
111 else
112 return data[row*cidx().size()+col];
113 }
114
122 {
123 assert(Aloc.N()==ridx().size() && Aloc.M()==cidx().size());
124 if (diagonal)
125 for (int r=0; r<Aloc.N(); ++r)
126 data[r] = Aloc[r][r];
127 else
128 for (int c=0; c<Aloc.M(); ++c) // TODO: consider implementing this as memcpy
129 for (int r=0; r<Aloc.N(); ++r) // for performance reasons
130 (*this)(r,c) = Aloc[r][c];
131
132 return *this;
133 }
134
136
137 private:
138 SortedRowIdx ridx_;
139 SortedColIdx cidx_;
140
141 // a pointer to the raw storage for the matrix entries
142 Entry* data;
143 };
144
145 template <class Entry, bool diagonal, class SortedRowIdx, class SortedColIdx>
147 {
148 int const n = A.ridx().size();
149 int const m = A.cidx().size();
150
151 for (int i=0; i<n; ++i)
152 {
153 for (int j=0; j<m; ++j)
154 out << (diagonal && i!=j? Entry(): A(i,j)) << " ";
155 out << "\n";
156 }
157 return out;
158 }
159
160 // ----------------------------------------------------------------------------------------------
161
177 template <class Entry, bool diagonal, class SortedRowIdx, class SortedColIdx,
178 class IT=void, class IndexType=std::size_t>
180 {
181 public:
183 using InfoType = IT;
184
188 LocalMatrices(NumaBCRSMatrix<Entry,IndexType>& globalMatrix_, size_t maxStorage_=256*1024)
189 : globalMatrix(&globalMatrix_)
190 , maxStorage(maxStorage_)
191 {
192 // Allocate memory as desired. The vector will only grow if there is a local matrix with more entries than defined here.
193 localData.reserve(maxStorage/sizeof(Entry));
194 }
195
202 : globalMatrix(nullptr), maxStorage(0)
203 {}
204
211 {
212 scatter();
213 }
214
215 // Storage for local stiffness matrices.
216 std::vector<value_type> localMatrices;
217
227 void push_back(SortedRowIdx const& ridx, SortedColIdx const& cidx)
228 {
229 // for diagonal matrices, only the diagonal is stored in a contiguous vector
230 size_t size = diagonal? ridx.size(): ridx.size()*cidx.size();
231 assert(ridx.size()==ridx.size() || !diagonal);
232
233 // Appending the new matrix exceeds the storage capacity. Scatter the existing matrices to their target and
234 // remove them.
235 if (localData.capacity() < localData.size()+size)
236 scatter();
237
238 // Append the new local matrix. Note that either the capacity of localData is sufficient, and
239 // the localMatrices data pointers remain valid, or the local matrices have been scattered,
240 // such that localMatrices is empty and no pointer exists that could be invalidated.
241 Entry* pos = &*localData.insert(localData.end(),size,Entry(0));
242 localMatrices.emplace_back(ridx,cidx,pos);
243 }
244
248 value_type & operator[](int n) { return localMatrices[n]; }
249 value_type const& operator[](int n) const { return localMatrices[n]; }
250
254 value_type & back() { return localMatrices.back(); }
255 value_type const& back() const { return localMatrices.back(); }
256
260 size_t size() const { return localMatrices.size(); }
261
269 void scatter()
270 {
271 if (globalMatrix)
272 globalMatrix->scatter(begin(localMatrices),end(localMatrices));
273 clear();
274 }
275
279 void clear()
280 {
281 localData.clear();
282 localMatrices.clear();
283 }
284
290 size_t storageSize() const
291 {
292 return localData.size() * sizeof(Entry);
293 }
294
298 size_t storageSizeLimit() const
299 {
300 return maxStorage;
301 }
302
303 private:
304 // This allows to hold a single array into which the local matrices are scattered, and
305 // thus improves memory locality (for better cache hit rates and less false sharing).
306 // Contains the local matrices one after the other, for diagonal matrices, only storage
307 // for the diagonal is provided.
308 std::vector<Entry> localData; // entries of elemental matrices
310 size_t maxStorage; // maximal desired storage space in bytes
311 };
312
313}
314
315#endif
A structure for holding a sequence of several local matrices to be filled sequentially and to be scat...
std::vector< value_type > localMatrices
void scatter()
Scatters the local matrices into the global one and removes them from the local container.
value_type & operator[](int n)
A reference to the n-th local matrix.
value_type & back()
A reference to the last pushed local matrix.
void push_back(SortedRowIdx const &ridx, SortedColIdx const &cidx)
Appends another (zero-initialized) local matrix.
value_type const & back() const
void clear()
clears all the data, leaving an empty state
~LocalMatrices()
Destructor.
LocalMatrices()
Default constructor.
value_type const & operator[](int n) const
size_t size() const
The number of local matrices that are stored.
size_t storageSize() const
reports the size of the local matrices storage in bytes
size_t storageSizeLimit() const
reports the maximal desired local matrices storage size
LocalMatrices(NumaBCRSMatrix< Entry, IndexType > &globalMatrix_, size_t maxStorage_=256 *1024)
Providing a matrix or array interface to LAPACK-ordered entries.
LocalMatrix & operator=(DynamicMatrix< Entry > const &Aloc)
Assignment.
LocalMatrix(SortedRowIdx const &ridx, SortedColIdx const &cidx, Entry *data_)
void relocate(Entry *newData)
Resets the data pointer.
static bool const lumped
SortedRowIdx ridx() const
A sequence of (global row, local row) indices, sorted ascendingly by global row.
SortedColIdx cidx() const
A sequence of (global col, local col) indices, sorted ascendingly by global col.
Entry & operator()(int row, int col)
Access the matrix entries.
size_t size() const
The number of entries stored.
Entry const & operator()(int row, int col) const
A NUMA-aware compressed row storage matrix adhering mostly to the Dune ISTL interface (to complete....
std::ostream & operator<<(std::ostream &s, std::vector< Scalar > const &vec)
Definition: dune_bridge.hh:47