Bembel
AugmentedEFIE.hpp
1 // This file is part of Bembel, the higher order C++ boundary element library.
2 //
3 // Copyright (C) 2024 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_AUGMENTEDEFIE_AUGMENTEDEFIE_HPP_
12 #define BEMBEL_SRC_AUGMENTEDEFIE_AUGMENTEDEFIE_HPP_
13 
14 namespace Bembel {
19 template <typename MatrixFormat, typename Derived>
21  public:
23  // constructors
25  AugmentedEFIE() {}
26  AugmentedEFIE(const AnsatzSpace<Derived> &ansatz_space_vector,
27  const Geometry &geometry) {
28  init_AugmentedEFIE(ansatz_space_vector, geometry);
29  }
31  // init_AugmentedEFIE
33  void init_AugmentedEFIE(const AnsatzSpace<Derived> &ansatz_space_vector,
34  const Geometry &geometry) {
35  ansatz_space_vector_ = ansatz_space_vector;
36 
37  // Build ansatz spaces
38  ansatz_space_mass_ = AnsatzSpace<MassMatrixScalarDisc>(
39  geometry, ansatz_space_vector.get_refinement_level(),
40  ansatz_space_vector.get_polynomial_degree() - 1);
41 
42  ansatz_space_scalar_ = AnsatzSpace<HelmholtzSingleLayerOperator>(
43  geometry, ansatz_space_vector.get_refinement_level(),
44  ansatz_space_vector.get_polynomial_degree() - 1);
45 
46  dofs_scalar_ = ansatz_space_scalar_.get_number_of_dofs();
47  dofs_vector_ = ansatz_space_vector_.get_number_of_dofs();
48  return;
49  }
51  // compute
53 
56  inline void compute() {
57  system_matrix_ = Eigen::MatrixXcd(dofs_scalar_ + dofs_vector_,
58  dofs_scalar_ + dofs_vector_);
59 
61  &system_matrix_, ansatz_space_mass_, ansatz_space_scalar_,
62  ansatz_space_vector_, wavenumber_);
63  return;
64  }
68  inline void compute(VoltageSource source) {
69  const int elements_per_edge =
70  (1 << ansatz_space_vector_.get_refinement_level());
71  // This number contains all degrees of freedom on the edge for the
72  // excitation and three extra ones dedicated to the potential of the voltage
73  // source.
74  const int dofs_excitation =
75  3 +
76  (source.positive_.size() + source.negative_.size()) * elements_per_edge;
77  system_matrix_ =
78  Eigen::MatrixXcd::Zero(dofs_scalar_ + dofs_vector_ + dofs_excitation,
79  dofs_scalar_ + dofs_vector_ + dofs_excitation);
80  excitation_ = Eigen::VectorXcd::Zero(dofs_scalar_);
81 
83  &system_matrix_, &excitation_, ansatz_space_mass_, ansatz_space_scalar_,
84  ansatz_space_vector_, wavenumber_, source);
85  return;
86  }
87  void stabilize() {
88  std::function<std::complex<double>(Eigen::Vector3d)> one =
89  [](Eigen::Vector3d in) { return std::complex<double>(1., 0.); };
90  DiscreteLinearForm<DirichletTrace<std::complex<double>>,
91  HelmholtzSingleLayerOperator>
92  const_lf(ansatz_space_scalar_);
93  const_lf.get_linear_form().set_function(one);
94  const_lf.compute();
95 
96  system_matrix_.bottomRows(dofs_scalar_) *= omega_ *
97  std::complex<double>(0., 1.) *
98  Constants::mu0 * Constants::eps0;
99  system_matrix_.leftCols(dofs_vector_) *=
100  1. / (omega_ * std::complex<double>(0., 1.) * Constants::mu0);
101 
102  std::complex<double> eigenvalues_average =
103  system_matrix_.trace() / ((double)system_matrix_.cols());
104 
105  Eigen::VectorXcd a = Eigen::VectorXcd::Zero(system_matrix_.cols());
106  a.bottomRows(dofs_scalar_) = const_lf.get_discrete_linear_form();
107 
108  system_matrix_ = system_matrix_ - eigenvalues_average * a * a.transpose();
109  }
111  // setters
113 
116  void set_wavenumber(std::complex<double> wavenumber) {
117  wavenumber_ = wavenumber;
118  }
119  void set_omega(double omega) { omega_ = omega; }
121  // getters
123  const MatrixFormat &get_system_matrix() const { return system_matrix_; }
127  const std::complex<double> get_wavenumber() { return wavenumber_; }
131  const int get_dofs_vector() { return dofs_vector_; }
135  const int get_dofs_scalar() { return dofs_scalar_; }
139  const Eigen::VectorXcd get_excitation() { return excitation_; }
144  return ansatz_space_scalar_;
145  }
146  const AnsatzSpace<MassMatrixScalarDisc> get_ansatz_space_mass() {
147  return ansatz_space_mass_;
148  }
150  // private member variables
152  private:
153  MatrixFormat system_matrix_;
154  Eigen::VectorXcd excitation_;
155 
156  AnsatzSpace<MassMatrixScalarDisc> ansatz_space_mass_;
157  AnsatzSpace<HelmholtzSingleLayerOperator> ansatz_space_scalar_;
158  AnsatzSpace<InductanceMatrix> ansatz_space_vector_;
159 
160  int dofs_scalar_;
161  int dofs_vector_;
162  double omega_;
163  std::complex<double> wavenumber_;
164 };
165 
166 } // namespace Bembel
167 #endif // BEMBEL_SRC_AUGMENTEDEFIE_AUGMENTEDEFIE_HPP_
The AnsatzSpace is the class that handles the assembly of the discrete basis.
Definition: AnsatzSpace.hpp:25
int get_polynomial_degree() const
Retrieves the polynomial degree of this AnsatzSpace.
int get_refinement_level() const
Retrieves the refinement level of this AnsatzSpace.
This class handles the assembly and storage of the system matrix.
void compute()
Assembles the system matrix without voltage source excitation.
const int get_dofs_vector()
Return number of degrees of freedom for the current.
void compute(VoltageSource source)
Assembles the system matrix with voltage source excitation.
const int get_dofs_scalar()
Return number of degrees of freedom for the potential.
const AnsatzSpace< HelmholtzSingleLayerOperator > get_ansatz_space_scalar()
Debug output for the excitation.
const Eigen::VectorXcd get_excitation()
Debug output for the excitation.
void set_wavenumber(std::complex< double > wavenumber)
Set wave number.
const std::complex< double > get_wavenumber()
Return wave number.
this class wraps a GeometryVector and provides some basic functionality, like reading Geometry files
Definition: Geometry.hpp:20
Routines for the evalutation of pointwise errors.
Definition: AnsatzSpace.hpp:14