Bembel
 
Loading...
Searching...
No Matches
Basis.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
12#ifndef BEMBEL_SRC_SPLINE_BASIS_HPP_
13#define BEMBEL_SRC_SPLINE_BASIS_HPP_
14
15namespace Bembel {
22namespace Basis {
23
24// These typedefs are required for the superspace to store the correct functions
25template <typename Scalar>
26using funptr_voidOut_scalarptrScalarDoubleIn =
27 void (*)(Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *, Scalar, double);
28template <typename Scalar>
29using funptr_voidOut_scalarptrScalarVec2In = void (*)(
30 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *, Scalar, Eigen::Vector2d);
31template <typename Scalar>
32using funptr_voidOut_scalarptrScalarVec2Vec2In =
33 void (*)(Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> *, Scalar,
34 Eigen::Vector2d, Eigen::Vector2d);
35
36// These typedefs are a convenience to make the above human-readable
37template <typename Scalar>
38using funptr_phi = funptr_voidOut_scalarptrScalarDoubleIn<Scalar>;
39template <typename Scalar>
40using funptr_phidx = funptr_voidOut_scalarptrScalarDoubleIn<Scalar>;
41template <typename Scalar>
42using funptr_phiphi = funptr_voidOut_scalarptrScalarVec2In<Scalar>;
43template <typename Scalar>
44using funptr_phiphidx = funptr_voidOut_scalarptrScalarVec2In<Scalar>;
45template <typename Scalar>
46using funptr_phiphidy = funptr_voidOut_scalarptrScalarVec2In<Scalar>;
47template <typename Scalar>
48using funptr_phitimesphi = funptr_voidOut_scalarptrScalarVec2Vec2In<Scalar>;
49template <typename Scalar>
50using funptr_divphitimesdivphi =
51 funptr_voidOut_scalarptrScalarVec2Vec2In<Scalar>;
52
57template <int P, typename Scalar>
58inline void phi_(Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c, Scalar w,
59 double x) {
60 constexpr int I = P + 1;
61 double base[I];
63 for (int i = 0; i < I; i++) (*c)(i) += w * base[i];
64 return;
65}
66
71template <int P, typename Scalar>
72inline void phi_dx_(Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c, Scalar w,
73 double x) {
74 constexpr int I = P + 1;
75 double base[I];
77 for (int i = 0; i < I; i++) (*c)(i) += w * base[i];
78 return;
79}
80
85template <int P, typename Scalar>
86inline void phiphi_(Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c, Scalar w,
87 Eigen::Vector2d a) {
88 constexpr int I = P + 1;
89 double X[I], Y[I];
92
93 for (int iy = 0; iy < I; iy++)
94 for (int ix = 0; ix < I; ix++) (*c)(iy * I + ix) += w * X[ix] * Y[iy];
95
96 return;
97}
98
104template <int P, typename Scalar>
105inline void phiphi_dx_(Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c, Scalar w,
106 Eigen::Vector2d a) {
107 constexpr int I = P + 1;
108 double dX[I], Y[I];
111
112 for (int iy = 0; iy < I; iy++)
113 for (int ix = 0; ix < I; ix++) (*c)(iy * I + ix) += w * dX[ix] * Y[iy];
114
115 return;
116}
117
123template <int P, typename Scalar>
124inline void phiphi_dy_(Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c, Scalar w,
125 Eigen::Vector2d a) {
126 constexpr int I = P + 1;
127 double X[I], dY[I];
130
131 for (int iy = 0; iy < I; iy++)
132 for (int ix = 0; ix < I; ix++) (*c)(iy * I + ix) += w * X[ix] * dY[iy];
133 return;
134}
135
141template <int P, typename Scalar>
142void Phi_times_Phi_(Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> *c,
143 Scalar w, Eigen::Vector2d xi, Eigen::Vector2d eta) {
144 constexpr int I = P + 1;
145 Scalar a[I * I];
146 double b[I * I], X[I], Y[I];
147
150
151 for (int iy = 0; iy < I; iy++)
152 for (int ix = 0; ix < I; ix++) a[iy * I + ix] = w * X[ix] * Y[iy];
153
156
157 for (int iy = 0; iy < I; iy++)
158 for (int ix = 0; ix < I; ix++) b[iy * I + ix] = X[ix] * Y[iy];
159
160 for (int i = 0; i < (I * I); i++)
161 for (int j = 0; j < (I * I); j++) (*c)(i, j) += a[i] * b[j];
162
163 return;
164}
165
170template <int P, typename Scalar>
172 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> *c, Scalar weight,
173 Eigen::Vector2d xi, Eigen::Vector2d eta) {
174 constexpr int I = P + 1;
175 constexpr int I2 = I * I;
176 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> a_dx(I2);
177 a_dx.setZero();
178 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> a_dy(I2);
179 a_dy.setZero();
180 Eigen::VectorXd b_dx(I2);
181 b_dx.setZero();
182 Eigen::VectorXd b_dy(I2);
183 b_dy.setZero();
184
187 phiphi_dx_<P>(&b_dx, 1., eta);
188 phiphi_dy_<P>(&b_dy, 1., eta);
189
190 for (int i = 0; i < I2; ++i)
191 for (int j = 0; j < I2; ++j) (*c)(i, j) += a_dx[i] * b_dx[j];
192 for (int i = 0; i < I2; ++i)
193 for (int j = 0; j < I2; ++j) (*c)(i, j + I2) += a_dx[i] * b_dy[j];
194 for (int i = 0; i < I2; ++i)
195 for (int j = 0; j < I2; ++j) (*c)(i + I2, j) += a_dy[i] * b_dx[j];
196 for (int i = 0; i < I2; ++i)
197 for (int j = 0; j < I2; ++j) (*c)(i + I2, j + I2) += a_dy[i] * b_dy[j];
198
199 return;
200}
201
208template <int P, typename Scalar>
210 public:
211 // These methods are for calling the functions
212 static inline void phi(int p, Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c,
213 Scalar w, double x) {
214 return P == p ? phi_<P, Scalar>(c, w, x)
216 }
217 static inline void phiDx(int p, Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c,
218 Scalar w, double x) {
219 return P == p ? phi_dx_<P, Scalar>(c, w, x)
221 }
222 static inline void phiPhi(int p, Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c,
223 Scalar w, Eigen::Vector2d a) {
224 return P == p ? phiphi_<P, Scalar>(c, w, a)
226 }
227 static inline void phiPhiDx(int p,
228 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c,
229 Scalar w, Eigen::Vector2d a) {
230 return P == p ? phiphi_dx_<P, Scalar>(c, w, a)
232 }
233 static inline void phiPhiDy(int p,
234 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c,
235 Scalar w, Eigen::Vector2d a) {
236 return P == p ? phiphi_dy_<P, Scalar>(c, w, a)
238 }
239 static inline void phiTimesPhi(
240 int p, Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> *c, Scalar w,
241 Eigen::Vector2d xi, Eigen::Vector2d eta) {
242 return P == p ? Phi_times_Phi_<P, Scalar>(c, w, xi, eta)
244 xi, eta);
245 }
246 static inline void divPhiTimesDivPhi(
247 int p, Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> *c,
248 Scalar weight, Eigen::Vector2d xi, Eigen::Vector2d eta) {
249 return P == p ? Div_Phi_times_Div_Phi_<P>(c, weight, xi, eta)
251 p, c, weight, xi, eta);
252 }
253 // These methods are for storing the functions for a given p, i.e., return
254 // the function pointers
255 static constexpr funptr_phi<Scalar> funPtrPhi(int p) {
256 return P == p ? &phi_<P, Scalar>
258 }
259 static constexpr funptr_phidx<Scalar> funPtrPhiDx(int p) {
260 return P == p ? &phi_dx_<P, Scalar>
262 }
263 static constexpr funptr_phiphi<Scalar> funPtrPhiPhi(int p) {
264 return P == p ? &phiphi_<P, Scalar>
266 }
267 static constexpr funptr_phiphidx<Scalar> funPtrPhiPhiDx(int p) {
268 return P == p ? &phiphi_dx_<P, Scalar>
270 }
271 static constexpr funptr_phiphidy<Scalar> funPtrPhiPhiDy(int p) {
272 return P == p ? &phiphi_dy_<P, Scalar>
274 }
275 static constexpr funptr_phitimesphi<Scalar> funPtrPhiTimesPhi(int p) {
276 return P == p ? &Phi_times_Phi_<P, Scalar>
278 }
279 static constexpr funptr_divphitimesdivphi<Scalar> funPtrDivPhiTimesDivPhi(
280 int p) {
281 return P == p
284 p);
285 }
286};
287
288// Anchors of the recursions above
289template <typename Scalar>
290class PSpecificBasisHandler<0, Scalar>
292 public:
293 static inline void phi(int p, Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c,
294 Scalar w, double x) {
295 return phi_<0, Scalar>(c, w, x);
296 }
297 static inline void phiDx(int p, Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c,
298 Scalar w, double x) {
299 return phi_dx_<0, Scalar>(c, w, x);
300 }
301 static inline void phiPhi(int p, Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c,
302 Scalar w, Eigen::Vector2d a) {
303 return phiphi_<0, Scalar>(c, w, a);
304 }
305 static inline void phiPhiDx(int p,
306 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c,
307 Scalar w, Eigen::Vector2d a) {
308 return phiphi_dx_<0, Scalar>(c, w, a);
309 }
310 static inline void phiPhiDy(int p,
311 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> *c,
312 Scalar w, Eigen::Vector2d a) {
313 return phiphi_dy_<0, Scalar>(c, w, a);
314 }
315 static inline void phiTimesPhi(
316 int p, Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> *c, Scalar w,
317 Eigen::Vector2d xi, Eigen::Vector2d eta) {
319 }
320 static inline void divPhiTimesDivPhi(
321 int p, Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> *c,
322 Scalar weight, Eigen::Vector2d xi, Eigen::Vector2d eta) {
324 }
325
326 static constexpr funptr_phi<Scalar> funPtrPhi(int p) {
327 return &phi_<0, Scalar>;
328 }
329 static constexpr funptr_phidx<Scalar> funPtrPhiDx(int p) {
330 return &phi_dx_<0, Scalar>;
331 }
332 static constexpr funptr_phiphi<Scalar> funPtrPhiPhi(int p) {
333 return &phiphi_<0, Scalar>;
334 }
335 static constexpr funptr_phiphidx<Scalar> funPtrPhiPhiDx(int p) {
336 return &phiphi_dx_<0, Scalar>;
337 }
338 static constexpr funptr_phiphidy<Scalar> funPtrPhiPhiDy(int p) {
339 return &phiphi_dy_<0, Scalar>;
340 }
341 static constexpr funptr_phitimesphi<Scalar> funPtrPhiTimesPhi(int p) {
343 }
344 static constexpr funptr_divphitimesdivphi<Scalar> funPtrDivPhiTimesDivPhi(
345 int p) {
347 }
348};
349
351template <typename Scalar>
353
354} // namespace Basis
355} // namespace Bembel
356
357#endif // BEMBEL_SRC_SPLINE_BASIS_HPP_
The functions above have a fixed compile time polynomial degree. The PSpecificBasis handler is used t...
Definition Basis.hpp:209
These routines implement a template recursion that allows to choose a compile time instantiation of a...
void phiphi_(Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > *c, Scalar w, Eigen::Vector2d a)
evaluates the 2D tensor product basis at a point a in [0,1]^2
Definition Basis.hpp:86
void phi_dx_(Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > *c, Scalar w, double x)
evaluates the derivative of phi
Definition Basis.hpp:72
void phiphi_dy_(Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > *c, Scalar w, Eigen::Vector2d a)
evaluates the y-derivative of the 2D tensor product basis at a point a in [0,1]^2
Definition Basis.hpp:124
void phiphi_dx_(Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > *c, Scalar w, Eigen::Vector2d a)
evaluates the x-derivative of the 2D tensor product basis at a point a in [0,1]^2
Definition Basis.hpp:105
void Phi_times_Phi_(Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > *c, Scalar w, Eigen::Vector2d xi, Eigen::Vector2d eta)
evaluates the interaction of two phiphis, one at xi and one at eta. Used for e.g. gram matrices.
Definition Basis.hpp:142
void Div_Phi_times_Div_Phi_(Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > *c, Scalar weight, Eigen::Vector2d xi, Eigen::Vector2d eta)
same as above, just using the divergence
Definition Basis.hpp:171
void phi_(Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > *c, Scalar w, double x)
evaluates the 1D basis at x weighted with a quadrature weight w
Definition Basis.hpp:58
Routines for the evalutation of pointwise errors.
constexpr int getFunctionSpaceOutputDimension()