AMDiS 2.11-git
The Adaptive Multi-Dimensional Simulation Toolbox
 
Loading...
Searching...
No Matches
BlockMatrix.hpp
1#pragma once
2
3#include <cassert>
4#include <cmath>
5#include <vector>
6
7#include <boost/numeric/mtl/matrix/inserter.hpp>
8#include <boost/numeric/mtl/utility/property_map.hpp>
9#include <boost/numeric/mtl/utility/range_wrapper.hpp>
10
11namespace AMDiS
12{
14 template <class Matrix>
16 : public mtl::dense2D<Matrix>
17 {
18 using Inserter = mtl::mat::inserter<Matrix, mtl::operations::update_plus<typename Matrix::value_type>>;
19 template <class, class, class, class> friend class BlockPreconditioner;
20
21 public:
22 BlockMatrix() = default;
23
24 // Mapping should be an instance of BlockedBasisMapping
25 template <class Mapping>
26 BlockMatrix(Matrix const& matrix, Mapping const& mapping, bool diagonalsOnly = false)
27 {
28 copyFrom(matrix, mapping, diagonalsOnly);
29 }
30
31 // Copy the non-blocked `matrix` into this blocked matrix, using the provided `mapping`.
32 template <class Mapping>
33 void copyFrom(Matrix const& matrix, Mapping const& mapping, bool diagonalsOnly = false)
34 {
35 initSizes(mapping.rowSizeInfo(), rowSizes_);
36 initSizes(mapping.colSizeInfo(), colSizes_);
37
38 this->change_dim(rows(), cols());
39
40 std::size_t avgRowSize = std::round((1.2 * (matrix.nnz() / num_rows(matrix))) / rows());
41
42 // start insertion
43 mtl::dense2D<Inserter*> inserter(rows(), cols());
44 for (std::size_t i = 0; i < rows(); ++i) {
45 for (std::size_t j = 0; j < cols(); ++j) {
46 (*this)[i][j].change_dim(rows(i), cols(j));
47 set_to_zero((*this)[i][j]);
48 inserter[i][j] = new Inserter((*this)[i][j], avgRowSize);
49 }
50 }
51
52 // assign non-zeros to blocks
53 auto row = mtl::mat::row_map(matrix);
54 auto col = mtl::mat::col_map(matrix);
55 auto value = mtl::mat::const_value_map(matrix);
56
57 for (auto row_it : mtl::rows_of(matrix)) {
58 for (auto it : mtl::nz_of(row_it)) {
59 auto r = mapping.row(row(it));
60 auto c = mapping.col(col(it));
61
62 assert(r[0] < rows() && c[0] < cols());
63 auto& ins = *inserter[r[0]][c[0]];
64 if (!diagonalsOnly || r[0] == c[0])
65 ins[r[1]][c[1]] << value(it);
66 }
67 }
68
69 // finish insertion
70 for (std::size_t i = 0; i < rows(); ++i)
71 for (std::size_t j = 0; j < cols(); ++j)
72 delete inserter[i][j];
73 }
74
76 std::size_t rows() const
77 {
78 return rowSizes_.size();
79 }
80
82 std::size_t rows(std::size_t i) const
83 {
84 return rowSizes_[i];
85 }
86
88 std::size_t cols() const
89 {
90 return colSizes_.size();
91 }
92
94 std::size_t cols(std::size_t i) const
95 {
96 return colSizes_[i];
97 }
98
99 private:
100
101 // extract the hierarchic size into rowSizes or colSizes
102 template <class SizeInfo>
103 static void initSizes(SizeInfo const& sizeInfo, std::vector<std::size_t>& sizes)
104 {
105 using SizePrefix = typename SizeInfo::SizePrefix;
106 SizePrefix sizePrefix{};
107
108 std::size_t numBlocks = sizeInfo.size(sizePrefix);
109 sizes.resize(numBlocks);
110
111 sizePrefix.push_back(0);
112 for (std::size_t i = 0; i < numBlocks; ++i) {
113 sizePrefix.back() = i;
114 sizes[i] = sizeInfo.size(sizePrefix);
115 }
116 }
117
118 private:
119 std::vector<std::size_t> rowSizes_, colSizes_;
120 };
121
122} // end namespace AMDiS
A block matrix supporting assignment from flat matrices.
Definition BlockMatrix.hpp:17
std::size_t rows() const
Return the number of row blocks.
Definition BlockMatrix.hpp:76
std::size_t rows(std::size_t i) const
Return the number of DOFs in i'th row block.
Definition BlockMatrix.hpp:82
std::size_t cols(std::size_t i) const
Return the number of DOFs in i'th column block.
Definition BlockMatrix.hpp:94
std::size_t cols() const
Return the number of columns blocks.
Definition BlockMatrix.hpp:88
Preconditioner for block-preconditioners using row/column sub-ranges.
Definition BlockPreconditioner.hpp:142