VM2D 1.14
Vortex methods for 2D flows simulation
Loading...
Searching...
No Matches
special_functions.h
Go to the documentation of this file.
1#pragma once
2#include <vector>
3#include <complex>
4#include "utils.h"
5#include "simple_math.h"
6#include <unordered_map>
7//#include "cuda_utils.h"
8
9namespace fmm {
10
11// associated Legendre(n,m), n=0..N-1, m=0..n
12__HOST__ __DEVICE__ inline void ComputePnm(int N, double theta, double* Pnm)
13{
14#ifdef __NVCC__
15 double x, y;
16 sincos(theta, &y, &x);
17#else
18 auto x = cos(theta);
19 auto y = sin(theta);
20#endif
21 Pnm[0] = 1;
22 for (int n = 1; n < N; ++n)
23 {
24 for (int m = 0; m <= n - 2; ++m)
25 {
26 Pnm[n * (n + 1) / 2 + m] = ((2 * n - 1) * x * Pnm[(n - 1) * n / 2 + m] - (n + m - 1) * Pnm[(n - 2) * (n - 1) / 2 + m]) / (n - m);
27 }
28 Pnm[n * (n + 1) / 2 + n - 1] = Pnm[(n - 1) * n / 2 + n - 1] * x * (2 * n - 1);
29 Pnm[n * (n + 1) / 2 + n] = Pnm[(n - 1) * n / 2 + n - 1] * y * (1 - 2 * n);
30 }
31}
32// Knm = sqrt{(n - |m|)! / (n + |m|)!} - normalization coefficient for Spherical harmonic Ynm
33// computes only m >= 0
34[[deprecated("Use only when constexpr Knm unavailable")]]
35treevector<double> ComputeKnm(int N);
36
37// Anm = (-1)^n / sqrt{(n-m)!(n+m)!}
38[[deprecated("Use only when constexpr Anm unavailable")]]
39treevector<double> ComputeAnm(int N);
40
41// WignerD(n,m,k), n=0..N-1, m=0..n, k=-n..n
42std::vector<double> ComputeWignerD(int N, double theta);
43
44namespace detail {
45
46 inline double constexpr sqrtNewton(double x, double curr, double prev)
47 {
48 return (prev - curr) / curr < 1.e-16 && (prev - curr) / curr > -1.e-16 ? curr : sqrtNewton(x, 0.5 * (curr + x / curr), curr);
49 }
50
51 inline double constexpr constexpr_sqrt(double x)
52 {
53 return sqrtNewton(x, x, 0);
54 }
55
56 template <int N>
58 {
59 std::array<double, N * (N + 1) / 2> Knm;
61 {
62 Knm[0] = 1.0;
63 for (int n = 1; n < N; ++n)
64 {
65 for (int m = 0; m <= n - 1; ++m)
66 Knm[n * (n + 1) / 2 + m] = Knm[n * (n - 1) / 2 + m] * (n - m) / (n + m);
67 Knm[n * (n + 1) / 2 + n] = Knm[n * (n + 1) / 2 + n - 1] / (2 * n);
68 }
69 for (int n = 1; n < N; ++n)
70 {
71 for (int m = 0; m <= n; ++m)
73 Knm[n * (n + 1) / 2 + m] = constexpr_sqrt(Knm[n * (n + 1) / 2 + m]);
74#else
75 Knm[n * (n + 1) / 2 + m] = sqrt(Knm[n * (n + 1) / 2 + m]);
76#endif
77 }
78 }
79 FMM_CONSTEXPR double operator()(int n, int m) const
80 {
81 return Knm[n * (n + 1) / 2 + m];
82 }
83 };
84
86
87 template <int N>
89 {
90 std::array<double, 2 * N * (2 * N + 1) / 2> Anm;
92 {
93 Anm[0] = 1.0;
94 for (int n = 1; n < 2 * N; ++n)
95 {
96 for (int m = 0; m <= n - 1; ++m)
97 Anm[n * (n + 1) / 2 + m] = Anm[(n - 1) * n / 2 + m] * (n - m) * (n + m);
98 Anm[n * (n + 1) / 2 + n] = Anm[n * (n + 1) / 2 + n - 1] * 2 * n;
99 }
100 for (int n = 1; n < 2 * N; ++n)
101 {
102 for (int m = 0; m <= n; ++m)
104 Anm[n * (n + 1) / 2 + m] = ni(n) / constexpr_sqrt(Anm[n * (n + 1) / 2 + m]);
105#else
106 Anm[n * (n + 1) / 2 + m] = ni(n) / sqrt(Anm[n * (n + 1) / 2 + m]);
107#endif
108 }
109 }
110 FMM_CONSTEXPR double operator()(int n, int m) const
111 {
112 return Anm[n * (n + 1) / 2 + m];
113 }
114 };
115
117
118 template <int N>
120 {
121 std::array<double, N * (N + 1) * (N + 2) / 2 + 1> m2lcoef;
123 {
124 for (int j = 0; j < N; ++j)
125 {
126 for (int k = 0; k <= j; ++k)
127 {
128 for (int n = k; n < N; ++n)
129 {
130 int idx = N * (j + 2) * (j + 1) / 2 + N * (k + 1) + n + 1;
131 m2lcoef[idx] = Anm(n, k) * Anm(j, k) * ni(n + k) / Anm(j + n, 0);
132 }
133 }
134 }
135 }
136 };
137
139
140#ifndef FMM_CONSTEXPR_MATH
141 inline double* dev_Knm; // deprecated, substituted with __constant__ version
142 inline double* dev_Anm; // deprecated, substituted with __constant__ version
143 inline double* dev_m2lcoef; // deprecated, substituted with __constant__ version
144#endif
145 inline std::unordered_map<int, std::vector<double>> dmatrix;
146 inline std::unordered_map<int, std::vector<std::complex<double>>> rotation_exponents;
147 inline double* dev_dmatrix;
148 // if dev_dm_map[i] = key, use dev_dmatrix[i] for given key
149 // dmatrices on device are sorted by key,
150 // so it is possible to use binary search for given key to find i such that dev_dm_map[i] = key
151 inline int* dev_dm_map;
152
153
154 void InitMathConstants(int N);
157}
158
159} // fmm
#define __DEVICE__
Definition defs.h:21
#define FMM_CONSTEXPR_MATH
Definition defs.h:8
#define __HOST__
Definition defs.h:20
#define FMM_CONSTEXPR
Definition defs.h:11
constexpr anm_wrapper< _3d_MAX_MULTIPOLE_NUM > Anm
std::unordered_map< int, std::vector< double > > dmatrix
constexpr knm_wrapper< _3d_MAX_MULTIPOLE_NUM > Knm
std::unordered_map< int, std::vector< std::complex< double > > > rotation_exponents
double constexpr sqrtNewton(double x, double curr, double prev)
constexpr m2lcoef_wrapper< _3d_MAX_MULTIPOLE_NUM > m2lcoef
void InitMathConstants(int N)
void cudaCopyMathConstants()
double constexpr constexpr_sqrt(double x)
void cudaClearMathConstants()
Definition avx.h:5
void ComputePnm(int N, double theta, double *Pnm)
std::vector< double > ComputeWignerD(int N, double theta)
constexpr double ni(int n)
Definition simple_math.h:99
treevector< double > ComputeKnm(int N)
treevector< double > ComputeAnm(int N)
constexpr double operator()(int n, int m) const
std::array< double, 2 *N *(2 *N+1)/2 > Anm
constexpr double operator()(int n, int m) const
std::array< double, N *(N+1)/2 > Knm
std::array< double, N *(N+1) *(N+2)/2+1 > m2lcoef