11 #ifndef BEMBEL_SRC_H2MATRIX_BLOCKCLUSTERTREE_HPP_
12 #define BEMBEL_SRC_H2MATRIX_BLOCKCLUSTERTREE_HPP_
16 template <
typename Scalar>
17 class BlockClusterTree;
20 enum { Refine = 0, LowRank = 1, Dense = 2 };
23 template <
typename Scalar>
26 : eta_(-1), min_cluster_level_(-1), max_level_(-1) {}
28 Eigen::Matrix<double, 12, Eigen::Dynamic> ffield_qnodes_;
31 int min_cluster_level_;
33 int polynomial_degree_;
34 int polynomial_degree_plus_one_squared_;
38 template <
typename Scalar>
45 : parameters_(nullptr),
48 leaf_pointers_(nullptr),
56 parameters_ = other.parameters_;
57 sons_ = std::move(other.sons_);
59 leaf_pointers_ = other.leaf_pointers_;
60 cluster1_ = other.cluster1_;
61 cluster2_ = other.cluster2_;
69 parameters_ = other.parameters_;
74 leaf_ = std::make_shared<
75 TreeLeaf<Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>>>();
76 *leaf_ =
static_cast<const TreeLeaf<
77 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>
> &>(
80 leaf_pointers_ = std::make_shared<std::vector<BlockClusterTree *>>();
81 cluster1_ = other.cluster1_;
82 cluster2_ = other.cluster2_;
89 template <
typename LinOp,
typename AnsatzSpace>
91 const AnsatzSpace &ansatz_space) {
92 init_BlockClusterTree(linear_operator, ansatz_space);
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();
114 parameters_ = std::make_shared<BlockClusterTreeParameters<Scalar>>();
115 parameters_->eta_ = eta;
116 parameters_->min_cluster_level_ = min_cluster_level;
120 template <
typename LinOp,
typename AnsatzSpace>
121 void init_BlockClusterTree(
const LinOp &linOp,
127 parameters_->et_root_ = std::addressof(element_tree.
root());
128 cluster1_ = std::addressof(element_tree.
root());
129 cluster2_ = std::addressof(element_tree.
root());
132 parameters_->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_);
140 leaf_pointers_ = std::make_shared<std::vector<BlockClusterTree *>>();
141 leaf_pointers_->clear();
148 updateLeafPointers();
154 template <
typename LinOp,
typename AnsatzSpace>
159 cc_ = compareCluster(*cluster1, *cluster2);
161 if (cc_ == BlockClusterAdmissibility::Refine) {
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());
174 sons_(i, j).appendSubtree(linear_operator, ansatz_space,
175 std::addressof(son1), std::addressof(son2));
178 leaf_ = std::make_shared<
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()
191 std::cout <<
"leaf: " << leaf_ << std::endl;
192 std::cout <<
"parameters: " << parameters_ << std::endl;
194 std::cout <<
"}" << std::endl;
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();
209 typename std::vector<BlockClusterTree *>::iterator lend() {
210 return leaf_pointers_->end();
212 typename std::vector<BlockClusterTree *>::const_iterator clbegin()
const {
213 return leaf_pointers_->begin();
215 typename std::vector<BlockClusterTree *>::const_iterator clend()
const {
216 return leaf_pointers_->end();
218 int get_row_start_index() {
219 return get_parameters().polynomial_degree_plus_one_squared_ *
220 std::distance(get_parameters().et_root_->begin(),
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());
227 int get_col_start_index() {
228 return get_parameters().polynomial_degree_plus_one_squared_ *
229 std::distance(get_parameters().et_root_->begin(),
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());
236 const BlockClusterTreeParameters<Scalar> &get_parameters()
const {
239 BlockClusterTreeParameters<Scalar> &get_parameters() {
return *parameters_; }
241 const TreeLeaf<Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>>
245 TreeLeaf<Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>> &get_leaf() {
255 int compareCluster(
const ElementTreeNode &cluster1,
256 const ElementTreeNode &cluster2) {
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_
267 if (dist < 0 || max_radius >= parameters_->eta_ * dist)
268 r = BlockClusterAdmissibility::Refine;
270 r = BlockClusterAdmissibility::LowRank;
272 if (r == BlockClusterAdmissibility::Refine &&
273 parameters_->max_level_ - cluster1.level_ <=
274 parameters_->min_cluster_level_)
275 r = BlockClusterAdmissibility::Dense;
279 void updateLeafPointers() {
281 if (cluster1_->
id_ != -1 || cluster1_ != cluster2_) {
284 leaf_pointers_->clear();
285 updateLeafPointers_recursion(*
this);
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));
294 leaf_pointers_->push_back(std::addressof(child));
301 std::shared_ptr<BlockClusterTreeParameters<Scalar>> parameters_;
302 GenericMatrix<BlockClusterTree> sons_;
304 TreeLeaf<Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>>>
306 std::shared_ptr<std::vector<BlockClusterTree *>> leaf_pointers_;
307 const ElementTreeNode *cluster1_;
308 const ElementTreeNode *cluster2_;
The AnsatzSpace is the class that handles the assembly of the discrete basis.
const SuperSpace< Derived > & get_superspace() const
Retrieves the reference to the SuperSpace associated with this AnsatzSpace.
BlockClusterTree & operator=(BlockClusterTree other) noexcept
assignment operator
void appendSubtree(const LinOp &linear_operator, const AnsatzSpace &ansatz_space, const ElementTreeNode *cluster1, const ElementTreeNode *cluster2)
methods
BlockClusterTree()
constructors
void set_parameters(double eta=1.6, int min_cluster_level=1)
init
This class organizes an element structure on a Geometry object and handles refinement.
int get_number_of_elements() const
Return number of elements in the ElementTree.
int get_max_level() const
Return maximum level of refinement.
ElementTreeNode & root()
Return reference to the root ElementTreeNode.
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.
Routines for the evalutation of pointwise errors.