www.pudn.com > ZFXMath-latest.zip > SHRotate.h
/// \file
///
/// \if DE
/// @brief SphericalHarmonics::SHRotate
///
/// SHRotate: Funktion um eine SH-Matrix zu erstellen auf Basis einer gewöhnlichen 4x4-Matrix
/// \else
/// @brief SphericalHarmonics::SHRotate
///
/// Rotation Matrices for Real Spherical Harmonics. Direct Determination by Recursion
/// Joseph Ivanic and Klaus Ruedenberg
/// J. Phys. Chem. 1996, 100, 6342-5347
///
/// Additions and Corrections (to previous paper)
/// Joseph Ivanic and Klaus Ruedenberg
/// J. Phys. Chem. A, 1998, Vol. 102, No. 45, 9099
///
/// SHRotate: Function to create an SH-Matrix based on an ordinary 4x4-Matrix
/// \endif
#ifndef _ZFXMATH_INCLUDE_SH_ROTATE_H_
#define _ZFXMATH_INCLUDE_SH_ROTATE_H_
namespace ZFXMath
{
namespace SphericalHarmonics
{
inline int delta(const int m, const int n)
{
// Kronecker Delta
return ( m == n ? 1 : 0 );
}
template
void uvw(const int l, const int m, const int n, PrecisionType& u, PrecisionType& v, PrecisionType& w)
{
// Pre-calculate simple reusable terms
PrecisionType d = PrecisionType( delta(m, 0) );
int abs_m = abs(m);
// Only calculate the required denominator once
PrecisionType denom;
if (abs(n) == l)
denom = PrecisionType( (2 * l) * (2 * l - 1) );
else
denom = PrecisionType( (l + n) * (l - n) );
// Now just calculate the scalars
u = PrecisionType( sqrt((l + m) * (l - m) / denom) );
v = PrecisionType( 0.5f * sqrt((1 + d) * (l + abs_m - 1) * (l + abs_m) / denom) * (1 - 2 * d) );
w = PrecisionType( -0.5f * sqrt((l - abs_m - 1) * (l - abs_m) / denom) * (1 - d) );
}
template
PrecisionType M(const int l, const int m, const int n, const TRotateMatrix& M)
{
// First get the scalars
PrecisionType u, v, w;
uvw(l, m, n, u, v, w);
// Scale by their functions
if (u)
u *= U(l, m, n, M);
if (v)
v *= V(l, m, n, M);
if (w)
w *= W(l, m, n, M);
return (u + v + w);
}
template
PrecisionType P(const int i, const int l, const int a, const int b, const TRotateMatrix& M)
{
// Rather than passing the permuted rotation matrix around grab it directly from the first
// rotation band which is never modified
PrecisionType ri1 = M(1, i, 1);
PrecisionType rim1 = M(1, i, -1);
PrecisionType ri0 = M(1, i, 0);
if (b == -l)
return (ri1 * M(l - 1, a, -l + 1) + rim1 * M(l - 1, a, l - 1));
else if (b == l)
return (ri1 * M(l - 1, a, l - 1) - rim1 * M(l - 1, a, -l + 1));
else // |b|
PrecisionType U(const int l, const int m, const int n, const TRotateMatrix& M)
{
// All cases fall correctly through here
return (P(0, l, m, n, M));
}
template
PrecisionType V(const int l, const int m, const int n, const TRotateMatrix& M)
{
if (m == 0)
{
PrecisionType p0 = P(1, l, 1, n, M);
PrecisionType p1 = P(-1, l, -1, n, M);
return (p0 + p1);
}
else if (m > 0)
{
PrecisionType d = PrecisionType( delta(m, 1) );
PrecisionType p0 = P(1, l, m - 1, n, M);
PrecisionType p1 = P(-1, l, -m + 1, n, M);
return PrecisionType(p0 * sqrt(1 + d) - p1 * (1 - d));
}
else // m < 0
{
PrecisionType d = PrecisionType( delta(m, -1) );
PrecisionType p0 = P(1, l, m + 1, n, M);
PrecisionType p1 = P(-1, l, -m - 1, n, M);
return PrecisionType(p0 * (1 - d) + p1 * sqrt(1 + d));
}
}
template
PrecisionType W(const int l, const int m, const int n, const TRotateMatrix& M)
{
if (m == 0)
{
// Never gets called as kd=0
assert(false);
return (0);
}
else if (m > 0)
{
PrecisionType p0 = P(1, l, m + 1, n, M);
PrecisionType p1 = P(-1, l, -m - 1, n, M);
return (p0 + p1);
}
else // m < 0
{
PrecisionType p0 = P(1, l, m - 1, n, M);
PrecisionType p1 = P(-1, l, -m + 1, n, M);
return (p0 - p1);
}
}
/// \if DE
/// @brief setze eine SHRotateMatrix durch eine einfache 4x4-Matrix
/// \else
/// @brief fill an SHRotateMatrix by an ordinary 4x4-Matrix
/// \endif
template
void SHRotate( TRotateMatrix& shrm, const TMatrix3x3& rotation )
{
// The first band is rotated by a permutation of the original matrix
shrm(1, -1, -1) = (PrecisionType) rotation._22;
shrm(1, -1, 0) = (PrecisionType) -rotation._32;
shrm(1, -1, +1) = (PrecisionType) rotation._12;
shrm(1, 0, -1) = (PrecisionType) -rotation._23;
shrm(1, 0, 0) = (PrecisionType) rotation._33;
shrm(1, 0, +1) = (PrecisionType) -rotation._13;
shrm(1, +1, -1) = (PrecisionType) rotation._21;
shrm(1, +1, 0) = (PrecisionType) -rotation._31;
shrm(1, +1, +1) = (PrecisionType) rotation._11;
// Calculate each block of the rotation matrix for each subsequent band
for (int band = 2; band < shrm.GetNbBands(); band++)
{
for (int m = -band; m <= band; m++)
for (int n = -band; n <= band; n++)
shrm(band, m, n) = M(band, m, n, shrm);
}
}
}; // namespace SphericalHarmonics
}; // namespace ZFXMath
#endif //_ZFXMATH_INCLUDE_SH_ROTATE_H_