17 #ifndef __itkSphericalHarmonicsGenerator_hxx 18 #define __itkSphericalHarmonicsGenerator_hxx 22 #include <gsl/gsl_sf_legendre.h> 24 #include <gsl/gsl_sf_coupling.h> 35 double Gamma(
const double);
41 template<
class PreciseType>
42 SphericalHarmonicsGenerator<PreciseType>
43 ::SphericalHarmonicsGenerator()
47 template <
class PreciseType>
53 template <
class PreciseType >
58 Superclass::PrintSelf(os, indent);
61 template<
class PreciseType>
62 std::complex<PreciseType>
64 ::ComplexSH(
const int l,
const int m,
const PreciseType theta,
const PreciseType phi)
66 int absm = (m<0 ? -m : m);
69 std::complex<PreciseType> retval(0.0,(PreciseType)(absm*phi));
70 retval = std::exp(retval) * gsl_sf_legendre_sphPlm(l,absm,cos(theta));
73 retval = sign * std::conj(retval);
80 template <
class PreciseType >
83 ::RealSH (
const int l,
const int m,
const PreciseType theta,
const PreciseType phi )
85 std::complex<PreciseType> cplx;
88 cplx = ComplexSH(l, m, theta, phi);
93 cplx = ComplexSH(l, m, theta, phi);
94 return std::real(cplx);
101 cplx = sign * ComplexSH(l, m, theta, phi);
106 template <
class PreciseType >
112 PreciseType result = 0.0;
113 if (m1+m2+m3==0 && l1+l2>=l3 && l1+l3>=l2 && l2+l3>=l1)
115 result = std::sqrt( (2*l1+1)*(2*l2+1)*(2*l3+1)/(4*
M_PI) ) * gsl_sf_coupling_3j(2*l1,2*l2,2*l3,2*m1,2*m2,2*m3) * gsl_sf_coupling_3j(2*l1,2*l2,2*l3,0,0,0);
122 template <
class PreciseType >
125 ::RealTripleIntegration (
const int l1,
const int m1,
const int l2,
const int m2,
const int l3,
const int m3,
const bool is_precalculated)
128 utlException((l1%2!=0) || (l2%2!=0) || (l3%2!=0),
"l1, l2, l3 need to be even integers" );
129 PreciseType result = 0;
131 if (is_precalculated)
136 if (l1<=rank && l2<=rank && l3<=rank)
142 result = (*utl::SH3IntegralTable)(index);
145 result = RealTripleIntegration(l1,m1,l2,m2,l3,m3,
false);
153 if (m1<0 && m2<0 && m3<0)
156 result = ( m3%2==0?1:-1 ) * ComplexTripleIntegration(l1,m1,l2,m2,l3,-m3) /
utl::SQRT2;
158 result = ( m2%2==0?1:-1 ) * ComplexTripleIntegration(l1,m1,l2,-m2,l3,m3) /
utl::SQRT2;
165 result = ( m1%2==0?1:-1 ) * ComplexTripleIntegration(l1,-m1,l2,m2,l3,m3) /
utl::SQRT2;
168 else if ( (m1>0 && m2<0 && m3<0) || (m1<0 && m2>0 && m3<0) || (m1<0 && m2<0 && m3>0) )
172 else if (m1>0 && m2>0 && m3<0)
175 result = (-1.0) * ( m3%2==0?1:-1 ) * ComplexTripleIntegration(l1,m1,l2,m2,l3,m3) /
utl::SQRT2;
177 result = ( m2%2==0?1:-1 ) * ComplexTripleIntegration(l1,m1,l2,-m2,l3,-m3) /
utl::SQRT2;
179 result = ( m1%2==0?1:-1 ) * ComplexTripleIntegration(l1,-m1,l2,m2,l3,-m3) /
utl::SQRT2;
181 else if (m1>0 && m2<0 && m3>0)
184 result = (-1.0) * ( m2%2==0?1:-1 ) * ComplexTripleIntegration(l1,m1,l2,m2,l3,m3) /
utl::SQRT2;
186 result = ( m3%2==0?1:-1 ) * ComplexTripleIntegration(l1,m1,l2,-m2,l3,-m3) /
utl::SQRT2;
188 result = ( m1%2==0?1:-1 ) * ComplexTripleIntegration(l1,-m1,l2,-m2,l3,m3) /
utl::SQRT2;
190 else if (m1<0 && m2>0 && m3>0)
193 result = (-1.0) * ( m1%2==0?1:-1 ) * ComplexTripleIntegration(l1,m1,l2,m2,l3,m3) /
utl::SQRT2;
195 result = ( m2%2==0?1:-1 ) * ComplexTripleIntegration(l1,-m1,l2,-m2,l3,m3) /
utl::SQRT2;
197 result = ( m3%2==0?1:-1 ) * ComplexTripleIntegration(l1,-m1,l2,m2,l3,-m3) /
utl::SQRT2;
199 else if (m1>0 && m2>0 && m3>0)
201 else if (m1==0 && m2==0 && m3==0)
202 result = ComplexTripleIntegration(l1,0,l2,0,l3,0);
203 else if (m1==0 && m2==m3)
204 result = ( m3%2==0?1:-1 ) * ComplexTripleIntegration(l1,0,l2,m2,l3,-m3);
205 else if (m2==0 && m3==m1)
206 result = ( m1%2==0?1:-1 ) * ComplexTripleIntegration(l1,m1,l2,0,l3,-m3);
207 else if (m3==0 && m1==m2)
208 result = ( m2%2==0?1:-1 ) * ComplexTripleIntegration(l1,m1,l2,-m2,l3,0);
213 template <
class PreciseType >
218 std::complex<double> result(0,0), ee(0,-phi);
219 std::complex<double> sh_value = ComplexSH(l, m, theta, phi);
220 double theta_used =
std::abs(theta)>1e-6? theta : (theta>=0?1e-6:-1e-6);
222 return l * 1.0/std::tan(theta_used) * sh_value;
223 std::complex<double> sh_value_2 = ComplexSH(l, m+1, theta_used, phi);
228 template <
class PreciseType >
233 std::complex<double> sh_value = ComplexSH(l, m, theta, phi);
234 std::complex<double> r1 (0,m);
238 template <
class PreciseType >
244 return std::real(ComplexDerivativeOfTheta(l,m,theta,phi));
246 return utl::SQRT2 * std::imag(ComplexDerivativeOfTheta(l,m,theta,phi));
248 return utl::SQRT2 * std::real(ComplexDerivativeOfTheta(l,-m,theta,phi));
251 template <
class PreciseType >
257 return std::real(ComplexDerivativeOfPhi(l,m,theta,phi));
259 return utl::SQRT2 * std::imag(ComplexDerivativeOfPhi(l,m,theta,phi));
261 return utl::SQRT2 * std::real(ComplexDerivativeOfPhi(l,-m,theta,phi));
void InitializeSHTripleIntegrationTable(const int rank0=-1, const int rank1=-1, const int rank2=-1, const bool useExactSize=false)
static std::shared_ptr< NDArray< double, 3 > > SH3IntegralTable(new NDArray< double, 3 >)
int GetIndexSHj(const int l, const int m)
bool IsEven(const int value)
#define utlException(cond, expout)
bool IsFileExist(const std::string &file)
int DimToRankSH(const int dimm)
T abs(const T x)
template version of the fabs function
Generate complex and real Spherical Harmonic Basis.
static const std::string SH3Itegralhdr
int sign(const T &x)
Return the sign of x.
static constexpr double SQRT2
double Gamma(const double x)
gamma function.