27sddk::mdarray<double, 2>
28wigner_d_matrix(
int l,
double beta)
30 sddk::mdarray<double, 2> d_mtrx(2 * l + 1, 2 * l + 1);
32 long double cos_b2 = std::cos((
long double)beta / 2.0L);
33 long double sin_b2 = std::sin((
long double)beta / 2.0L);
35 for (
int m1 = -l; m1 <= l; m1++) {
36 for (
int m2 = -l; m2 <= l; m2++) {
38 for (
int j = 0; j <= std::min(l + m1, l - m2); j++) {
39 if ((l - m2 - j) >= 0 && (l + m1 - j) >= 0 && (j + m2 - m1) >= 0) {
40 long double g = (std::sqrt(factorial<long double>(l + m1)) / factorial<long double>(l - m2 - j)) *
41 (std::sqrt(factorial<long double>(l - m1)) / factorial<long double>(l + m1 - j)) *
42 (std::sqrt(factorial<long double>(l - m2)) / factorial<long double>(j + m2 - m1)) *
43 (std::sqrt(factorial<long double>(l + m2)) / factorial<long double>(j));
44 d += g * std::pow(-1, j) * std::pow(cos_b2, 2 * l + m1 - m2 - 2 * j) * std::pow(sin_b2, 2 * j + m2 - m1);
47 d_mtrx(m1 + l, m2 + l) = (double)d;
55sddk::mdarray<std::complex<double>, 2>
56rotation_matrix_l<std::complex<double>>(
int l, r3::vector<double>
euler_angles,
int proper_rotation)
58 sddk::mdarray<std::complex<double>, 2> rot_mtrx(2 * l + 1, 2 * l + 1);
62 for (
int m1 = -l; m1 <= l; m1++) {
63 for (
int m2 = -l; m2 <= l; m2++) {
65 d_mtrx(m1 + l, m2 + l) * std::pow(proper_rotation, l);
73sddk::mdarray<double, 2>
74rotation_matrix_l<double>(
int l, r3::vector<double>
euler_angles,
int proper_rotation)
76 auto rot_mtrx_ylm = rotation_matrix_l<std::complex<double>>(l,
euler_angles, proper_rotation);
78 sddk::mdarray<double, 2> rot_mtrx(2 * l + 1, 2 * l + 1);
81 for (
int m1 = -l; m1 <= l; m1++) {
82 auto i13 = (m1 == 0) ? std::vector<int>({0}) : std::vector<int>({-m1, m1});
84 for (
int m2 = -l; m2 <= l; m2++) {
85 auto i24 = (m2 == 0) ? std::vector<int>({0}) : std::vector<int>({-m2, m2});
89 rot_mtrx(m1 + l, m2 + l) += std::real(SHT::rlm_dot_ylm(l, m1, m3) *
90 rot_mtrx_ylm(m3 + l, m4 + l) *
104rotation_matrix(
int lmax, r3::vector<double>
euler_angles,
int proper_rotation,
105 sddk::mdarray<T, 2>& rotm)
109 for (
int l = 0; l <=
lmax; l++) {
110 auto rl = rotation_matrix_l<T>(l,
euler_angles, proper_rotation);
111 for (
int m = 0; m < 2 * l + 1; m++) {
112 for (
int mp = 0; mp < 2 * l + 1; mp++) {
113 rotm(l * l + m, l * l + mp) = rl(m, mp);
121rotation_matrix<double>(
int lmax, r3::vector<double>
euler_angles,
int proper_rotation,
122 sddk::mdarray<double, 2>& rotm);
126rotation_matrix<std::complex<double>>(
int lmax, r3::vector<double>
euler_angles,
int proper_rotation,
127 sddk::mdarray<std::complex<double>, 2>& rotm);
130std::vector<sddk::mdarray<T, 2>>
131rotation_matrix(
int lmax, r3::vector<double>
euler_angles,
int proper_rotation)
133 std::vector<sddk::mdarray<T, 2>> result(
lmax + 1);
135 for (
int l = 0; l <=
lmax; l++) {
136 result[l] = rotation_matrix_l<T>(l,
euler_angles, proper_rotation);
142std::vector<sddk::mdarray<double, 2>>
143rotation_matrix<double>(
int lmax, r3::vector<double>
euler_angles,
int proper_rotation);
146std::vector<sddk::mdarray<std::complex<double>, 2>>
147rotation_matrix<std::complex<double>>(
int lmax, r3::vector<double>
euler_angles,
int proper_rotation);
150ClebschGordan(
const int l,
const double j,
const double mj,
const int spin)
158 if ((spin != 0) && (spin != 1)) {
159 RTE_THROW(
"Error : unknown spin direction");
162 const double denom = std::sqrt(1.0 / (2.0 * l + 1.0));
164 if (std::abs(j - l - 0.5) < 1e-8) {
165 int m =
static_cast<int>(mj - 0.5);
167 CG = std::sqrt(l + m + 1.0);
170 CG = std::sqrt((l - m));
173 if (std::abs(j - l + 0.5) < 1e-8) {
174 int m =
static_cast<int>(mj + 0.5);
179 CG = std::sqrt(l - m + 1);
182 CG = -std::sqrt(l + m);
187 s <<
"Clebsch-Gordan coefficients do not exist for this combination of j=" << j <<
" and l=" << l;
203calculate_U_sigma_m(
const int l,
const double j,
const int mj,
const int mp,
const int sigma)
205 if ((sigma != 0) && (sigma != 1)) {
206 RTE_THROW(
"SphericalIndex function : unknown spin direction");
209 if (std::abs(j - l - 0.5) < 1e-8) {
213 int m1 = (mj - 1) >> 1;
218 return SHT::rlm_dot_ylm(l, m1, mp);
224 return SHT::rlm_dot_ylm(l, m1 + 1, mp);
228 if (std::abs(j - l + 0.5) < 1e-8) {
229 int m1 = (mj + 1) >> 1;
231 return SHT::rlm_dot_ylm(l, m1 - 1, mp);
233 return SHT::rlm_dot_ylm(l, m1, mp);
236 RTE_THROW(
"Spherical Index function : l and j are not compatible");
245void SHT::backward_transform<double>(
int ld,
double const *flm,
int nr,
int lmmax,
double *ftp)
const
254void SHT::backward_transform<std::complex<double>>(
int ld, std::complex<double>
const *flm,
int nr,
int lmmax,
255 std::complex<double> *ftp)
const
257 assert(
lmmax <= lmmax_);
260 &la::constant<std::complex<double>>::one(), &ylm_backward_(0, 0), lmmax_, flm, ld,
261 &la::constant<std::complex<double>>
::zero(), ftp, num_points_);
265void SHT::forward_transform<double>(
double const *ftp,
int nr,
int lmmax,
int ld,
double *flm)
const
274void SHT::forward_transform<std::complex<double>>(std::complex<double>
const *ftp,
int nr,
int lmmax,
int ld,
275 std::complex<double> *flm)
const
277 assert(
lmmax <= lmmax_);
279 la::wrap(
la::lib_t::blas).gemm(
'T',
'N',
lmmax, nr, num_points_, &la::constant<std::complex<double>>::one(),
280 &ylm_forward_(0, 0), num_points_, ftp, num_points_, &la::constant<std::complex<double>>
::zero(), flm, ld);
289 for (
int lm1 = 0; lm1 <
lmmax_; lm1++) {
291 std::complex<double> zt(0, 0);
308 if (dr > 1e-15 || dy > 1e-15) {
310 s <<
"spherical mesh error is too big" << std::endl
311 <<
" real spherical integration error " << dr << std::endl
312 <<
" complex spherical integration error " << dy;
316 std::vector<double> flm(
lmmax_);
319 std::memset(&flm[0], 0,
lmmax_ *
sizeof(
double));
326 for (
int lm1 = 0; lm1 <
lmmax_; lm1++) {
327 t += std::abs(flm[lm1]);
334 s <<
"test of backward / forward real SHT failed" << std::endl
335 <<
" total error " << t;
336 RTE_WARNING(s.str());
void check() const
Check the transformations.
sddk::mdarray< std::complex< double >, 2 > ylm_forward_
Forward transformation from spherical coordinates to Ylm.
int lmmax_
Maximum number of components.
void backward_transform(int ld, T const *flm, int nr, int lmmax, T *ftp) const
Perform a backward transformation from spherical harmonics to spherical coordinates.
sddk::mdarray< double, 2 > rlm_forward_
Forward transformation from spherical coordinates to Rlm.
void forward_transform(T const *ftp, int nr, int lmmax, int ld, T *flm) const
Perform a forward transformation from spherical coordinates to spherical harmonics.
sddk::mdarray< std::complex< double >, 2 > ylm_backward_
Backward transformation from Ylm to spherical coordinates.
int num_points_
Number of real-space points on the sphere.
sddk::mdarray< double, 2 > rlm_backward_
Backward transformation from Rlm to spherical coordinates.
static std::complex< double > ylm_dot_rlm(int l, int m1, int m2)
Compute element of the transformation matrix from complex to real spherical harmonics.
void zero(T *ptr__, size_t n__)
Zero the device memory.
int lmax(int lmmax__)
Get maximum orbital quantum number by the maximum lm index.
int lmmax(int lmax)
Maximum number of combinations for a given .
int lm(int l, int m)
Get composite lm index by angular index l and azimuthal index m.
Namespace of the SIRIUS library.
auto euler_angles(r3::matrix< double > const &rot__, double tolerance__)
Compute Euler angles corresponding to the proper rotation matrix.
Contains declaration and particular implementation of sirius::SHT class.