KASKADE 7 development version
matrixOps.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) 2024-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 MATRIXOPS_HH
14#define MATRIXOPS_HH
15
16namespace Kaskade
17{
19 // forward declarations such that we need not include both dense and sparse matrix headers
20 template<class K> class DynamicMatrix;
21 template <class Entry, class Index> class NumaBCRSMatrix;
22 template <class Index> class NumaCRSPatternCreator;
23
24 namespace MatrixOpsDetail
25 {
26 template <class Target>
27 class Submatrix;
28
29 template <class Entry, class Allocator>
30 class Submatrix<Dune::BCRSMatrix<Entry,Allocator>>
31 {
32 public:
33 template <class Source, class RowIndices, class ColIndices>
34 static Dune::BCRSMatrix<Entry,Allocator> apply(Source const& A,
35 RowIndices const& ri, ColIndices const& ci)
36 {
37 using Target = Dune::BCRSMatrix<Entry,Allocator>;
38 using Index = typename Source::size_type;
39
40 // Extract nonzero entries in the requested row and column ranges and store them
41 // in sorted triplet format.
42 std::vector<std::tuple<Index,Index>> a;
43 std::vector<Entry> av;
44 for (Index r=0; r<ri.size(); ++r)
45 {
46 auto row = A[ri[r]];
47 for (Index c=0; c<ci.size(); ++c)
48 {
49 auto coli = row.find(ci[c]);
50 if (coli != row.end())
51 {
52 a.push_back(std::make_tuple(r,c));
53 av.push_back(*coli);
54 }
55 }
56 }
57
58 // Define the sparsity pattern.
59 Target S(ri.size(),ci.size(),a.size(),Target::row_wise);
60 using CreateIter = typename Target::CreateIterator;
61 auto ai = begin(a);
62 for(CreateIter row=S.createbegin(); row!=S.createend(); ++row)
63 for ( ; ai!=end(a) && std::get<0>(*ai)==row.index(); ++ai)
64 row.insert(std::get<1>(*ai));
65
66 // Enter the matrix entries
67 auto avi = begin(av);
68 for (auto r=S.begin(); r!=S.end(); ++r)
69 for (auto c=r->begin(); c!=r->end(); ++c, ++avi)
70 *c = *avi;
71
72 return S;
73 }
74 };
75
76
77 template <class Entry, class Index>
78 class Submatrix<NumaBCRSMatrix<Entry,Index>>
79 {
80 public:
81 template <class Source, class RowIndices, class ColIndices>
82 static NumaBCRSMatrix<Entry,Index> apply(Source const& A,
83 RowIndices const& ri, ColIndices const& ci)
84 {
85 NumaCRSPatternCreator<Index> creator(ri.size(), ci.size());
86
87 // define sparsity pattern
88 // WARNING: This has O(n*m) run time if the target matrix is n x m.
89 // TODO: Devise a more sophisticated algorithm with O(nnz+n) run time.
90 for(Index r=0; r<ri.size(); ++r) // iterate over rows in ri
91 {
92 auto row = A[ri[r]];
93 for (Index c=0; c<ci.size(); ++c) // iterate over columns in ci
94 if (auto coli = row.find(ci[c]); coli != row.end())
95 creator.addElement(r,c);
96 }
97
98 NumaBCRSMatrix<Entry,Index> S(creator);
99
100 // Enter the matrix entries
101 for (auto r=S.begin(); r!=S.end(); ++r)
102 for (auto c=r->begin(); c!=r->end(); ++c)
103 *c = A[ri[r.index()]][ci[c.index()]];
104
105 return S;
106 }
107 };
108
109 template <class Entry>
110 class Submatrix<DynamicMatrix<Entry>>
111 {
112 public:
113 template <class RowIdx, class ColIdx>
114 static DynamicMatrix<Entry> apply(DynamicMatrix<Entry> const& A,
115 RowIdx const& rows, ColIdx const& cols)
116 {
117 assert(*std::min_element(begin(rows),end(rows))>=0);
118 assert(*std::min_element(begin(cols),end(cols))>=0);
119 assert(*std::max_element(begin(rows),end(rows))<A.N());
120 assert(*std::max_element(begin(cols),end(cols))<A.M());
121
122 DynamicMatrix<Entry> S(size(rows),size(cols));
123 auto ci = begin(cols);
124 for (int j=0; ci!=end(cols); ++j, ++ci)
125 {
126 auto ri = begin(rows);
127 for (int i=0; ri!=end(rows); ++i, ++ri)
128 S[i][j] = A[*ri][*ci];
129 }
130 return S;
131 }
132
133 template <class Source, class RowIndices, class ColIndices>
134 static DynamicMatrix<Entry> apply(Source const& A,
135 RowIndices const& ri, ColIndices const& ci)
136 {
137 DynamicMatrix<Entry> S(ri.size(),ci.size());
138 for (int r=0; r<ri.size(); ++r)
139 {
140 auto row = A[ri[r]];
141
142 for (int c=0; c<ci.size(); ++c)
143 if (auto coli = row.find(ci[c]); coli != row.end())
144 S[r][c] = *coli;
145 }
146
147 return S;
148 }
149 };
150 }
152
172 template <class Target, class Source, class RowIndices, class ColIndices>
173 Target submatrix(Source const& A, RowIndices const& ri, ColIndices const& ci)
174 {
175 return MatrixOpsDetail::Submatrix<Target>::apply(A,ri,ci);
176 }
177
178
179
180}
181
182#endif
Target submatrix(Source const &A, RowIndices const &ri, ColIndices const &ci)
extracts a sparse or dense submatrix of
Definition: matrixOps.hh:173