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  std::cout << "Tree:\n" << tree << std::endl;
129 
130  // instantiate the fmm object
131  std::cout << "Instantiating fmm object ..." << std::endl;
132  fmm_t fmm(m_wave_number);
134  fmm.set_accuracy(m_accuracy);
135 
136  // initialize tree data
137  std::cout << "Initializing tree data ..." << std::endl;
138  fmm.init_level_data(tree);
139  for (size_t c = 0; c < tree.get_n_clusters(); ++c)
140  tree[c].set_p_level_data(&fmm.get_level_data(tree[c].get_level()));
141 
142 #if NIHU_FMM_PARALLEL
143  auto max_num_threads = omp_get_max_threads();
144  std::cout << "Expanding to " << max_num_threads << " threads" << std::endl;
145  for (size_t i = 0; i < tree.get_n_levels(); ++i)
146  fmm.get_level_data(i).set_num_threads(max_num_threads);
147 #endif
148 
149  // create interaction lists
150  std::cout << "Computing interaction lists..." << std::endl;
151  interaction_lists lists(tree);
152 
153  // create functors
155  m_far_field_order, true);
156 
157  auto idx_fctr = create_indexed_functor(
158  m_test_space.template field_begin<test_field_t>(),
159  m_test_space.template field_end<test_field_t>(),
160  m_trial_space.template field_begin<trial_field_t>(),
161  m_trial_space.template field_end<trial_field_t>(),
162  tree);
163 
164  auto pre_fctr = create_precompute_functor(tree, lists);
165 
166  // Burton-Miller coupling constant
167  std::complex<double> alpha(0.0, -1.0 / m_wave_number);
168 
169  // integration
170  auto I = create_identity_p2p_integral(type2tag<test_field_t>(), type2tag<trial_field_t>());
171  auto lhs_collection = create_fmm_operator_collection(
172  int_fctr(fmm.template create_p2p<0, 1>())
173  + alpha * int_fctr(fmm.template create_p2p<1, 1>())
174  - 0.5 * I,
175  int_fctr(fmm.template create_p2m<1>()),
176  int_fctr(fmm.template create_p2l<1>()),
177  int_fctr(fmm.template create_m2p<0>())
178  + alpha * int_fctr(fmm.template create_m2p<1>()),
179  int_fctr(fmm.template create_l2p<0>())
180  + alpha * int_fctr(fmm.template create_l2p<1>()),
181  fmm.create_m2m(),
182  fmm.create_m2l(),
183  fmm.create_l2l()
184  );
185 
186  auto rhs_collection = create_fmm_operator_collection(
187  int_fctr(fmm.template create_p2p<0, 0>())
188  + alpha * int_fctr(fmm.template create_p2p<1, 0>())
189  + (alpha / 2.0) * I,
190  int_fctr(fmm.template create_p2m<0>()),
191  int_fctr(fmm.template create_p2l<0>())
192  );
193 
194  // indexing
195  auto lhs_cix_collection = lhs_collection.transform(idx_fctr);
196  auto rhs_cix_collection = rhs_collection.transform(idx_fctr);
197 
198  // precomputation
199  std::cout << "Precomputing fmm operators ..." << std::endl;
200  auto lhs_pre_collection = lhs_cix_collection.transform(pre_fctr);
201 
202  // create rhs matrix object
203  std::cout << "Assembling rhs matrix ..." << std::endl;
204  auto slp_matrix = create_fmm_matrix(
205  pre_fctr(rhs_cix_collection.get(p2p_tag())),
206  rhs_cix_collection.get(p2m_tag()),
207  rhs_cix_collection.get(p2l_tag()),
208  lhs_pre_collection.get(m2p_tag()),
209  lhs_pre_collection.get(l2p_tag()),
210  lhs_pre_collection.get(m2m_tag()),
211  lhs_pre_collection.get(l2l_tag()),
212  lhs_pre_collection.get(m2l_tag()),
213  tree, lists);
214 
215  // compute rhs with fmbem
216  std::cout << "Computing rhs ..." << std::endl;
217  response_t rhs = slp_matrix * m_excitation;
218 
219  // create matrix object
220  std::cout << "Assembling lhs matrix ..." << std::endl;
221  auto dlp_matrix = create_fmm_matrix(
222  lhs_pre_collection,
223  tree, lists);
224 
225  // compute solution
226  std::cout << "Starting iterative solution ..." << std::endl;
227  auto M = create_matrix_free(dlp_matrix);
228 
229  Eigen::GMRES<decltype(M), Eigen::IdentityPreconditioner > solver(M);
230  solver.setTolerance(m_tolerance);
231  solver.set_restart(m_restart);
232  m_response = solver.solve(rhs);
233  m_iters = solver.iterations();
234 
235  return m_response;
236  }
237 
238  size_t get_iterations() const
239  {
240  return m_iters;
241  }
242 
243 private:
244  trial_space_t const &m_trial_space;
245  test_space_t const &m_test_space;
246 
247  double m_wave_number;
248  double m_accuracy;
249  size_t m_far_field_order;
250  excitation_t m_excitation;
251  response_t m_response;
252  size_t m_iters;
253  size_t m_restart;
254  double m_tolerance;
255 };
256 
257 template <class FmmTag, class TrialSpace>
258 auto create_helmholtz_burton_miller_solver(FmmTag, TrialSpace const& trial_space)
259 {
260  return helmholtz_burton_miller_solver<typename tag2type<FmmTag>::type, TrialSpace>(trial_space);
261 }
262 
263 } // end of namespace fmm
264 } // end of namespace NiHu
265 
266 #endif /* NIHU_HELMHOLTZ_BURTON_MILLER_SOLVER_HPP_INCLUDED */
type2tag.hpp
Assign a tag to a type.
fmm_matrix.hpp
Class NiHu::fmm::fmm_matrix.
NiHu::fmm::chebyshev_cluster
Cluster class of the Black Box FMM.
Definition: chebyshev_cluster.hpp:28
NiHu::fmm::op_tags::l2p
Definition: fmm_operator.hpp:26
NiHu::fmm::cluster_tree< cluster_t >
tmp::begin
return begin iterator of a sequence
Definition: sequence.hpp:79
tmp::deref
metafunction to dereference an iterator
Definition: sequence.hpp:114
NiHu::fmm::op_tags::p2l
Definition: fmm_operator.hpp:25
Eigen::GMRES
A GMRES solver for sparse square problems.
Definition: GMRES.h:217
NiHu::fmm::op_tags::p2m
Definition: fmm_operator.hpp:24
NiHu::type2tag
Metafunction assigning a tag to a type.
Definition: type2tag.hpp:17
NiHu::fmm::divide_base
Base CRTP class for cluster division.
Definition: divide.hpp:28
NiHu::fmm::cluster_tree::get_n_clusters
size_t get_n_clusters() const
return number of clusters
Definition: cluster_tree.hpp:282
NiHu::fmm::cluster_tree::get_n_levels
size_t get_n_levels() const
return number of levels
Definition: cluster_tree.hpp:253
fmm_operator_collection.hpp
Implementation of NiHu::fmm::fmm_operator_collection.
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::dirac_space
Dirac-like extension of a function space.
Definition: function_space.hpp:312
field.hpp
implementation of fields and field views
NiHu::dirac_field
dirac view of a field
Definition: field.hpp:175
NiHu::fmm::op_tags::m2m
Definition: fmm_operator.hpp:20
matrix_free.hpp
An Eigen::Matrix adaptor for the NiHu::fmm::fmm_matrix class.
elem_center_iterator.hpp
Classes for iterating through elements and fields.
cluster_tree.hpp
Implementation of class NiHu::fmm::cluster_tree.
NiHu::fmm::op_tags::m2p
Definition: fmm_operator.hpp:27
fmm_indexed.hpp
Interface for indexing FMM operators.
fmm_precompute.hpp
Operator pre-computation interface.
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::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
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
timer.h
portable implementation of wall clock and cpu timers
NiHu::fmm::helmholtz_burton_miller_solver
a generic collocational Burton-Miller solver
Definition: helmholtz_burton_miller_solver.hpp:41
fmm_integrated.hpp
Integrated operators (P2P, P2X, X2P)
function_space.hpp
declaration of class function_space
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::solve
const response_t & solve(divide_base< DivideDerived > const &divide)
solve the BIE
Definition: helmholtz_burton_miller_solver.hpp:120
NiHu::fmm::op_tags::l2l
Definition: fmm_operator.hpp:21
NiHu::fmm::op_tags::p2p
Definition: fmm_operator.hpp:29
NiHu::dirac
const dirac_field< Field > & dirac(field_base< Field > const &f)
dirac field view factory
Definition: field.hpp:629
NiHu::fmm::interaction_lists
class storing the different interaction lists of a tree
Definition: lists.hpp:22