Bembel
 
Loading...
Searching...
No Matches
AugmentedEFIEAssembler.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_AUGMENTEDEFIEASSEMBLER_HPP_
12#define BEMBEL_SRC_AUGMENTEDEFIE_AUGMENTEDEFIEASSEMBLER_HPP_
13
14namespace Bembel {
15template <typename MatrixFormat>
21template <>
23 public:
29 static std::unique_ptr<Eigen::MatrixXcd> compute(
30 Eigen::MatrixXcd *system_matrix,
34 const std::complex<double> wavenumber) {
35 const int dofs_scalar = ansatz_space_scalar.get_number_of_dofs();
36 const int dofs_vector = ansatz_space_vector.get_number_of_dofs();
37
39
42 incidence_matrix.compute();
43
45
47 mass_matrix.compute();
48
50
53 capacitive_operator.get_linear_operator().set_wavenumber(wavenumber);
54 capacitive_operator.compute();
55
56 std::unique_ptr<Eigen::MatrixXcd> P_times_mass_inverse(
57 new Eigen::MatrixXcd);
59 capacitive_operator.get_discrete_operator() / Constants::eps0 *
60 Eigen::MatrixXcd(mass_matrix.get_discrete_operator()).inverse();
61
64
66 }
75 Eigen::MatrixXcd *system_matrix, Eigen::VectorXcd *excitation,
79 const std::complex<double> wavenumber, const VoltageSource &source) {
80 assert(ansatz_space_scalar.get_polynomial_degree() == 0 &&
81 "This works only for lowest order!");
82 const int refinement_level = ansatz_space_scalar.get_refinement_level();
83 const int dofs_scalar = ansatz_space_scalar.get_number_of_dofs();
84 const int dofs_vector = ansatz_space_vector.get_number_of_dofs();
85
86 std::unique_ptr<Eigen::MatrixXcd> P_times_mass_inverse =
89
92 ansatz_space_scalar.get_number_of_dofs());
95 return;
96 }
97
98 private:
104 static void assembleZ(
105 Eigen::MatrixXcd *system_matrix,
107 const std::complex<double> wavenumber) {
110 disc_op.get_linear_operator().set_wavenumber(wavenumber);
111 disc_op.compute();
112
113 const int dofs_vector = ansatz_space_vector.get_number_of_dofs();
114 std::complex<double> omega =
115 wavenumber / std::sqrt(Constants::mu0 * Constants::eps0);
116 system_matrix->block(0, 0, dofs_vector, dofs_vector) =
117 Constants::mu0 * omega * std::complex<double>(0., 1.) *
118 disc_op.get_discrete_operator();
119 return;
120 }
125 static void assembleS(
126 Eigen::MatrixXcd *system_matrix,
129 const int dofs_vector, const int dofs_scalar) {
131 incidence_matrix.get_incidence_matrix();
132 return;
133 }
138 static void assembleM(Eigen::MatrixXcd *system_matrix,
140 const std::complex<double> wavenumber,
141 const int dofs_vector, const int dofs_scalar) {
142 std::complex<double> omega =
143 wavenumber / std::sqrt(Constants::mu0 * Constants::eps0);
145 -omega * std::complex<double>(0., 1.) *
146 mass_matrix.get_discrete_operator();
147 return;
148 }
153 static void assembleP(
154 Eigen::MatrixXcd *system_matrix,
156 const std::unique_ptr<Eigen::MatrixXcd> &P_times_mass_inverse,
159 const std::complex<double> wavenumber, const int dofs_vector,
160 const int dofs_scalar) {
163 incident_matrix.get_incidence_matrix().transpose();
164 return;
165 }
169 static void assembleV(
170 Eigen::MatrixXcd *system_matrix, Eigen::VectorXcd *excitation,
172 const std::unique_ptr<Eigen::MatrixXcd> &P_times_mass_inverse,
173 VoltageSource source, const int dofs_vector, const int dofs_scalar) {
174 Eigen::MatrixXcd V = get_voltage_incidence_matrix(
175 excitation, source, ansatz_space_scalar.get_number_of_dofs(),
176 ansatz_space_scalar.get_polynomial_degree(),
177 ansatz_space_scalar.get_refinement_level());
178
180 V.rows()) = *P_times_mass_inverse * V.transpose();
182 dofs_scalar) = V;
183 return;
184 }
194 static void assembleA(Eigen::MatrixXcd *system_matrix,
195 const VoltageSource &source, const int refinement_level,
196 const int dofs_vector, const int dofs_scalar) {
197 const int dofs_excitation_positive =
198 source.positive_.size() * (1 << refinement_level);
199 const int dofs_excitation_negative =
200 source.negative_.size() * (1 << refinement_level);
201 const int dofs_excitation =
203 Eigen::MatrixXcd A = Eigen::MatrixXcd::Ones(dofs_excitation, 2);
204 A.block(1, 1, dofs_excitation_negative, 1) =
205 Eigen::VectorXcd::Zero(dofs_excitation_negative);
207 Eigen::VectorXcd::Zero(dofs_excitation_positive);
208 A(0, 0) = 1;
209 A(0, 1) = -1;
210
211 const int dofs_basis = dofs_vector + dofs_scalar;
213 dofs_excitation, 2) = A;
215 dofs_excitation) = A.transpose();
216 return;
217 }
218 static Eigen::MatrixXcd get_voltage_incidence_matrix(
219 Eigen::VectorXcd *excitation, VoltageSource source, const int dofs_scalar,
220 const int polynomial_degree, const int refinement_level) {
221 const int elements_per_edge = (1 << refinement_level);
223 const int dofs_excitation_V =
224 (source.positive_.size() + source.negative_.size()) *
226 1;
227 const int number_of_basisfunctions = polynomial_degree + elements_per_edge;
228
229 Eigen::MatrixXcd ret =
230 Eigen::MatrixXcd::Zero(dofs_excitation_V, dofs_scalar);
231
232 const int number_of_patches_negative = source.negative_.size();
233 int row_count = 1;
234 for (auto i = 0; i < number_of_patches_negative; ++i) {
235 std::vector<int> edge_dofs = GlueRoutines::getEdgeDofIndices(
236 source.negative_[i][1], number_of_basisfunctions,
238 source.negative_[i][0] * num_elements_per_patch);
239 for (auto dof : edge_dofs) {
240 ret(row_count, dof) = -1;
241 excitation[0](dof) = -1;
242 ++row_count;
243 }
244 }
245
246 const int number_of_patches_positive = source.positive_.size();
247 for (auto i = 0; i < number_of_patches_positive; ++i) {
248 std::vector<int> edge_dofs = GlueRoutines::getEdgeDofIndices(
249 source.positive_[i][1], number_of_basisfunctions,
251 source.positive_[i][0] * num_elements_per_patch);
252 for (auto dof : edge_dofs) {
253 ret(row_count, dof) = -1;
254 excitation[0](dof) = 1;
255 ++row_count;
256 }
257 }
258 return ret;
259 }
260};
261} // namespace Bembel
262#endif // BEMBEL_SRC_AUGMENTEDEFIE_AUGMENTEDEFIEASSEMBLER_HPP_
The AnsatzSpace is the class that handles the assembly of the discrete basis.
Routines for the evalutation of pointwise errors.
constexpr int getFunctionSpaceOutputDimension()
static std::unique_ptr< Eigen::MatrixXcd > compute(Eigen::MatrixXcd *system_matrix, const AnsatzSpace< MassMatrixScalarDisc > &ansatz_space_mass, const AnsatzSpace< HelmholtzSingleLayerOperator > &ansatz_space_scalar, const AnsatzSpace< InductanceMatrix > &ansatz_space_vector, const std::complex< double > wavenumber)
static void compute_matrix_and_excitation(Eigen::MatrixXcd *system_matrix, Eigen::VectorXcd *excitation, const AnsatzSpace< MassMatrixScalarDisc > &ansatz_space_mass, const AnsatzSpace< HelmholtzSingleLayerOperator > &ansatz_space_scalar, const AnsatzSpace< InductanceMatrix > &ansatz_space_vector, const std::complex< double > wavenumber, const VoltageSource &source)