12#ifndef BEMBEL_SRC_UTIL_SPHERICALS_HPP_
13#define BEMBEL_SRC_UTIL_SPHERICALS_HPP_
26 unsigned int deg,
bool grad);
32 Eigen::VectorXd cs,
unsigned int deg);
35 Eigen::Vector3d
x,
unsigned int N);
38 Eigen::Vector2d
y1, Eigen::Vector2d
y2);
44 unsigned int n, Eigen::VectorXd
L,
double y_re,
double y_im);
74 assert(
abs(
x.norm() - 1) < Constants::generic_tolerance);
82 for (
m = 0;
m < deg - 1;
m++) {
95 r +=
fac * cs((
m + 1) * (
m + 2) +
m) *
z2[0];
96 for (
n =
m + 2;
n < deg;
n++) {
112 r += 2 * cs((deg - 1) * (deg + 1)) *
z1[0];
129 unsigned int deg,
bool grad) {
137 if (
grad && deg <= 1) {
139 }
else if (!
grad && deg <= 1) {
140 return cs(0) *
z1[0];
146 for (
m = 0;
m < deg - 1;
m++) {
173 for (
n =
m + 2;
n < deg;
n++) {
200 r +=
fac_tot * cs((deg - 1) * (deg + 1)) *
z1[0];
220 assert(
abs(
x.norm() - 1) < Constants::generic_tolerance);
225 dr = Eigen::Vector3d(0.0, 0.0, 0.0);
231 for (
m = 1;
m < deg - 1;
m++) {
237 dr(0) += 2 *
m * (cs(
m * (
m + 1) +
m) *
z1[0]);
239 dr(0) += 2 *
m * (cs((
m + 1) * (
m + 2) +
m) *
z2[0]);
241 dr(1) -= 2 *
m * (cs(
m * (
m + 1) +
m) *
z1[1]);
243 dr(1) -= 2 *
m * (cs((
m + 1) * (
m + 2) +
m) *
z2[1]);
249 * (cs(
m * (
m + 1) + (
m - 1)) *
z1[0]
250 + cs(
m * (
m + 1) - (
m - 1)) *
z1[1]);
252 * (cs((
m + 1) * (
m + 2) + (
m - 1)) *
z2[0]
253 + cs((
m + 1) * (
m + 2) - (
m - 1)) *
z2[1]);
259 * (cs((
m + 1) * (
m + 2) + (
m - 1)) *
z2[0]);
263 for (
n =
m + 2;
n < deg;
n++) {
269 dr(0) += 2 *
m * (cs(
n * (
n + 1) +
m) *
z3[0]);
270 dr(1) -= 2 *
m * (cs(
n * (
n + 1) +
m) *
z3[1]);
272 * (cs(
n * (
n + 1) + (
m - 1)) *
z3[0]);
282 dr(0) += (deg - 1) * (2 * cs((deg - 1) * (deg + 1)) *
z1[0]);
284 dr(1) -= (deg - 1) * (2 * cs((deg - 1) * (deg + 1)) *
z1[1]);
286 dr(2) += 2 *
sqrt(2 * (deg - 1))
287 * (cs(deg * (deg - 1) + (deg - 2)) *
z1[0]
288 + cs(deg * (deg - 1) - (deg - 2)) *
z1[1]);
303 Eigen::VectorXd cs,
unsigned int deg) {
306 Eigen::Vector3d
dr,
y;
312 dr = Eigen::Vector3d(0.0, 0.0, 0.0);
320 for (
m = 1;
m < deg - 1;
m++) {
336 * (cs(
m * (
m + 1) + (
m - 1)) *
z1[0]
337 + cs(
m * (
m + 1) - (
m - 1)) *
z1[1]);
339 * (cs((
m + 1) * (
m + 2) + (
m - 1)) *
z2[0]
340 + cs((
m + 1) * (
m + 2) - (
m - 1)) *
z2[1]);
345 * (cs((
m + 1) * (
m + 2) + (
m - 1)) *
z2[0]);
350 for (
n =
m + 2;
n < deg;
n++) {
360 * (cs(
n * (
n + 1) + (
m - 1)) *
z3[0]);
371 dr(0) += (deg - 1) *
r_n3 * (2 * cs((deg - 1) * (deg + 1)) *
z1[0]);
372 dr(1) -= (deg - 1) *
r_n3 * (2 * cs((deg - 1) * (deg + 1)) *
z1[1]);
374 * (cs(deg * (deg - 1) + (deg - 2)) *
z1[0]
375 + cs(deg * (deg - 1) - (deg - 2)) *
z1[1]);
389 Eigen::Vector3d
x,
unsigned int N) {
391 Eigen::VectorXd
real((
N + 1) * (
N + 1));
392 Eigen::VectorXd
imag((
N + 1) * (
N + 1));
394 Eigen::Vector3d
y =
x /
x.norm();
405 for (
n = 1;
n <=
N;
n++) {
406 for (
m = 0;
m <
n - 1;
m++) {
440 z1(0) =
real((
n - 1) * (
n - 1) +
n - 1 +
n - 1);
441 z2(0) =
imag((
n - 1) * (
n - 1) +
n - 1 +
n - 1);
453 Eigen::MatrixXd
res((
N + 1) * (
N + 1), 2);
464 Eigen::Vector2d
y1, Eigen::Vector2d
y2) {
469 if ((
m == 0) && (
n == 0)) {
470 z(0) = 0.5 /
sqrt(pi);
473 z(0) =
sqrt((2 *
m + 1.0) / (2 *
m)) * (
x(0) *
y1(0) -
x(1) *
y2(0));
474 z(1) =
sqrt((2 *
m + 1.0) / (2 *
m)) * (
x(0) *
y2(0) +
x(1) *
y1(0));
475 }
else if (
m + 1 ==
n) {
479 z(0) =
sqrt((2 *
n + 1.0) / ((
n -
m) * (
n +
m)))
481 -
sqrt(((
n +
m - 1.0) * (
n -
m - 1.0)) / (2 *
n - 3)) *
y1(1));
482 z(1) =
sqrt((2 *
n + 1.0) / ((
n -
m) * (
n +
m)))
484 -
sqrt(((
n +
m - 1.0) * (
n -
m - 1.0)) / (2 *
n - 3)) *
y2(1));
496 Eigen::Matrix<double, 3, 2>
z;
498 Eigen::MatrixXd
reals(3, (
N + 1) * (
N + 1)),
imags(3, (
N + 1) * (
N + 1));
502 for (
n = 0;
n <=
N;
n++) {
503 for (
m = 0;
m <=
n;
m++) {
533 unsigned int n, Eigen::VectorXd
L) {
540 Eigen::Matrix<double, 3, 2>
z;
543 z(0, 0) =
z(0, 1) =
z(2, 1) = 0;
547 z(2, 0) =
L((
n * (
n + 1)) / 2 + 1);
553 z(0, 0) =
L((
n * (
n + 1)) / 2 +
m);
559 z(2, 0) =
L((
n * (
n + 1)) / 2 +
m + 1);
561 z(0, 1) =
z(2, 1) = 0;
563 c =
x(0) *
z(2, 0) -
x(1) *
z(2, 1);
564 z(2, 1) =
x(0) *
z(2, 1) +
x(1) *
z(2, 0);
567 for (
i = 1;
i <
m;
i++) {
568 c =
x(0) *
z(0, 0) -
x(1) *
z(0, 1);
569 z(0, 1) =
x(0) *
z(0, 1) +
x(1) *
z(0, 0);
572 c =
x(0) *
z(2, 0) -
x(1) *
z(2, 1);
573 z(2, 1) =
x(0) *
z(2, 1) +
x(1) *
z(2, 0);
594 unsigned int n, Eigen::VectorXd
L,
double y_re,
double y_im) {
599 Eigen::Vector3d
x =
y /
r;
600 Eigen::Matrix<double, 3, 2>
z_harm;
646 Eigen::Matrix<double, 3, 2>
z_rad;
678 Eigen::VectorXd
L(((
N + 1) * (
N + 2)) / 2);
688 for (
n = 2;
n <=
N;
n++) {
689 s = (
n * (
n + 1)) / 2;
690 for (
m = 0;
m <
n - 1;
m++) {
691 L(
s +
m) = ((2 *
n - 1) *
t *
L((
n * (
n - 1)) / 2 +
m)
692 - (
n +
m - 1) *
L(((
n - 1) * (
n - 2)) / 2 +
m)) / (
n -
m);
697 L(
s +
m) = (2 *
m + 1) *
t *
L((
m * (
m + 1)) / 2 +
m);
701 L(
s +
m) = (2 *
m - 1) *
L((
n * (
n - 1)) / 2 +
n - 1);
711 double c =
sqrt((2 *
n + 1) / (4 * pi));
713 for (
i = 0;
i <
m;
i++) {
728 M(0, 0) =
r *
r -
z(0) *
z(0);
729 M(1, 1) =
r *
r -
z(1) *
z(1);
730 M(2, 2) =
r *
r -
z(2) *
z(2);
732 M(1, 0) =
M(0, 1) = -
z(0) *
z(1);
733 M(2, 0) =
M(0, 2) = -
z(0) *
z(2);
734 M(2, 1) =
M(1, 2) = -
z(1) *
z(2);
755 for (
k = 1;
k <
ul;
k++) {
Routines for the evalutation of pointwise errors.
double evaluate_sphericals(Eigen::Vector3d x, Eigen::VectorXd cs, unsigned int deg)
Evaluates the series for real coefficients, with the convenction that .
Eigen::Vector3d evaluate_dsolid_sphericals(Eigen::Vector3d x, Eigen::VectorXd cs, unsigned int deg)
Evaluates the series for real coefficients.
Eigen::VectorXd legendreFull(unsigned int N, double t)
Returns the values of the spherical polynomials .
Eigen::Matrix< double, 3, 2 > dsolid_spherical_prev(Eigen::Vector3d y, int m, unsigned int n, Eigen::VectorXd L, double y_re, double y_im)
Calculates the derivative of the solid harmonics function at the point with the spherical values.
double pow_int(double x, int n)
returns the -th power of without using pow.
double constant(int m, unsigned int n)
gives the norming factor of the spherical polynomials
double evaluate_solid_sphericals(Eigen::Vector3d x, Eigen::VectorXd cs, unsigned int deg, bool grad)
Evaluates the series for real coefficients cs if grad is false, and for real coefficients cs if gra...
Eigen::Matrix< double, 3, 2 > dspherical_prev(Eigen::Vector3d x, int m, unsigned int n, Eigen::VectorXd L)
Calculates based on the Legendre Coefficients L.
constexpr int getFunctionSpaceOutputDimension()
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::Vector3d evaluate_dsphericals(Eigen::Vector3d x, Eigen::VectorXd cs, unsigned int deg)
Evaluates the series for real coefficients.
Eigen::Matrix< double, Eigen::Dynamic, 2 > spherical_harmonics_full(Eigen::Vector3d x, unsigned int N)
Calculates the the spherical harmonics , ordered by .
Eigen::Matrix3d functionalMatrix(Eigen::Vector3d z)
gives times the Jacobi Matrix of the transformation
Eigen::Vector2d spherical_prev(Eigen::Vector3d x, int m, int n, Eigen::Vector2d y1, Eigen::Vector2d y2)
Calculates the spherical harmonic based on previous values.