5#ifndef SPHERICALHARMONICS_HPP_
6#define SPHERICALHARMONICS_HPP_
8#include <boost/math/special_functions/spherical_harmonic.hpp>
11typedef std::tuple <int, int> lm;
16struct key_hash :
public std::unary_function<lm, std::size_t>
18 std::size_t operator()(
const lm& k)
const
20 return std::get<0>(k) ^ std::get<1>(k);
27struct key_equal :
public std::binary_function<lm, lm, bool>
29 bool operator()(
const lm& v0,
const lm& v1)
const
32 std::get<0>(v0) == std::get<0>(v1) &&
33 std::get<1>(v0) == std::get<1>(v1)
45 template<
class T,
class Policy>
46 inline T spherical_harmonic_prefix_raw(
unsigned n,
unsigned m, T theta,
const Policy &pol) {
56 prefix = boost::math::tgamma_delta_ratio(
static_cast<T
>(n - m + 1),
static_cast<T
>(2 * m), pol);
58 prefix *= (2 * n + 1) / (4 * boost::math::constants::pi<T>());
59 prefix = sqrt(prefix);
63 template<
class T,
class Policy>
64 T Y(
unsigned n,
int m, T theta, T phi,
const Policy &pol) {
82 T prefix = spherical_harmonic_prefix_raw(n, m, theta, pol);
85 T leg = boost::math::legendre_p(n, m, x, pol);
89 return sign ? prefix * sin(m * phi) : prefix * cos(m * phi);
92 template<
class T,
class Policy>
93 T DYdTheta(
unsigned n,
int m, T theta, T phi,
const Policy &pol) {
111 T prefix = spherical_harmonic_prefix_raw(n, m, theta, pol);
114 T leg2,leg1 = boost::math::legendre_p(n, m + 1, x, pol);
119 leg2 = boost::math::legendre_p(n, m - 1, x, pol);
123 prefix *= (0.5 * leg1 - 0.5 * (n + m) * (n - m + 1) * leg2);
124 return sign ? prefix * sin(m * phi) : prefix * cos(m * phi);
128 template<
class T,
class Policy>
129 T DYdPhi(
unsigned n,
int m, T theta, T phi,
const Policy &pol) {
149 T prefix = spherical_harmonic_prefix_raw(n, m, theta, pol);
150 T sin_theta = sin(theta);
152 T leg = boost::math::legendre_p(n, m, x, pol);
153 prefix *= sqrt(2) * leg;
154 return sign ? m * prefix * cos(m * phi) : -m * prefix * sin(m * phi);
159 template<
class T1,
class T2,
class Policy>
160 inline typename boost::math::tools::promote_args<T1, T2>::type
161 Y(
unsigned n,
int m, T1 theta, T2 phi,
const Policy &pol) {
162 typedef typename boost::math::tools::promote_args<T1, T2>::type result_type;
163 typedef typename boost::math::policies::evaluation<result_type, Policy>::type value_type;
164 return boost::math::policies::checked_narrowing_cast<result_type, Policy>(
165 detail::Y(n, m,
static_cast<value_type
>(theta),
static_cast<value_type
>(phi), pol),
166 "openfpm::math::Y<%1%>(unsigned, int, %1%, %1%)");
169 template<
class T1,
class T2>
170 inline typename boost::math::tools::promote_args<T1, T2>::type
171 Y(
unsigned n,
int m, T1 theta, T2 phi) {
172 return openfpm::math::Y(n, m, theta, phi, boost::math::policies::policy<>());
176 template<
class T1,
class T2,
class Policy>
177 inline typename boost::math::tools::promote_args<T1, T2>::type
178 DYdTheta(
unsigned n,
int m, T1 theta, T2 phi,
const Policy &pol) {
179 typedef typename boost::math::tools::promote_args<T1, T2>::type result_type;
180 typedef typename boost::math::policies::evaluation<result_type, Policy>::type value_type;
181 return boost::math::policies::checked_narrowing_cast<result_type, Policy>(
182 detail::DYdTheta(n, m,
static_cast<value_type
>(theta),
static_cast<value_type
>(phi), pol),
183 "openfpm::math::DYdTheta<%1%>(unsigned, int, %1%, %1%)");
186 template<
class T1,
class T2>
187 inline typename boost::math::tools::promote_args<T1, T2>::type
188 DYdTheta(
unsigned n,
int m, T1 theta, T2 phi) {
189 return openfpm::math::DYdTheta(n, m, theta, phi, boost::math::policies::policy<>());
192 template<
class T1,
class T2,
class Policy>
193 inline typename boost::math::tools::promote_args<T1, T2>::type
194 DYdPhi(
unsigned n,
int m, T1 theta, T2 phi,
const Policy &pol) {
195 typedef typename boost::math::tools::promote_args<T1, T2>::type result_type;
196 typedef typename boost::math::policies::evaluation<result_type, Policy>::type value_type;
197 return boost::math::policies::checked_narrowing_cast<result_type, Policy>(
198 detail::DYdPhi(n, m,
static_cast<value_type
>(theta),
static_cast<value_type
>(phi), pol),
199 "openfpm::math::DYdPhi<%1%>(unsigned, int, %1%, %1%)");
202 template<
class T1,
class T2>
203 inline typename boost::math::tools::promote_args<T1, T2>::type
204 DYdPhi(
unsigned n,
int m, T1 theta, T2 phi) {
205 return openfpm::math::DYdPhi(n, m, theta, phi, boost::math::policies::policy<>());
208 inline double sph_A1(
int l,
int m,
double v1,
double vr) {
209 return 0.5 * (1 + l) * (l * v1 - vr);
212 inline double sph_A2(
int l,
int m,
double v1,
double vr) {
213 return 0.5 * ((1 + l) * (-l) * v1 + (l + 3) * vr);
216 inline double sph_B(
int l,
int m,
double v2) {
220 inline double sph_A3(
int l,
int m,
double v1,
double vr) {
222 return 0.5 *l* ((1 + l)*v1 - vr)-1.5*sph_A2(l,m,v1,vr);
225 return 0.5 *l* ((1 + l)*v1 - vr);
229 inline double sph_A4(
int l,
int m,
double v1,
double vr) {
231 return 0.5* (-l*(1 + l)*v1 + (2-l)*vr)+0.5*sph_A2(l,m,v1,vr);
234 return 0.5* (-l*(1 + l)*v1 + (2-l)*vr);
250 inline std::vector<double> sph_anasol_u(
double nu,
int l,
int m,
double vr,
double v1,
double v2,
double r) {
258 ur=sph_A1(l,m,v1,vr)*r+sph_A2(l,m,v1,vr)/r;
264 ur=sph_A1(l,m,v1,vr)*pow(r,l+1)+sph_A2(l,m,v1,vr)*pow(r,l-1);
267 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));
268 u2=sph_B(l,m,v2)*(pow(r,l));
269 p= nu*((4.0*l+6.0)/
double(l)*sph_A1(l,m,v1,vr)*pow(r,l));
284 template<
unsigned int k>
285 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) {
289 for (
int l = 0; l <= k; l++) {
290 for (
int m = -l; m <= l; m++) {
291 auto Er= Vr.find(std::make_tuple(l,m));
292 auto E1= V1.find(std::make_tuple(l,m));
293 auto E2= V2.find(std::make_tuple(l,m));
294 Sum1 += Er->second * openfpm::math::Y(l, m, theta, phi);
295 double DYdPhi=openfpm::math::DYdPhi(l, m, theta, phi);
296 double DYdTheta=openfpm::math::DYdTheta(l, m, theta, phi);
302 Sum2 += E1->second * DYdTheta -
303 E2->second / sin(theta) * DYdPhi;
305 Sum3 += E2->second * DYdTheta +
306 E1->second/sin(theta) * DYdPhi;
321 double x=Sum2*cos(theta)*cos(phi)-Sum3*sin(phi)+Sum1*cos(phi)*sin(theta);
322 double y=Sum3*cos(phi)+Sum2*cos(theta)*sin(phi)+Sum1*sin(phi)*sin(theta);
323 double z=Sum1*cos(theta)-Sum2*sin(theta);
337 template<
unsigned int k>
338 double sumY_Scalar(
double r,
double theta,
double phi,
const std::unordered_map<const lm,double,key_hash,key_equal> &Vr) {
340 for (
int l = 0; l <= k; l++) {
341 for (
int m = -l; m <= l; m++) {
342 auto Er= Vr.find(std::make_tuple(l,m));
343 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.