12 #ifndef BEMBEL_SRC_HOMOGENISEDLAPLACE_COEFFICIENTS_HPP_
13 #define BEMBEL_SRC_HOMOGENISEDLAPLACE_COEFFICIENTS_HPP_
16 #define POINT_DEGREE 20
19 #include <Eigen/Dense>
20 #include <Bembel/HomogenisedLaplace>
21 #include <Bembel/Quadrature>
29 inline unsigned int getDegree(
double precision);
31 Eigen::VectorXd
getDisplacement(Eigen::MatrixXd ps_l, Eigen::MatrixXd ps_f,
32 Eigen::MatrixXd ps_b);
34 inline double k_mod(Eigen::Vector3d in);
36 inline Eigen::Vector3d
Dk_mod(Eigen::Vector3d in);
39 Eigen::MatrixXd ps_l, Eigen::MatrixXd ps_f, Eigen::MatrixXd ps_b);
62 Eigen::RowVectorXd difft;
64 Eigen::MatrixXd spherical_values_pre, spherical_values_pst, Dsolid_values_pre,
68 unsigned int Msquare = (POINT_DEGREE + 1) * (POINT_DEGREE + 1);
71 double scale, fac, norm;
74 Eigen::MatrixXd xs = GS[POINT_DEGREE].xi_;
75 xs -= 0.5 * Eigen::MatrixXd::Ones(xs.rows(), xs.cols());
77 Eigen::Vector3d ex(1.0, 0.0, 0.0);
78 Eigen::Vector3d ey(0.0, 1.0, 0.0);
79 Eigen::Vector3d ez(0.0, 0.0, 1.0);
81 Eigen::MatrixXd ps_left(3, xs.cols());
82 ps_left.row(0) = -0.5 * Eigen::VectorXd::Ones(xs.cols());
83 ps_left.block(1, 0, 2, xs.cols()) = xs.block(0, 0, 2, xs.cols());
85 Eigen::MatrixXd ps_front(3, xs.cols());
86 ps_front.row(0) = xs.row(0);
87 ps_front.row(1) = -0.5 * Eigen::VectorXd::Ones(xs.cols());
88 ps_front.row(2) = xs.row(1);
90 Eigen::MatrixXd ps_bottom(3, xs.cols());
91 ps_bottom.block(0, 0, 2, xs.cols()) = xs.block(0, 0, 2, xs.cols());
92 ps_bottom.row(2) = -0.5 * Eigen::VectorXd::Ones(xs.cols());
94 Eigen::VectorXd displacement =
getDisplacement(ps_left, ps_front, ps_bottom);
96 Eigen::MatrixXd systemMatrix(6 * Msquare, ((deg + 1) * (deg + 2)) / 2 - 1);
98 for (k = 0; k < Msquare; k++) {
108 spherical_values_pst);
110 for (n = 1; n <= deg; n++) {
111 scale = pow(norm, n);
113 * (spherical_values_pre.block(n * n + n, 0, n + 1, 1)
114 - spherical_values_pst.block(n * n + n, 0, n + 1, 1));
115 difft = Dsolid_values_pre.block(0, n * n + n, 1, n + 1)
116 - Dsolid_values_pst.block(0, n * n + n, 1, n + 1);
119 diff.segment(1, n) *= 2.0;
120 difft.segment(1, n) *= 2.0;
122 systemMatrix.block(k, (n * (n + 1)) / 2 - 1, 1, n + 1) = diff.transpose();
123 systemMatrix.block(k + Msquare, (n * (n + 1)) / 2 - 1, 1, n + 1) = difft;
135 spherical_values_pst);
137 for (n = 1; n <= deg; n++) {
138 scale = pow(norm, n);
140 * (spherical_values_pre.block(n * n + n, 0, n + 1, 1)
141 - spherical_values_pst.block(n * n + n, 0, n + 1, 1));
142 difft = Dsolid_values_pre.block(1, n * n + n, 1, n + 1)
143 - Dsolid_values_pst.block(1, n * n + n, 1, n + 1);
146 diff.segment(1, n) *= 2.0;
147 difft.segment(1, n) *= 2.0;
149 systemMatrix.block(k + 2 * Msquare, (n * (n + 1)) / 2 - 1, 1, n + 1) =
151 systemMatrix.block(k + 3 * Msquare, (n * (n + 1)) / 2 - 1, 1, n + 1) =
156 v = ps_bottom.col(k);
164 spherical_values_pst);
166 for (n = 1; n <= deg; n++) {
167 scale = pow(norm, n);
169 * (spherical_values_pre.block(n * n + n, 0, n + 1, 1)
170 - spherical_values_pst.block(n * n + n, 0, n + 1, 1));
171 difft = Dsolid_values_pre.block(2, n * n + n, 1, n + 1)
172 - Dsolid_values_pst.block(2, n * n + n, 1, n + 1);
175 diff.segment(1, n) *= 2.0;
176 difft.segment(1, n) *= 2.0;
178 systemMatrix.block(k + 4 * Msquare, (n * (n + 1)) / 2 - 1, 1, n + 1) =
180 systemMatrix.block(k + 5 * Msquare, (n * (n + 1)) / 2 - 1, 1, n + 1) =
186 Eigen::VectorXd coeffs(((deg + 1) * (deg + 2)) / 2);
188 coeffs.segment(1, ((deg + 1) * (deg + 2)) / 2 - 1) =
189 systemMatrix.colPivHouseholderQr().solve(-displacement);
192 Eigen::VectorXd coeffs_full((deg + 1) * (deg + 1));
194 for (n = 1; n <= deg; n++) {
195 coeffs_full(n * n + n) = coeffs((n * (n + 1)) / 2);
196 for (m = 1; m <= n; m++) {
197 coeffs_full(n * n + n + m) = coeffs((n * (n + 1)) / 2 + m);
198 coeffs_full(n * n + n - m) = coeffs((n * (n + 1)) / 2 + m);
204 ps_front, ps_bottom);
222 if (precision > 1e-4) {
224 }
else if (precision > 1e-6) {
239 Eigen::MatrixXd ps_b) {
241 std::function<double(Eigen::Vector3d)> u = [](Eigen::Vector3d in) {
244 std::function<Eigen::Vector3d(Eigen::Vector3d)> Du = [](Eigen::Vector3d in) {
248 unsigned int Msquare = (POINT_DEGREE + 1) * (POINT_DEGREE + 1);
251 Eigen::Vector3d ex(1.0, 0.0, 0.0);
252 Eigen::Vector3d ey(0.0, 1.0, 0.0);
253 Eigen::Vector3d ez(0.0, 0.0, 1.0);
256 Eigen::VectorXd d(6 * Msquare);
259 for (k = 0; k < Msquare; k++) {
260 tmp = Du(ps_l.col(k)) - Du(ps_l.col(k) + ex);
261 d(k) = u(ps_l.col(k)) - u(ps_l.col(k) + ex);
262 d(k + Msquare) = tmp(0);
266 for (k = 0; k < Msquare; k++) {
267 tmp = Du(ps_f.col(k)) - Du(ps_f.col(k) + ey);
268 d(k + 2 * Msquare) = u(ps_f.col(k)) - u(ps_f.col(k) + ey);
269 d(k + 3 * Msquare) = tmp(1);
273 for (k = 0; k < Msquare; k++) {
274 tmp = Du(ps_b.col(k)) - Du(ps_b.col(k) + ez);
275 d(k + 4 * Msquare) = u(ps_b.col(k)) - u(ps_b.col(k) + ez);
276 d(k + 5 * Msquare) = tmp(2);
286 inline double k_mod(Eigen::Vector3d in) {
291 for (i = -1; i <= 1; i++) {
292 for (j = -1; j <= 1; j++) {
293 for (k = -1; k <= 1; k++) {
294 m = Eigen::Vector3d(i, j, k);
295 r += 1.0 / ((in - m).norm());
303 r += (in.dot(in)) / 6.0;
312 inline Eigen::Vector3d
Dk_mod(Eigen::Vector3d in) {
313 Eigen::Vector3d r, s;
318 for (i = -1; i <= 1; i++) {
319 for (j = -1; j <= 1; j++) {
320 for (k = -1; k <= 1; k++) {
321 s = in - Eigen::Vector3d(i, j, k);
323 r -= s / (snorm * snorm * snorm);
347 Eigen::MatrixXd ps_l, Eigen::MatrixXd ps_f, Eigen::MatrixXd ps_b) {
351 Eigen::VectorXd ws = GS[POINT_DEGREE].w_;
353 Eigen::VectorXd cs_tmp(cs.rows());
359 for (k = 0; k < ps_l.cols(); k++) {
360 norm = ps_l.col(k).norm();
361 for (n = 1; n <= deg; n++) {
362 cs_tmp.segment(n * n, 2 * n + 1) = pow(norm, n)
363 * cs.segment(n * n, 2 * n + 1);
367 * (
k_mod(ps_l.col(k))
370 * (
k_mod(ps_f.col(k))
373 * (
k_mod(ps_b.col(k))
381 return -2.0 * sqrt(M_PI) * res;
Routines for the evalutation of pointwise errors.
Eigen::VectorXd getCoefficients(double precision)
Calculates the coefficients for the solid harmonics expansion of the periodic kernel .
double evaluate_sphericals(Eigen::Vector3d x, Eigen::VectorXd cs, unsigned int deg)
Evaluates the series for real coefficients, with the convenction that .
unsigned int getDegree(double precision)
Returns the degree of the sphericals expansion given a precision. Can be extended,...
Eigen::VectorXd getDisplacement(Eigen::MatrixXd ps_l, Eigen::MatrixXd ps_f, Eigen::MatrixXd ps_b)
Returns the right-hand side for the homogenised coefficient calculation.
Eigen::Vector3d Dk_mod(Eigen::Vector3d in)
Returns the gradient of the modified kernel .
double k_mod(Eigen::Vector3d in)
Returns the modified kernel .
Eigen::Matrix< double, 3, Eigen::Dynamic > Dsolid_harmonics_full(Eigen::Vector3d x, unsigned int N, Eigen::MatrixXd spherical_val)
Calculates all gradients of the solid harmonics, given the Legendre Coefficients L.
Eigen::Matrix< double, Eigen::Dynamic, 2 > spherical_harmonics_full(Eigen::Vector3d x, unsigned int N)
Calculates the the spherical harmonics , ordered by .
double calculateFirstCoefficient(Eigen::VectorXd cs, unsigned int deg, Eigen::MatrixXd ps_l, Eigen::MatrixXd ps_f, Eigen::MatrixXd ps_b)
Calculates the first coefficient such that the mean of the kernel vanishes.