Bembel
 
Loading...
Searching...
No Matches
H2Matrix.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_H2MATRIX_HPP_
12#define BEMBEL_SRC_H2MATRIX_H2MATRIX_HPP_
13
26namespace Eigen {
28template <typename ScalarT>
29class H2Matrix;
31namespace internal {
32template <typename ScalarT>
33struct traits<H2Matrix<ScalarT>> {
34 typedef ScalarT Scalar;
35 typedef int StorageIndex;
36 typedef H2 StorageKind;
37 typedef MatrixXpr XprKind;
38 enum {
39 RowsAtCompileTime = Dynamic,
40 ColsAtCompileTime = Dynamic,
41 MaxRowsAtCompileTime = Dynamic,
42 MaxColsAtCompileTime = Dynamic,
43 Flags = NestByRefBit
44 };
45};
46
47// this struct is necessary for compatibility with iterative solvers
48template <typename ScalarT>
49struct is_ref_compatible<H2Matrix<ScalarT>> {
50 enum { value = false };
51};
52template <typename ScalarT>
53struct is_ref_compatible<const H2Matrix<ScalarT>>
54 : is_ref_compatible<H2Matrix<ScalarT>> {};
55
56} // namespace internal
57
58// actual definition of the class
59template <typename ScalarT>
60class H2Matrix : public H2MatrixBase<H2Matrix<ScalarT>> {
61 public:
65 // Required typedefs, constants and so on.
66 typedef ScalarT Scalar;
67 typedef typename NumTraits<ScalarT>::Real RealScalar;
68 typedef Index StorageIndex;
69 enum {
70 ColsAtCompileTime = Dynamic,
71 MaxColsAtCompileTime = Dynamic,
72 IsRowMajor = false,
73 Flags = NestByRefBit
74 };
75 // Minimum specialisation of EigenBase methods
76 Index rows() const { return transformation_matrix_.cols(); }
77 Index cols() const { return transformation_matrix_.cols(); }
78 // Definition of the matrix multiplication
79 template <typename Rhs>
80 Product<H2Matrix, Rhs, AliasFreeProduct> operator*(
81 const MatrixBase<Rhs>& x) const {
82 return Product<H2Matrix, Rhs, AliasFreeProduct>(*this, x.derived());
83 }
93 template <typename Derived>
94 void init_H2Matrix(const Derived& linOp,
95 const Bembel::AnsatzSpace<Derived>& ansatz_space,
96 int number_of_points = 9) {
97 // get transformation matrix from ansatz space
98 transformation_matrix_ = ansatz_space.get_transformation_matrix();
104 // initialize block-cluster-trees and get parameters
105 const int vector_dimension = Bembel::getFunctionSpaceVectorDimension<
107 block_cluster_tree_.resize(vector_dimension, vector_dimension);
108 {
109 Bembel::BlockClusterTree<Scalar> bt(linOp, ansatz_space);
110 for (int i = 0; i < vector_dimension; ++i)
111 for (int j = 0; j < vector_dimension; ++j)
112 block_cluster_tree_(i, j) =
113 bt; // .init_BlockClusterTree(linOp, ansatz_space);
114 }
115 auto parameters = block_cluster_tree_(0, 0).get_parameters();
116 // compute transfer and moment matrices for fmm
117 int cluster_level = parameters.max_level_ - parameters.min_cluster_level_;
118 if (cluster_level < 0) cluster_level = 0;
119 int cluster_refinement = parameters.min_cluster_level_;
120 if (cluster_refinement > parameters.max_level_)
121 cluster_refinement = parameters.max_level_;
122 fmm_transfer_matrices_ = Bembel::H2Multipole::computeTransferMatrices<
123 Bembel::H2Multipole::ChebychevRoots>(number_of_points);
124 fmm_moment_matrix_ = Bembel::H2Multipole::
125 Moment2D<Bembel::H2Multipole::ChebychevRoots, Derived>::compute2DMoment(
126 ansatz_space.get_superspace(), cluster_level, cluster_refinement,
127 number_of_points);
128 // compute interpolation points
129 Eigen::VectorXd interpolation_points1D =
130 Bembel::H2Multipole::ChebychevRoots(number_of_points).points_;
131 Eigen::MatrixXd interpolation_points2D =
132 Bembel::H2Multipole::interpolationPoints2D(interpolation_points1D);
133 // compute content of tree leafs
134 int polynomial_degree = ansatz_space.get_polynomial_degree();
135 int polynomial_degree_plus_one_squared =
136 (polynomial_degree + 1) * (polynomial_degree + 1);
138 auto super_space = ansatz_space.get_superspace();
139 auto ffield_deg = linOp.get_FarfieldQuadratureDegree(polynomial_degree);
140 std::vector<ElementSurfacePoints> ffield_qnodes =
141 Bembel::DuffyTrick::computeFfieldQnodes(super_space, GS[ffield_deg]);
142 const int NumberOfFMMComponents =
144#pragma omp parallel
145 {
146#pragma omp single
147 {
148 // build vector of iterators
149 std::vector<
150 typename std::vector<Bembel::BlockClusterTree<Scalar>*>::iterator>
151 leafs;
152 leafs.resize(vector_dimension * vector_dimension);
153 for (int i = 0; i < vector_dimension; ++i)
154 for (int j = 0; j < vector_dimension; ++j)
155 leafs[i * vector_dimension + j] =
156 block_cluster_tree_(j, i).lbegin();
157 // iterate over leafs
158 for (; leafs[0] != block_cluster_tree_(0, 0).lend();) {
159#pragma omp task firstprivate(leafs)
160 {
161 switch ((*(leafs[0]))->get_cc()) {
162 // assemble dense matrix blocks
163 case Bembel::BlockClusterAdmissibility::Dense: {
164 const Bembel::ElementTreeNode* cluster1 =
165 (*(leafs[0]))->get_cluster1();
166 const Bembel::ElementTreeNode* cluster2 =
167 (*(leafs[0]))->get_cluster2();
168 int block_size =
169 std::distance(cluster2->begin(), cluster2->end()) *
170 polynomial_degree_plus_one_squared;
171 std::vector<
172 Eigen::Matrix<ScalarT, Eigen::Dynamic, Eigen::Dynamic>>
173 F;
174 for (int i = 0; i < vector_dimension * vector_dimension; ++i)
175 F.push_back(
176 Eigen::Matrix<ScalarT, Eigen::Dynamic, Eigen::Dynamic>(
177 block_size, block_size));
178 // iterate over elements in dense matrix block
179 unsigned int cl1index = 0;
180 unsigned int cl2index = 0;
181 for (const auto& element1 : *cluster1) {
182 cl2index = 0;
183 for (const auto& element2 : *cluster2) {
184 Eigen::Matrix<ScalarT, Eigen::Dynamic, Eigen::Dynamic>
185 intval(vector_dimension *
186 polynomial_degree_plus_one_squared,
187 vector_dimension *
188 polynomial_degree_plus_one_squared);
189 // do integration
191 linOp, super_space, element1, element2, GS,
192 ffield_qnodes[element1.id_],
193 ffield_qnodes[element2.id_], &intval);
194 // insert into dense matrices of all block cluster trees
195 for (int i = 0; i < vector_dimension; ++i)
196 for (int j = 0; j < vector_dimension; ++j)
197 F[i * vector_dimension + j].block(
198 polynomial_degree_plus_one_squared * cl1index,
199 polynomial_degree_plus_one_squared * cl2index,
200 polynomial_degree_plus_one_squared,
201 polynomial_degree_plus_one_squared) =
202 intval.block(j * polynomial_degree_plus_one_squared,
203 i * polynomial_degree_plus_one_squared,
204 polynomial_degree_plus_one_squared,
205 polynomial_degree_plus_one_squared);
206 ++cl2index;
207 }
208 ++cl1index;
209 }
210 for (int i = 0; i < vector_dimension * vector_dimension; ++i)
211 (*(leafs[i]))->get_leaf().set_F(F[i]);
212 } break;
213 // interpolation for low-rank blocks
214 case Bembel::BlockClusterAdmissibility::LowRank: {
215 auto F = Bembel::H2Multipole::interpolateKernel<Derived>(
216 linOp, super_space, interpolation_points2D,
217 *((*(leafs[0]))->get_cluster1()),
218 *((*(leafs[0]))->get_cluster2()));
219 for (int i = 0; i < vector_dimension; ++i) {
220 for (int j = 0; j < vector_dimension; ++j) {
221 (*(leafs[i * vector_dimension + j]))
222 ->get_leaf()
223 .set_F(F.block(j * interpolation_points2D.rows() *
224 NumberOfFMMComponents,
225 i * interpolation_points2D.rows() *
226 NumberOfFMMComponents,
227 interpolation_points2D.rows() *
228 NumberOfFMMComponents,
229 interpolation_points2D.rows() *
230 NumberOfFMMComponents));
231 (*(leafs[i * vector_dimension + j]))
232 ->get_leaf()
233 .set_low_rank_flag(true);
234 }
235 }
236 } break;
237 // this leaf is not a low-rank block and not a dense block,
238 // thus it is not a leaf -> error
239 default:
240 assert(0 && "This should never happen");
241 break;
242 }
243 }
244 // increment leafs of all block-cluster trees
245 for (auto leafsit = leafs.begin(); leafsit != leafs.end(); ++leafsit)
246 ++(*leafsit);
247 }
248 }
249 }
250 }
254 Eigen::Matrix<ScalarT, Eigen::Dynamic, Eigen::Dynamic> get_dense() const {
255 Eigen::Matrix<ScalarT, Eigen::Dynamic, Eigen::Dynamic> dense(rows(),
256 cols());
257 for (int i = 0; i < cols(); ++i) {
258 Eigen::VectorXd unit(cols());
259 unit.setZero();
260 unit(i) = 1.;
261 dense.col(i) = (*this) * unit;
262 }
263 return dense;
264 }
268 const Eigen::SparseMatrix<double> get_transformation_matrix() const {
269 return transformation_matrix_;
270 }
271 const Eigen::MatrixXd get_fmm_transfer_matrices() const {
272 return fmm_transfer_matrices_;
273 }
274 const std::vector<Eigen::MatrixXd> get_fmm_moment_matrix() const {
275 return fmm_moment_matrix_;
276 }
278 get_block_cluster_tree() const {
279 return block_cluster_tree_;
280 }
284 private:
285 // we declare functionality which has not been implemented (yet)
286 // to be private
287 H2Matrix(const H2Matrix<ScalarT>& H);
289 H2Matrix& operator=(const H2Matrix<ScalarT>& H);
290 H2Matrix& operator=(H2Matrix<ScalarT>&& H);
291
292 Eigen::SparseMatrix<double> transformation_matrix_;
294 Eigen::MatrixXd fmm_transfer_matrices_;
295 std::vector<Eigen::MatrixXd> fmm_moment_matrix_;
296};
297
298namespace internal {
299
300// adaption from SparseMatrix from Eigen
301template <typename Scalar>
302struct evaluator<H2Matrix<Scalar>> : evaluator<H2MatrixBase<H2Matrix<Scalar>>> {
303 typedef evaluator<H2MatrixBase<H2Matrix<Scalar>>> Base;
305 evaluator() : Base() {}
306 explicit evaluator(const H2MatrixType& mat) : Base(mat) {}
307};
308
309} // namespace internal
310} // namespace Eigen
311
312#endif // BEMBEL_SRC_H2MATRIX_H2MATRIX_HPP_
The AnsatzSpace is the class that handles the assembly of the discrete basis.
int get_polynomial_degree() const
Retrieves the polynomial degree of this AnsatzSpace.
const SuperSpace< Derived > & get_superspace() const
Retrieves the reference to the SuperSpace associated with this AnsatzSpace.
const Eigen::SparseMatrix< double > & get_transformation_matrix() const
Retrieves the transformation matrix associated with this AnsatzSpace.
The ElementTreeNode corresponds to an element in the element tree.
const_iterator begin() const
Returns an iterator pointing to the element in the sequence before this ElementTreeNodes.
const_iterator end() const
Returns an iterator pointing to the element in the sequence after this ElementTreeNode.
forward definition of the H2Matrix Class in order to define traits
Definition H2Matrix.hpp:60
H2Matrix()
constructors
Definition H2Matrix.hpp:87
Eigen::Matrix< ScalarT, Eigen::Dynamic, Eigen::Dynamic > get_dense() const
methods
Definition H2Matrix.hpp:254
const Eigen::SparseMatrix< double > get_transformation_matrix() const
getter
Definition H2Matrix.hpp:268
ScalarT Scalar
Eigen related things.
Definition H2Matrix.hpp:66
void init_H2Matrix(const Derived &linOp, const Bembel::AnsatzSpace< Derived > &ansatz_space, int number_of_points=9)
Assemble H2-Matrix for linear operator linOp and AnsatzSpace ansatz_space with number_of_points inter...
Definition H2Matrix.hpp:94
Hierarchical Matrix class, which extends the EigenBase class.
void evaluateBilinearForm(const LinearOperatorBase< Derived > &linOp, const T &super_space, const ElementTreeNode &e1, const ElementTreeNode &e2, const CubatureVector &GS, const ElementSurfacePoints &ffield_qnodes1, const ElementSurfacePoints &ffield_qnodes2, Eigen::Matrix< typename LinearOperatorTraits< Derived >::Scalar, Eigen::Dynamic, Eigen::Dynamic > *intval)
This function wraps the quadrature routines for the DuffyTrick and returns all integrals for the give...
std::vector< ElementSurfacePoints > computeFfieldQnodes(const T &super_space, const Cubature &Q)
evaluates a given quadrature on all surface panels storage format is qNodes.col(k) = [xi,...
Eigen::MatrixXd interpolationPoints2D(const Eigen::VectorXd &x)
Compute tensor interpolation points on unit square from 1D interpolation points.
Eigen::MatrixXd computeTransferMatrices(int number_of_points)
Computes transfer matrices in required order to apply them all-at-once in a matrix-vector-product,...
constexpr int getFunctionSpaceVectorDimension()
Computes the number_of_points Chebychev points.
struct containing specifications on the linear operator has to be specialized or derived for any part...