NiHu  2.0
helmholtz_burton_miller_solver.hpp
Go to the documentation of this file.
1 
7 #ifndef NIHU_HELMHOLTZ_BURTON_MILLER_SOLVER_HPP_INCLUDED
8 #define NIHU_HELMHOLTZ_BURTON_MILLER_SOLVER_HPP_INCLUDED
9 
10 #include "cluster_tree.hpp"
11 #include "elem_center_iterator.hpp"
12 #include "fmm_indexed.hpp"
13 #include "fmm_integrated.hpp"
14 #include "fmm_matrix.hpp"
16 #include "fmm_precompute.hpp"
17 #include "matrix_free.hpp"
18 #include "preconditioner.hpp"
19 
20 #include "core/field.hpp"
21 #include "core/function_space.hpp"
22 #include "util/timer.h"
23 #include "util/type2tag.hpp"
24 
25 #include <Eigen/IterativeLinearSolvers>
26 #include "GMRES.h"
27 
28 #ifdef NIHU_FMM_PARALLEL
29 #include <omp.h>
30 #endif
31 
32 namespace NiHu
33 {
34 namespace fmm
35 {
36 
40 template <class Fmm, class TrialSpace>
42 {
43 public:
44  typedef Fmm fmm_t;
45  typedef TrialSpace trial_space_t;
46 
48  typedef Eigen::Matrix<std::complex<double>, Eigen::Dynamic, 1> excitation_t;
49  typedef Eigen::Matrix<std::complex<double>, Eigen::Dynamic, 1> response_t;
50 
51  typedef typename fmm_t::cluster_t cluster_t;
53 
54  typedef typename tmp::deref<
55  typename tmp::begin<
56  typename trial_space_t::field_type_vector_t
57  >::type
58  >::type trial_field_t;
59 
63 
64  helmholtz_burton_miller_solver(trial_space_t const &trial_space)
65  : m_trial_space(trial_space)
66  , m_test_space(dirac(m_trial_space))
67  , m_wave_number(0.0)
68  , m_accuracy(3.0)
69  , m_far_field_order(6)
70  , m_iters(0)
71  , m_restart(3000)
72  , m_tolerance(1e-8)
73  {
74  }
75 
76  void set_restart(size_t restart)
77  {
78  m_restart = restart;
79  }
80 
81  void set_tolerance(double tolerance)
82  {
83  m_tolerance = tolerance;
84  }
85 
86  void set_wave_number(double k)
87  {
88  m_wave_number = k;
89  }
90 
91  double get_wave_number() const
92  {
93  return m_wave_number;
94  }
95 
96  response_t const &get_response() const
97  {
98  return m_response;
99  }
100 
101  void set_excitation(excitation_t const &xct)
102  {
103  m_excitation = xct;
104  }
105 
106  void set_accuracy(double accuracy)
107  {
108  m_accuracy = accuracy;
109  }
110 
111  void set_far_field_order(size_t order)
112  {
113  m_far_field_order = order;
114  }
115 
119  template <class DivideDerived>
120  response_t const &solve(divide_base<DivideDerived> const &divide)
121  {
122  // build the cluster tree
123  std::cout << "Building cluster tree ..." << std::endl;
124  cluster_tree_t tree(
125  create_field_center_iterator(m_trial_space.template field_begin<trial_field_t>()),
126  create_field_center_iterator(m_trial_space.template field_end<trial_field_t>()),
127  divide.derived());
128 
129 
130  std::cout << "Tree:\n" << tree << std::endl;
131 
132  // instantiate the fmm object
133  std::cout << "Instantiating fmm object ..." << std::endl;
134  fmm_t fmm(m_wave_number);
136  fmm.set_accuracy(m_accuracy);
137 
138  // initialize tree data
139  std::cout << "Initializing tree data ..." << std::endl;
140  fmm.init_level_data(tree);
141  for (size_t c = 0; c < tree.get_n_clusters(); ++c)
142  tree[c].set_p_level_data(&fmm.get_level_data(tree[c].get_level()));
143 
144 #if NIHU_FMM_PARALLEL
145  auto max_num_threads = omp_get_max_threads();
146  std::cout << "Expanding to " << max_num_threads << " threads" << std::endl;
147  for (size_t i = 0; i < tree.get_n_levels(); ++i)
148  fmm.get_level_data(i).set_num_threads(max_num_threads);
149 #endif
150 
151  // create interaction lists
152  std::cout << "Computing interaction lists..." << std::endl;
153  interaction_lists lists(tree);
154 
155  // create functors
157  m_far_field_order, true);
158 
159  auto idx_fctr = create_indexed_functor(
160  m_test_space.template field_begin<test_field_t>(),
161  m_test_space.template field_end<test_field_t>(),
162  m_trial_space.template field_begin<trial_field_t>(),
163  m_trial_space.template field_end<trial_field_t>(),
164  tree);
165 
166  auto pre_fctr = create_precompute_functor(tree, lists);
167 
168  // Burton-Miller coupling constant
169  std::complex<double> alpha(0.0, -1.0 / m_wave_number);
170 
171  // integration
172  auto I = create_identity_p2p_integral(type2tag<test_field_t>(), type2tag<trial_field_t>());
173  auto lhs_collection = create_fmm_operator_collection(
174  int_fctr(fmm.template create_p2p<0, 1>())
175  + alpha * int_fctr(fmm.template create_p2p<1, 1>())
176  - 0.5 * I,
177  int_fctr(fmm.template create_p2m<1>()),
178  int_fctr(fmm.template create_p2l<1>()),
179  int_fctr(fmm.template create_m2p<0>())
180  + alpha * int_fctr(fmm.template create_m2p<1>()),
181  int_fctr(fmm.template create_l2p<0>())
182  + alpha * int_fctr(fmm.template create_l2p<1>()),
183  fmm.create_m2m(),
184  fmm.create_m2l(),
185  fmm.create_l2l()
186  );
187 
188  auto rhs_collection = create_fmm_operator_collection(
189  int_fctr(fmm.template create_p2p<0, 0>())
190  + alpha * int_fctr(fmm.template create_p2p<1, 0>())
191  + (alpha / 2.0) * I,
192  int_fctr(fmm.template create_p2m<0>()),
193  int_fctr(fmm.template create_p2l<0>())
194  );
195 
196  // indexing
197  auto lhs_cix_collection = lhs_collection.transform(idx_fctr);
198  auto rhs_cix_collection = rhs_collection.transform(idx_fctr);
199 
200  // precomputation
201  std::cout << "Precomputing fmm operators ..." << std::endl;
202  auto lhs_pre_collection = lhs_cix_collection.transform(pre_fctr);
203 
204  // create rhs matrix object
205  std::cout << "Assembling rhs matrix ..." << std::endl;
206  auto slp_matrix = create_fmm_matrix(
207  pre_fctr(rhs_cix_collection.get(p2p_tag())),
208  rhs_cix_collection.get(p2m_tag()),
209  rhs_cix_collection.get(p2l_tag()),
210  lhs_pre_collection.get(m2p_tag()),
211  lhs_pre_collection.get(l2p_tag()),
212  lhs_pre_collection.get(m2m_tag()),
213  lhs_pre_collection.get(l2l_tag()),
214  lhs_pre_collection.get(m2l_tag()),
215  tree, lists);
216 
217  // compute rhs with fmbem
218  std::cout << "Computing rhs ..." << std::endl;
219  response_t rhs = slp_matrix * m_excitation;
220 
221  // create matrix object
222  std::cout << "Assembling lhs matrix ..." << std::endl;
223  auto dlp_matrix = create_fmm_matrix(
224  lhs_pre_collection,
225  tree, lists);
226 
227  // compute solution
228  std::cout << "Starting iterative solution ..." << std::endl;
229  auto M = create_matrix_free(dlp_matrix);
230 
231  Eigen::GMRES<decltype(M), Eigen::IdentityPreconditioner > solver(M);
232  solver.setTolerance(m_tolerance);
233  solver.set_restart(m_restart);
234  m_response = solver.solve(rhs);
235  m_iters = solver.iterations();
236 
237  return m_response;
238  }
239 
240  size_t get_iterations() const
241  {
242  return m_iters;
243  }
244 
245 private:
246  trial_space_t const &m_trial_space;
247  test_space_t const &m_test_space;
248 
249  double m_wave_number;
250  double m_accuracy;
251  size_t m_far_field_order;
252  excitation_t m_excitation;
253  response_t m_response;
254  size_t m_iters;
255  size_t m_restart;
256  double m_tolerance;
257 };
258 
259 template <class FmmTag, class TrialSpace>
260 auto create_helmholtz_burton_miller_solver(FmmTag, TrialSpace const& trial_space)
261 {
262  return helmholtz_burton_miller_solver<typename tag2type<FmmTag>::type, TrialSpace>(trial_space);
263 }
264 
265 } // end of namespace fmm
266 } // end of namespace NiHu
267 
268 #endif /* NIHU_HELMHOLTZ_BURTON_MILLER_SOLVER_HPP_INCLUDED */
NiHu::fmm::op_tags::m2l
Definition: fmm_operator.hpp:22
NiHu::fmm::create_matrix_free
matrix_free< FmmMatrix > create_matrix_free(FmmMatrix &fmm_mtx)
Create function for the matrix_free class.
Definition: matrix_free.hpp:124
NiHu::type2tag
Metafunction assigning a tag to a type.
Definition: type2tag.hpp:17
matrix_free.hpp
An Eigen::Matrix adaptor for the NiHu::fmm::fmm_matrix class.
type2tag.hpp
Assign a tag to a type.
tmp::deref
metafunction to dereference an iterator
Definition: sequence.hpp:114
NiHu::fmm::op_tags::l2p
Definition: fmm_operator.hpp:26
NiHu::fmm::cluster_tree::get_n_clusters
size_t get_n_clusters() const
return number of clusters
Definition: cluster_tree.hpp:282
NiHu::fmm::chebyshev_cluster
Cluster class of the Black Box FMM.
Definition: chebyshev_cluster.hpp:28
tmp::begin
return begin iterator of a sequence
Definition: sequence.hpp:79
NiHu::fmm::op_tags::p2l
Definition: fmm_operator.hpp:25
NiHu::fmm::op_tags::l2l
Definition: fmm_operator.hpp:21
fmm_precompute.hpp
Operator pre-computation interface.
NiHu::fmm::cluster_tree< cluster_t >
field.hpp
implementation of fields and field views
timer.h
portable implementation of wall clock and cpu timers
Eigen::GMRES
A GMRES solver for sparse square problems.
Definition: GMRES.h:217
NiHu::fmm::op_tags::p2m
Definition: fmm_operator.hpp:24
NiHu::fmm::op_tags::m2m
Definition: fmm_operator.hpp:20
cluster_tree.hpp
Implementation of class NiHu::fmm::cluster_tree.
NiHu::fmm::cluster_tree::get_n_levels
size_t get_n_levels() const
return number of levels
Definition: cluster_tree.hpp:253
NiHu::fmm::divide_base
Base CRTP class for cluster division.
Definition: divide.hpp:28
NiHu::dirac_space
Dirac-like extension of a function space.
Definition: function_space.hpp:312
NiHu::fmm::create_fmm_matrix
fmm_matrix< P2P, P2M, P2L, M2P, L2P, M2M, L2L, M2L > create_fmm_matrix(P2P &&p2p, P2M &&p2m, P2L &&p2l, M2P &&m2p, L2P &&l2p, M2M &&m2m, L2L &&l2l, M2L &&m2l, cluster_tree< Cluster > const &tree, interaction_lists const &lists)
factory function to create an fmm_matrix object
Definition: fmm_matrix.hpp:626
fmm_integrated.hpp
Integrated operators (P2P, P2X, X2P)
fmm_operator_collection.hpp
Implementation of NiHu::fmm::fmm_operator_collection.
NiHu::fmm::op_tags::p2p
Definition: fmm_operator.hpp:29
NiHu::fmm::create_integrated_functor
auto create_integrated_functor(TestTag test_tag, TrialTag trial_tag, size_t quadrature_order, bool sing_check)
factory function to create an integrated functor
Definition: fmm_integrated.hpp:131
elem_center_iterator.hpp
Classes for iterating through elements and fields.
fmm_matrix.hpp
Class NiHu::fmm::fmm_matrix.
function_space.hpp
declaration of class function_space
NiHu::fmm::helmholtz_burton_miller_solver::solve
const response_t & solve(divide_base< DivideDerived > const &divide)
solve the BIE
Definition: helmholtz_burton_miller_solver.hpp:120
NiHu::fmm::create_field_center_iterator
auto create_field_center_iterator(It it)
factory function to create a field center iterator
Definition: elem_center_iterator.hpp:232
NiHu::dirac_field
dirac view of a field
Definition: field.hpp:175
NiHu::fmm::interaction_lists
class storing the different interaction lists of a tree
Definition: lists.hpp:22
NiHu::dirac
const dirac_field< Field > & dirac(field_base< Field > const &f)
dirac field view factory
Definition: field.hpp:629
fmm_indexed.hpp
Interface for indexing FMM operators.
NiHu::fmm::op_tags::m2p
Definition: fmm_operator.hpp:27
NiHu::fmm::create_fmm_operator_collection
fmm_operator_collection< Ops... > create_fmm_operator_collection(Ops &&... ops)
Create function for the collection.
Definition: fmm_operator_collection.hpp:166
NiHu::fmm::helmholtz_burton_miller_solver
a generic collocational Burton-Miller solver
Definition: helmholtz_burton_miller_solver.hpp:41