KASKADE 7 development version
dynamicMatrixOps.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) 2013-2024 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 DYNAMICMATRIXOPS_HH
14#define DYNAMICMATRIXOPS_HH
15
17
18
23namespace Kaskade
24{
33 template <class MEntry, class VEntry>
34 auto operator*(DynamicMatrix<MEntry> const& A, Dune::DynamicVector<VEntry> const& x)
35 {
36 using YEntry = decltype(A[0][0]*x[0]);
37 Dune::DynamicVector<YEntry> y(A.N());
38 A.mv(x,y);
39 return y;
40 }
41
50 template <class MEntry, class VEntry>
52 {
53 using YEntry = decltype(A[0][0]*x[0]);
55 A.mv(x,y);
56 return y;
57 }
58
64 template <class MEntry>
65 auto operator*(typename Dune::FieldTraits<DynamicMatrix<MEntry>>::field_type x, DynamicMatrix<MEntry> A)
66 {
67 // Dune 2.5.1 appears to have a bug in densematrix.hh, where DenseMatrix<M>::field_type is defined
68 // as DenseMatVecTraits<M>::value_type (which is the entry type, and maybe a matrix). Thus, A *= x
69 // fails, as x is interpreted to be the entry type instead of a scalar.
70 for (int j=0; j<A.M(); ++j)
71 for (int i=0; i<A.N(); ++i)
72 A[i][j] *= x;
73 return A;
74 }
75
81 template <class MEntry>
83 {
84 return -1.0*A;
85 }
86
92 template <class MEntry>
94 {
95 assert(A.N()==B.N() && A.M()==B.M());
96// A -= B; <--- strange, this runs into a loop (2016-09-29).
97 for (int i=0; i<A.N(); ++i)
98 for (int j=0; j<A.N(); ++j)
99 A[i][j] -= B[i][j];
100 return A;
101 }
102
108 template <class MEntry>
110 {
111 assert(A.N()==B.N() && A.M()==B.M());
112 A += B;
113 return A;
114 }
115
122 template <class EntryA, class EntryB>
125 {
126 using namespace DynamicMatrixDetail;
127 using EntryC = typename ProductTraits<EntryA,EntryB>::type;
128 assert(A.M()==B.N() && C.N()==A.N() && C.M()==B.M());
129
131 && EntryTraits<EntryC>::lapackLayout && A.N()>0 && A.M()>0 && B.M()>0)
132 gemm(false,false,A.N(),B.M(),A.M(),1.0,A.data(),A.lda(),B.data(),B.lda(),0.0,C.data(),C.lda());
133 else
134 for (int j=0; j<B.M(); ++j)
135 for (int i=0; i<A.N(); ++i)
136 {
137 C[i][j] = 0;
138 for (int l=0; l<A.M(); ++l)
139 C[i][j] += A[i][l]*B[l][j];
140 }
141 }
142
153 template <class EntryA, class EntryB>
156 {
157 using namespace DynamicMatrixDetail;
158 using EntryC = typename ProductTraits<EntryA,EntryB>::type;
159
160 DynamicMatrix<EntryC> C(A.N(),B.M());
161 matrixMatrixProduct(A,B,C);
162
163 return C;
164 }
165
166
167 // ----------------------------------------------------------------------------------------------
168 // ----------------------------------------------------------------------------------------------
169
177 template <class MEntry>
179 int rowstart, int rowend, int colstart, int colend)
180 {
181 assert(rowend>=rowstart && colend>=colstart);
182 assert(0<=rowstart && 0<=colstart);
183 assert(rowend<=A.N() && colend<=A.M());
184 DynamicMatrix<MEntry> S(rowend-rowstart,colend-colstart);
185 for (int j=0; j<colend-colstart; ++j)
186 for (int i=0; i<rowend-rowstart; ++i)
187 S[i][j] = A[i+rowstart][j+colstart];
188 return S;
189 }
190
191 // ----------------------------------------------------------------------------------------------
192 // ----------------------------------------------------------------------------------------------
193
205 template <class EntryA, class EntryB>
207 {
208 using EntryC = decltype(A[0][0]*B[0][0]);
209 DynamicMatrix<EntryC> C(A.N()*B.N(),A.M()*B.M());
210
211 for (int i=0; i<A.N(); ++i)
212 for (int j=0; j<A.M(); ++j)
213 for (int k=0; k<B.N(); ++k)
214 for (int l=0; l<B.M(); ++l)
215 C[i*B.N()+k][j*B.M()+l] = A[i][j]*B[k][l];
216 return C;
217 }
218
219 // --------------------------------------------------------------------------------------------------
220 // --------------------------------------------------------------------------------------------------
221
222 namespace DynamicMatrixDetail
223 {
224 // TODO: move this into global horzcat/vertcat functions using constexpr if once we switch to C++17
225 template <class EntryA, class EntryB>
226 struct cat
227 {
228 static auto horz(DynamicMatrix<EntryA> const& A, DynamicMatrix<EntryB> const& B)
229 {
230 using field_type = typename EntryA::field_type;
231 static_assert(std::is_same<field_type,typename EntryB::field_type>::value,"A and B need to have the same underlying field type!");
232
233 int const N = A.N()*EntryA::rows;
234 assert(N==B.N()*EntryB::rows);
235
236 using EntryAB = Dune::FieldMatrix<field_type,1,1>;
237
238 DynamicMatrix<EntryAB> C(N,A.M()*EntryA::cols+B.M()*EntryB::cols);
239 unflatten(C,horzcat(flatMatrix(A),flatMatrix(B))); // TODO: a lot of copying around -> improve
240 return C;
241 }
242
243 static auto vert(Dune::DynamicVector<EntryA> const& x, Dune::DynamicVector<EntryB> const& y)
244 {
245 }
246 };
247
248 template <class Entry>
249 struct cat<Entry,Entry>
250 {
251 static auto horz(DynamicMatrix<Entry> const& A, DynamicMatrix<Entry> const& B)
252 {
253 assert(A.N()==B.N());
254 DynamicMatrix<Entry> C(A.N(),A.M()+B.M());
255 for (int i=0; i<A.N(); ++i)
256 {
257 for (int j=0; j<A.M(); ++j)
258 C[i][j] = A[i][j];
259 for (int j=0; j<B.M(); ++j)
260 C[i][j+A.M()] = B[i][j];
261 }
262 return C;
263 }
264
265 static auto vert(Dune::DynamicVector<Entry> const& x, Dune::DynamicVector<Entry> const& y)
266 {
267 Dune::DynamicVector<Entry> z(x.N()+y.N());
268 for (int i=0; i<x.N(); ++i)
269 z[i] = x[i];
270 for (int i=0; i<y.N(); ++i)
271 z[i+x.N()] = y[i];
272 return z;
273 }
274 };
275 }
276
284 template <class EntryA, class EntryB>
286 {
288 }
289
295 template <class EntryX, class EntryY>
296 auto vertcat(Dune::DynamicVector<EntryX> const& x, Dune::DynamicVector<EntryY> const& y)
297 {
299 }
300
308 template <class Entry>
310 {
311 assert(A.M()==B.M());
312 DynamicMatrix<Entry> C(A.N()+B.N(),A.M());
313 for (int j=0; j<A.M(); ++j)
314 {
315 for (int i=0; i<A.N(); ++i)
316 C[i][j] = A[i][j];
317 for (int i=0; i<B.N(); ++i)
318 C[i+A.N()][j] = B[i][j];
319 }
320 return C;
321 }
322
333 template <class Entry>
334 auto dynamicUnitMatrix(Entry const& d, int n)
335 {
336 Entry zero = 0.0;
337 DynamicMatrix<Entry> I(n,n,zero); // make sure it is zero-initialized
338 for (int i=0; i<n; ++i)
339 I[i][i] = d;
340 return I;
341 }
342
343 // --------------------------------------------------------------------------------------------------
344 // --------------------------------------------------------------------------------------------------
345
350 template <class Entry, int n>
352 {
353 Dune::FieldMatrix<Entry,n,n> A; // Create matrix
354 A = Entry(); // and zero-initialize it
355 for (int i=0; i<n; ++i)
356 A[i][i] = d[i];
357 return A;
358 }
359}
360
361#endif
A LAPACK-compatible dense matrix class with shape specified at runtime.
field_type * data()
Raw access to data (for calling BLAS/LAPACK).
void mv(const X &x, Y &y) const
matrix-vector product
size_type lda() const
The leading dimension (for calling BLAS/LAPACK).
auto operator*(DynamicMatrix< MEntry > const &A, Dune::DynamicVector< VEntry > const &x)
matrix-vector product
void gemm(bool transposeA, bool transposeB, int m, int n, int k, double alpha, double const *A, int lda, double const *B, int ldb, double beta, double *C, int ldc)
computes
auto dynamicUnitMatrix(Entry const &d, int n)
Returns the diagonal matrix with the given entry replicated on the diagonal.
void matrixMatrixProduct(DynamicMatrix< EntryA > const &A, DynamicMatrix< EntryB > const &B, DynamicMatrix< typename DynamicMatrixDetail::ProductTraits< EntryA, EntryB >::type > &C)
matrix-matrix product
auto vertcat(Dune::DynamicVector< EntryX > const &x, Dune::DynamicVector< EntryY > const &y)
Concatenes two (column) vectors vertically.
DynamicMatrix< Entry > vertcat(DynamicMatrix< Entry > const &A, DynamicMatrix< Entry > const &B)
Concatenates two matrices vertically.
DynamicMatrix< typename DynamicMatrixDetail::ProductTraits< EntryA, EntryB >::type > operator*(DynamicMatrix< EntryA > const &A, DynamicMatrix< EntryB > const &B)
matrix-matrix product
auto operator+(DynamicMatrix< MEntry > A, DynamicMatrix< MEntry > const &B)
matrix addition
DynamicMatrix< MEntry > submatrix(DynamicMatrix< MEntry > const &A, int rowstart, int rowend, int colstart, int colend)
extracts contiguous submatrices, copying the data
auto operator*(typename Dune::FieldTraits< DynamicMatrix< MEntry > >::field_type x, DynamicMatrix< MEntry > A)
multiplication with scalar
auto operator*(DynamicMatrix< MEntry > const &A, Dune::BlockVector< VEntry > const &x)
matrix-vector product
auto operator-(DynamicMatrix< MEntry > const &A)
Multiplication with -1.
Dune::FieldMatrix< Entry, n, n > diag(Dune::FieldVector< Entry, n > const &d)
Creates a fixed-size diagonal matrix from the given diagonal vector.
auto kron(DynamicMatrix< EntryA > const &A, DynamicMatrix< EntryB > const &B)
Computes the Kronecker product of two matrices.
auto horzcat(DynamicMatrix< EntryA > const &A, DynamicMatrix< EntryB > const &B)
Concatenates two matrices horizontally.
auto operator-(DynamicMatrix< MEntry > A, DynamicMatrix< MEntry > const &B)
matrix subtraction
void unflatten(DynamicMatrix< Entry > &A, DynamicMatrix< typename EntryTraits< Entry >::field_type > const &B)
DynamicMatrix< Scalar > flatMatrix(DynamicMatrix< Scalar > const &A)
auto horzcat(Dune::FieldVector< Scalar, n > const &c1)
Definition: fixdune.hh:328
static auto vert(Dune::DynamicVector< Entry > const &x, Dune::DynamicVector< Entry > const &y)
static auto horz(DynamicMatrix< Entry > const &A, DynamicMatrix< Entry > const &B)
static auto horz(DynamicMatrix< EntryA > const &A, DynamicMatrix< EntryB > const &B)
static auto vert(Dune::DynamicVector< EntryA > const &x, Dune::DynamicVector< EntryB > const &y)
Definition: scalar.hh:73