30#include <gsl/gsl_sf_coupling.h>
31#include <gsl/gsl_sf_legendre.h>
47sddk::mdarray<double, 2>
48wigner_d_matrix(
int l,
double beta);
52rotation_matrix_l(
int l, r3::vector<double>
euler_angles,
int proper_rotation);
56rotation_matrix(
int lmax, r3::vector<double>
euler_angles,
int proper_rotation, sddk::mdarray<T, 2>& rotm);
59std::vector<sddk::mdarray<T, 2>>
60rotation_matrix(
int lmax, r3::vector<double>
euler_angles,
int proper_rotation);
63ClebschGordan(
const int l,
const double j,
const double mj,
const int spin);
72calculate_U_sigma_m(
const int l,
const double j,
const int mj,
const int mp,
const int sigma);
102 std::vector<double>
w_;
139 s <<
"[SHT] wrong spherical coverage parameter : " <<
mesh_type_;
140 throw std::runtime_error(s.str());
156 Lebedev_Laikov_sphere(
num_points_, &x[0], &y[0], &z[0], &
w_[0]);
193 double t =
tp_(0, itp);
194 double p =
tp_(1, itp);
196 coord_(0, itp) = std::sin(t) * std::cos(p);
197 coord_(1, itp) = std::sin(t) * std::sin(p);
198 coord_(2, itp) = std::cos(t);
218 case sddk::device_t::GPU: {
225 case sddk::device_t::CPU: {
245 template <
typename T>
260 template <
typename T>
264 static void convert(
int lmax__,
double const* f_rlm__, std::complex<double>* f_ylm__)
267 for (
int l = 0; l <= lmax__; l++) {
268 for (
int m = -l; m <= l; m++) {
270 f_ylm__[
lm] = f_rlm__[
lm];
281 static void convert(
int lmax__, std::complex<double>
const* f_ylm__,
double* f_rlm__)
284 for (
int l = 0; l <= lmax__; l++) {
285 for (
int m = -l; m <= l; m++) {
287 f_rlm__[
lm] = std::real(f_ylm__[
lm]);
290 f_rlm__[
lm] = std::real(rlm_dot_ylm(l, m, m) * f_ylm__[
lm] + rlm_dot_ylm(l, m, -m) * f_ylm__[lm1]);
363 static inline std::complex<double>
ylm_dot_rlm(
int l,
int m1,
int m2)
365 double const isqrt2 = 1.0 / std::sqrt(2);
367 RTE_ASSERT(l >= 0 && std::abs(m1) <= l && std::abs(m2) <= l);
369 if (!((m1 == m2) || (m1 == -m2))) {
370 return std::complex<double>(0, 0);
374 return std::complex<double>(1, 0);
379 return -std::complex<double>(0, isqrt2);
381 return std::pow(-1.0, m2) * std::complex<double>(isqrt2, 0);
385 return std::pow(-1.0, m1) * std::complex<double>(0, isqrt2);
387 return std::complex<double>(isqrt2, 0);
392 static inline std::complex<double> rlm_dot_ylm(
int l,
int m1,
int m2)
403 static double gaunt_yyy(
int l1,
int l2,
int l3,
int m1,
int m2,
int m3)
408 RTE_ASSERT(m1 >= -l1 && m1 <= l1);
409 RTE_ASSERT(m2 >= -l2 && m2 <= l2);
410 RTE_ASSERT(m3 >= -l3 && m3 <= l3);
412 return std::pow(-1.0, std::abs(m1)) * std::sqrt(
double(2 * l1 + 1) *
double(2 * l2 + 1) *
double(2 * l3 + 1) /
fourpi) *
413 gsl_sf_coupling_3j(2 * l1, 2 * l2, 2 * l3, 0, 0, 0) *
414 gsl_sf_coupling_3j(2 * l1, 2 * l2, 2 * l3, -2 * m1, 2 * m2, 2 * m3);
423 static double gaunt_rrr(
int l1,
int l2,
int l3,
int m1,
int m2,
int m3)
428 RTE_ASSERT(m1 >= -l1 && m1 <= l1);
429 RTE_ASSERT(m2 >= -l2 && m2 <= l2);
430 RTE_ASSERT(m3 >= -l3 && m3 <= l3);
433 for (
int k1 = -l1; k1 <= l1; k1++) {
434 for (
int k2 = -l2; k2 <= l2; k2++) {
435 for (
int k3 = -l3; k3 <= l3; k3++) {
457 RTE_ASSERT(m1 >= -l1 && m1 <= l1);
458 RTE_ASSERT(m2 >= -l2 && m2 <= l2);
459 RTE_ASSERT(m3 >= -l3 && m3 <= l3);
462 for (
int k1 = -l1; k1 <= l1; k1++) {
463 for (
int k3 = -l3; k3 <= l3; k3++) {
478 static std::complex<double>
gaunt_hybrid(
int l1,
int l2,
int l3,
int m1,
int m2,
int m3)
483 RTE_ASSERT(m1 >= -l1 && m1 <= l1);
484 RTE_ASSERT(m2 >= -l2 && m2 <= l2);
485 RTE_ASSERT(m3 >= -l3 && m3 <= l3);
488 return std::complex<double>(
gaunt_yyy(l1, l2, l3, m1, m2, m3), 0.0);
495 void uniform_coverage()
501 double hk = -1.0 + double(2 * k) / double(
num_points_ - 1);
502 tp_(0, k) = std::acos(hk);
503 double t =
tp_(1, k - 1) + 3.80925122745582 / std::sqrt(
double(
num_points_)) / std::sqrt(1 - hk * hk);
515 static inline double clebsch_gordan(
int l1,
int l2,
int l3,
int m1,
int m2,
int m3)
520 RTE_ASSERT(m1 >= -l1 && m1 <= l1);
521 RTE_ASSERT(m2 >= -l2 && m2 <= l2);
522 RTE_ASSERT(m3 >= -l3 && m3 <= l3);
524 return std::pow(-1, l1 - l2 + m3) * std::sqrt(
double(2 * l3 + 1)) *
525 gsl_sf_coupling_3j(2 * l1, 2 * l2, 2 * l3, 2 * m1, 2 * m2, -2 * m3);
528 inline auto ylm_backward(
int lm,
int itp)
const
533 inline auto rlm_backward(
int lm,
int itp)
const
538 inline auto coord(
int x,
int itp)
const
543 inline auto coord(
int idx__)
const
545 return r3::vector<double>(
coord_(0, idx__),
coord_(1, idx__), coord(2, idx__));
548 inline auto theta(
int idx__)
const
550 return tp_(0, idx__);
553 inline auto phi(
int idx__)
const
555 return tp_(1, idx__);
558 inline auto weight(
int idx__)
const
563 inline auto num_points()
const
568 inline auto lmax()
const
573 inline auto lmmax()
const
Spherical harmonics transformations and related oprtations.
void check() const
Check the transformations.
static double gaunt_rlm_ylm_rlm(int l1, int l2, int l3, int m1, int m2, int m3)
Gaunt coefficent of two real spherical harmonics with a complex one.
int mesh_type_
Type of spherical grid (0: Lebedev-Laikov, 1: uniform).
static std::complex< double > gaunt_hybrid(int l1, int l2, int l3, int m1, int m2, int m3)
Gaunt coefficent of two complex and one real spherical harmonics.
SHT(sddk::device_t pu__, int lmax__, int mesh_type__=0)
Default constructor.
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.
static void convert(int lmax__, double const *f_rlm__, std::complex< double > *f_ylm__)
Convert form Rlm to Ylm representation.
static double gaunt_rrr(int l1, int l2, int l3, int m1, int m2, int m3)
Gaunt coefficent of three real spherical harmonics.
std::vector< double > w_
Point weights.
static double gaunt_yyy(int l1, int l2, int l3, int m1, int m2, int m3)
Gaunt coefficent of three complex spherical harmonics.
static void convert(int lmax__, std::complex< double > const *f_ylm__, double *f_rlm__)
Convert from Ylm to Rlm representation.
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.
sddk::mdarray< double, 2 > coord_
Cartesian coordinates of points (normalized to 1).
sddk::device_t pu_
Type of processing unit.
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.
int lmax_
Maximum of spherical harmonics.
static double clebsch_gordan(int l1, int l2, int l3, int m1, int m2, int m3)
Return Clebsch-Gordan coefficient.
sddk::mdarray< double, 2 > tp_
angles of points.
void geinv(ftn_int n, sddk::matrix< T > &A) const
Invert a general matrix.
mdarray< T, N > & allocate(memory_t memory__)
Allocate memory for array.
Generate Lebedev-Laikov grids on the sphere.
Linear algebra interface.
device_t
Type of the main processing unit.
auto spherical_coordinates(vector< double > vc)
Transform Cartesian coordinates [x,y,z] to spherical coordinates [r,theta,phi].
int lmax(int lmmax__)
Get maximum orbital quantum number by the maximum lm index.
int lm(int l, int m)
Get composite lm index by angular index l and azimuthal index m.
void spherical_harmonics(int lmax, double theta, double phi, std::complex< double > *ylm)
Optimized implementation of complex spherical harmonics.
Namespace of the SIRIUS library.
auto euler_angles(r3::matrix< double > const &rot__, double tolerance__)
Compute Euler angles corresponding to the proper rotation matrix.
auto conj(double x__)
Return complex conjugate of a number. For a real value this is the number itself.
Simple classes and functions to work with vectors and matrices of the R^3 space.
Contains typedefs, enums and simple descriptors.