7 #include <boost/math/special_functions/spherical_harmonic.hpp> 10 typedef std::tuple <int, int> lm;
15 struct key_hash :
public std::unary_function<lm, std::size_t>
17 std::size_t operator()(
const lm& k)
const 19 return std::get<0>(k) ^ std::get<1>(k);
26 struct key_equal :
public std::binary_function<lm, lm, bool>
28 bool operator()(
const lm& v0,
const lm& v1)
const 31 std::get<0>(v0) == std::get<0>(v1) &&
32 std::get<1>(v0) == std::get<1>(v1)
44 template<
class T,
class Policy>
45 inline T spherical_harmonic_prefix_raw(
unsigned n,
unsigned m, T theta,
const Policy &pol) {
55 prefix = boost::math::tgamma_delta_ratio(static_cast<T>(n - m + 1), static_cast<T>(2 * m), pol);
57 prefix *= (2 * n + 1) / (4 * boost::math::constants::pi<T>());
58 prefix = sqrt(prefix);
62 template<
class T,
class Policy>
63 T Y(
unsigned n,
int m, T theta, T phi,
const Policy &pol) {
81 T prefix = spherical_harmonic_prefix_raw(n, m, theta, pol);
84 T leg = boost::math::legendre_p(n, m, x, pol);
88 return sign ? prefix * sin(m * phi) : prefix * cos(m * phi);
91 template<
class T,
class Policy>
92 T DYdTheta(
unsigned n,
int m, T theta, T phi,
const Policy &pol) {
110 T prefix = spherical_harmonic_prefix_raw(n, m, theta, pol);
113 T leg2,leg1 = boost::math::legendre_p(n, m + 1, x, pol);
118 leg2 = boost::math::legendre_p(n, m - 1, x, pol);
122 prefix *= (0.5 * leg1 - 0.5 * (n + m) * (n - m + 1) * leg2);
123 return sign ? prefix * sin(m * phi) : prefix * cos(m * phi);
127 template<
class T,
class Policy>
128 T DYdPhi(
unsigned n,
int m, T theta, T phi,
const Policy &pol) {
148 T prefix = spherical_harmonic_prefix_raw(n, m, theta, pol);
149 T sin_theta = sin(theta);
151 T leg = boost::math::legendre_p(n, m, x, pol);
152 prefix *= sqrt(2) * leg;
153 return sign ? m * prefix * cos(m * phi) : -m * prefix * sin(m * phi);
158 template<
class T1,
class T2,
class Policy>
159 inline typename boost::math::tools::promote_args<T1, T2>::type
160 Y(
unsigned n,
int m, T1 theta, T2 phi,
const Policy &pol) {
161 typedef typename boost::math::tools::promote_args<T1, T2>::type result_type;
162 typedef typename boost::math::policies::evaluation<result_type, Policy>::type value_type;
163 return boost::math::policies::checked_narrowing_cast<result_type, Policy>(
164 detail::Y(n, m, static_cast<value_type>(theta), static_cast<value_type>(phi), pol),
165 "openfpm::math::Y<%1%>(unsigned, int, %1%, %1%)");
168 template<
class T1,
class T2>
169 inline typename boost::math::tools::promote_args<T1, T2>::type
170 Y(
unsigned n,
int m, T1 theta, T2 phi) {
171 return openfpm::math::Y(n, m, theta, phi, boost::math::policies::policy<>());
175 template<
class T1,
class T2,
class Policy>
176 inline typename boost::math::tools::promote_args<T1, T2>::type
177 DYdTheta(
unsigned n,
int m, T1 theta, T2 phi,
const Policy &pol) {
178 typedef typename boost::math::tools::promote_args<T1, T2>::type result_type;
179 typedef typename boost::math::policies::evaluation<result_type, Policy>::type value_type;
180 return boost::math::policies::checked_narrowing_cast<result_type, Policy>(
181 detail::DYdTheta(n, m, static_cast<value_type>(theta), static_cast<value_type>(phi), pol),
182 "openfpm::math::DYdTheta<%1%>(unsigned, int, %1%, %1%)");
185 template<
class T1,
class T2>
186 inline typename boost::math::tools::promote_args<T1, T2>::type
187 DYdTheta(
unsigned n,
int m, T1 theta, T2 phi) {
188 return openfpm::math::DYdTheta(n, m, theta, phi, boost::math::policies::policy<>());
191 template<
class T1,
class T2,
class Policy>
192 inline typename boost::math::tools::promote_args<T1, T2>::type
193 DYdPhi(
unsigned n,
int m, T1 theta, T2 phi,
const Policy &pol) {
194 typedef typename boost::math::tools::promote_args<T1, T2>::type result_type;
195 typedef typename boost::math::policies::evaluation<result_type, Policy>::type value_type;
196 return boost::math::policies::checked_narrowing_cast<result_type, Policy>(
197 detail::DYdPhi(n, m, static_cast<value_type>(theta), static_cast<value_type>(phi), pol),
198 "openfpm::math::DYdPhi<%1%>(unsigned, int, %1%, %1%)");
201 template<
class T1,
class T2>
202 inline typename boost::math::tools::promote_args<T1, T2>::type
203 DYdPhi(
unsigned n,
int m, T1 theta, T2 phi) {
204 return openfpm::math::DYdPhi(n, m, theta, phi, boost::math::policies::policy<>());
207 double sph_A1(
int l,
int m,
double v1,
double vr) {
208 return 0.5 * (1 + l) * (l * v1 - vr);
211 double sph_A2(
int l,
int m,
double v1,
double vr) {
212 return 0.5 * ((1 + l) * (-l) * v1 + (l + 3) * vr);
215 double sph_B(
int l,
int m,
double v2) {
219 double sph_A3(
int l,
int m,
double v1,
double vr) {
221 return 0.5 *l* ((1 + l)*v1 - vr)-1.5*sph_A2(l,m,v1,vr);
224 return 0.5 *l* ((1 + l)*v1 - vr);
228 double sph_A4(
int l,
int m,
double v1,
double vr) {
230 return 0.5* (-l*(1 + l)*v1 + (2-l)*vr)+0.5*sph_A2(l,m,v1,vr);
233 return 0.5* (-l*(1 + l)*v1 + (2-l)*vr);
249 std::vector<double> sph_anasol_u(
double nu,
int l,
int m,
double vr,
double v1,
double v2,
double r) {
257 ur=sph_A1(l,m,v1,vr)*r+sph_A2(l,m,v1,vr)/r;
263 ur=sph_A1(l,m,v1,vr)*pow(r,l+1)+sph_A2(l,m,v1,vr)*pow(r,l-1);
266 u1=1.0/double(l*(l+1))*((l+3.0)*sph_A1(l,m,v1,vr)*pow(r,l+1)+(l+1)*sph_A2(l,m,v1,vr)*pow(r,l-1));
267 u2=sph_B(l,m,v2)*(pow(r,l));
268 p= nu*((4.0*l+6.0)/double(l)*sph_A1(l,m,v1,vr)*pow(r,l));
283 template<
unsigned int k>
284 std::vector<double> sumY(
double r,
double theta,
double phi,
const std::unordered_map<const lm,double,key_hash,key_equal> &Vr,
const std::unordered_map<const lm,double,key_hash,key_equal> &V1,
const std::unordered_map<const lm,double,key_hash,key_equal> &V2) {
288 for (
int l = 0; l <= k; l++) {
289 for (
int m = -l; m <= l; m++) {
290 auto Er= Vr.find(std::make_tuple(l,m));
291 auto E1= V1.find(std::make_tuple(l,m));
292 auto E2= V2.find(std::make_tuple(l,m));
293 Sum1 += Er->second * openfpm::math::Y(l, m, theta, phi);
294 double DYdPhi=openfpm::math::DYdPhi(l, m, theta, phi);
295 double DYdTheta=openfpm::math::DYdTheta(l, m, theta, phi);
301 Sum2 += E1->second * DYdTheta -
302 E2->second / sin(theta) * DYdPhi;
304 Sum3 += E2->second * DYdTheta +
305 E1->second/sin(theta) * DYdPhi;
320 double x=Sum2*cos(theta)*cos(phi)-Sum3*sin(phi)+Sum1*cos(phi)*sin(theta);
321 double y=Sum3*cos(phi)+Sum2*cos(theta)*sin(phi)+Sum1*sin(phi)*sin(theta);
322 double z=Sum1*cos(theta)-Sum2*sin(theta);
336 template<
unsigned int k>
337 double sumY_Scalar(
double r,
double theta,
double phi,
const std::unordered_map<const lm,double,key_hash,key_equal> &Vr) {
339 for (
int l = 0; l <= k; l++) {
340 for (
int m = -l; m <= l; m++) {
341 auto Er= Vr.find(std::make_tuple(l,m));
342 Sum1 += Er->second * openfpm::math::Y(l, m, theta, phi);
convert a type into constant type
Structure required for the Sph Harmonic amplitude dictionary arguments.
Structure required for the Sph Harmonic amplitude dictionary arguments.