Bembel
 
Loading...
Searching...
No Matches
BlockClusterTree.hpp
1// This file is part of Bembel, the higher order C++ boundary element library.
2//
3// Copyright (C) 2022 see <http://www.bembel.eu>
4//
5// It was written as part of a cooperation of J. Doelz, H. Harbrecht, S. Kurz,
6// M. Multerer, S. Schoeps, and F. Wolf at Technische Universitaet Darmstadt,
7// Universitaet Basel, and Universita della Svizzera italiana, Lugano. This
8// source code is subject to the GNU General Public License version 3 and
9// provided WITHOUT ANY WARRANTY, see <http://www.bembel.eu> for further
10// information.
11#ifndef BEMBEL_SRC_H2MATRIX_BLOCKCLUSTERTREE_HPP_
12#define BEMBEL_SRC_H2MATRIX_BLOCKCLUSTERTREE_HPP_
13
14namespace Bembel {
15
16template <typename Scalar>
17class BlockClusterTree;
18
20 enum { Refine = 0, LowRank = 1, Dense = 2 };
21};
22
23template <typename Scalar>
26 : eta_(-1), min_cluster_level_(-1), max_level_(-1) {}
28 Eigen::Matrix<double, 12, Eigen::Dynamic> ffield_qnodes_;
29 double eta_; // eta from admissibility condition
30 int ffield_deg_; // todo @Michael comment this
31 int min_cluster_level_; // a tree leaf has 4^min_cluster_level_ elements
32 int max_level_; // depth of block cluster tree
33 int polynomial_degree_; // todo @Michael comment this
34 int polynomial_degree_plus_one_squared_; // todo @Michael comment this
35 const ElementTreeNode *et_root_;
36};
37
38template <typename Scalar>
40 public:
45 : parameters_(nullptr),
47 leaf_(nullptr),
48 leaf_pointers_(nullptr),
49 cluster1_(nullptr),
50 cluster2_(nullptr),
51 rows_(0),
52 cols_(0),
53 cc_(-1) {}
54
56 parameters_ = other.parameters_;
57 sons_ = std::move(other.sons_);
58 leaf_ = other.leaf_;
59 leaf_pointers_ = other.leaf_pointers_;
60 cluster1_ = other.cluster1_;
61 cluster2_ = other.cluster2_;
62 rows_ = other.rows_;
63 cols_ = other.cols_;
64 cc_ = other.cc_;
65 updateLeafPointers();
66 }
67
68 BlockClusterTree(const BlockClusterTree &other) noexcept {
69 parameters_ = other.parameters_;
70 sons_ = other.sons_;
71 // tree leaf is deep copied for const copy constructor! This has to be
72 // taken care of in some sense when going for Hmatrix arithmetics...
73 if (other.leaf_) {
74 leaf_ = std::make_shared<
76 *leaf_ = static_cast<const TreeLeaf<
77 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>> &>(
78 *(other.leaf_));
79 }
80 leaf_pointers_ = std::make_shared<std::vector<BlockClusterTree *>>();
81 cluster1_ = other.cluster1_;
82 cluster2_ = other.cluster2_;
83 rows_ = other.rows_;
84 cols_ = other.cols_;
85 cc_ = other.cc_;
86 updateLeafPointers();
87 }
88
89 template <typename LinOp, typename AnsatzSpace>
91 const AnsatzSpace &ansatz_space) {
92 init_BlockClusterTree(linear_operator, ansatz_space);
93 }
98 std::swap(parameters_, other.parameters_);
99 std::swap(sons_, other.sons_);
100 std::swap(leaf_, other.leaf_);
101 std::swap(leaf_pointers_, other.leaf_pointers_);
102 std::swap(cluster1_, other.cluster1_);
103 std::swap(cluster2_, other.cluster2_);
104 std::swap(rows_, other.rows_);
105 std::swap(cols_, other.cols_);
106 std::swap(cc_, other.cc_);
107 updateLeafPointers();
108 return *this;
109 }
113 void set_parameters(double eta = 1.6, int min_cluster_level = 1) {
114 parameters_ = std::make_shared<BlockClusterTreeParameters<Scalar>>();
115 parameters_->eta_ = eta;
116 parameters_->min_cluster_level_ = min_cluster_level;
117 return;
118 }
119
120 template <typename LinOp, typename AnsatzSpace>
121 void init_BlockClusterTree(const LinOp &linOp,
122 const AnsatzSpace &ansatz_space) {
123 if (parameters_ == nullptr) set_parameters();
124 // get element tree from ansatz space
126 ansatz_space.get_superspace().get_mesh().get_element_tree();
127 parameters_->et_root_ = std::addressof(element_tree.root());
128 cluster1_ = std::addressof(element_tree.root());
129 cluster2_ = std::addressof(element_tree.root());
130 // set parameters for matrix assembly
131 parameters_->max_level_ = element_tree.get_max_level();
132 parameters_->polynomial_degree_ =
133 ansatz_space.get_superspace().get_polynomial_degree();
134 parameters_->polynomial_degree_plus_one_squared_ =
135 (parameters_->polynomial_degree_ + 1) *
136 (parameters_->polynomial_degree_ + 1);
137 parameters_->ffield_deg_ =
138 linOp.get_FarfieldQuadratureDegree(parameters_->polynomial_degree_);
139 // set up leaf_pointers
140 leaf_pointers_ = std::make_shared<std::vector<BlockClusterTree *>>();
141 leaf_pointers_->clear();
142 // block cluster tree assembly
143 rows_ = element_tree.get_number_of_elements();
144 cols_ = element_tree.get_number_of_elements();
145 // we let appendSubtree handle everything, since the root always
146 // returns 0 in compare cluster
147 appendSubtree(linOp, ansatz_space, cluster1_, cluster2_);
148 updateLeafPointers();
149 return;
150 }
154 template <typename LinOp, typename AnsatzSpace>
158 const ElementTreeNode *cluster2) {
159 cc_ = compareCluster(*cluster1, *cluster2);
160 // there are children to handle
161 if (cc_ == BlockClusterAdmissibility::Refine) {
162 // reserve memory for sons_
163 sons_.resize(cluster1->sons_.size(), cluster2->sons_.size());
164 for (auto j = 0; j < sons_.cols(); ++j)
165 for (auto i = 0; i < sons_.rows(); ++i) {
168 sons_(i, j).parameters_ = parameters_;
169 sons_(i, j).cluster1_ = std::addressof(son1);
170 sons_(i, j).cluster2_ = std::addressof(son2);
171 sons_(i, j).rows_ = std::distance(son1.begin(), son1.end());
172 sons_(i, j).cols_ = std::distance(son2.begin(), son2.end());
173 // let recursion handle the rest
174 sons_(i, j).appendSubtree(linear_operator, ansatz_space,
175 std::addressof(son1), std::addressof(son2));
176 }
177 } else {
178 leaf_ = std::make_shared<
180 }
181 return;
182 }
183
184 void printNode() const {
185 std::cout << "{" << std::endl;
186 std::cout << "cluster: " << cluster1_ << " & " << cluster2_ << std::endl;
187 std::cout << "rows: " << rows_ << " cols: " << cols_ << std::endl;
188 std::cout << "format: " << cc_ << std::endl;
189 std::cout << "children: " << sons_.rows() << " x " << sons_.cols()
190 << std::endl;
191 std::cout << "leaf: " << leaf_ << std::endl;
192 std::cout << "parameters: " << parameters_ << std::endl;
193
194 std::cout << "}" << std::endl;
195 return;
196 }
200 int get_cc() const { return cc_; }
201 int rows() const { return rows_; }
202 int cols() const { return cols_; }
203 const ElementTreeNode *get_cluster1() const { return cluster1_; }
204 const ElementTreeNode *get_cluster2() const { return cluster2_; }
205 int get_level() const { return get_cluster1()->get_level(); }
206 typename std::vector<BlockClusterTree *>::iterator lbegin() {
207 return leaf_pointers_->begin();
208 }
209 typename std::vector<BlockClusterTree *>::iterator lend() {
210 return leaf_pointers_->end();
211 }
212 typename std::vector<BlockClusterTree *>::const_iterator clbegin() const {
213 return leaf_pointers_->begin();
214 }
215 typename std::vector<BlockClusterTree *>::const_iterator clend() const {
216 return leaf_pointers_->end();
217 }
218 int get_row_start_index() {
219 return get_parameters().polynomial_degree_plus_one_squared_ *
220 std::distance(get_parameters().et_root_->begin(),
221 cluster1_->begin());
222 }
223 int get_row_end_index() {
224 return get_parameters().polynomial_degree_plus_one_squared_ *
225 std::distance(get_parameters().et_root_->begin(), cluster1_->end());
226 }
227 int get_col_start_index() {
228 return get_parameters().polynomial_degree_plus_one_squared_ *
229 std::distance(get_parameters().et_root_->begin(),
230 cluster2_->begin());
231 }
232 int get_col_end_index() {
233 return get_parameters().polynomial_degree_plus_one_squared_ *
234 std::distance(get_parameters().et_root_->begin(), cluster2_->end());
235 }
236 const BlockClusterTreeParameters<Scalar> &get_parameters() const {
237 return *parameters_;
238 }
239 BlockClusterTreeParameters<Scalar> &get_parameters() { return *parameters_; }
240
242 &get_leaf() const {
243 return *leaf_;
244 }
246 return *leaf_;
247 }
251 private:
255 int compareCluster(const ElementTreeNode &cluster1,
256 const ElementTreeNode &cluster2) {
257 int r;
258 double dist = (cluster1.midpoint_ - cluster2.midpoint_).norm() -
259 cluster1.radius_ - cluster2.radius_;
260 dist = dist > 0 ? dist : 0;
261 double max_radius = cluster1.radius_ > cluster2.radius_ ? cluster1.radius_
262 : cluster2.radius_;
263
267 if (dist < 0 || max_radius >= parameters_->eta_ * dist)
268 r = BlockClusterAdmissibility::Refine;
269 else
270 r = BlockClusterAdmissibility::LowRank;
271
272 if (r == BlockClusterAdmissibility::Refine &&
273 parameters_->max_level_ - cluster1.level_ <=
274 parameters_->min_cluster_level_)
275 r = BlockClusterAdmissibility::Dense;
276
277 return r;
278 }
279 void updateLeafPointers() {
280 // make sure we have the root of the block cluster tree calling this method
281 if (cluster1_->id_ != -1 || cluster1_ != cluster2_) {
282 return;
283 } else {
284 leaf_pointers_->clear();
285 updateLeafPointers_recursion(*this);
286 }
287 }
288 void updateLeafPointers_recursion(BlockClusterTree &child) {
289 if (child.cc_ == BlockClusterAdmissibility::Refine) {
290 for (auto j = 0; j < child.sons_.cols(); ++j)
291 for (auto i = 0; i < child.sons_.rows(); ++i)
292 updateLeafPointers_recursion(child.sons_(i, j));
293 } else {
294 leaf_pointers_->push_back(std::addressof(child));
295 }
296 return;
297 }
301 std::shared_ptr<BlockClusterTreeParameters<Scalar>> parameters_;
303 std::shared_ptr<
305 leaf_;
306 std::shared_ptr<std::vector<BlockClusterTree *>> leaf_pointers_;
307 const ElementTreeNode *cluster1_;
308 const ElementTreeNode *cluster2_;
309 int rows_;
310 int cols_;
311 int cc_;
312};
313
314} // namespace Bembel
315#endif // BEMBEL_SRC_H2MATRIX_BLOCKCLUSTERTREE_HPP_
The AnsatzSpace is the class that handles the assembly of the discrete basis.
void appendSubtree(const LinOp &linear_operator, const AnsatzSpace &ansatz_space, const ElementTreeNode *cluster1, const ElementTreeNode *cluster2)
methods
void set_parameters(double eta=1.6, int min_cluster_level=1)
init
BlockClusterTree & operator=(BlockClusterTree other) noexcept
assignment operator
This class organizes an element structure on a Geometry object and handles refinement.
The ElementTreeNode corresponds to an element in the element tree.
int id_
radius of the element
const_iterator begin() const
Returns an iterator pointing to the element in the sequence before this ElementTreeNodes.
int get_level() const
Get the level of refinement of the element.
std::vector< ElementTreeNode > sons_
member variables
const_iterator end() const
Returns an iterator pointing to the element in the sequence after this ElementTreeNode.
This class is managing the leafs of the H2Matrix BlockClusterTree.
Definition TreeLeaf.hpp:20
Routines for the evalutation of pointwise errors.
constexpr int getFunctionSpaceOutputDimension()