Loading...
Searching...
No Matches
spherical_harmonics_table.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * SphericalHarmonicsTable — precomputed real spherical harmonics Y_lm(Ĝ)
5 * for all G-vectors in a PlanewaveBasis.
6 *
7 * This table is a general planewave concept, not specific to ultrasoft
8 * pseudopotential_set. Any code that needs Y_lm evaluated at the directions
9 * of the G-vectors can use this cached table.
10 */
11
12#include <cmath>
13#include <vector>
14
19
20namespace q3 {
21
23 public:
25
26 /**
27 * Initialize the table for all G-vectors up to the given maximum angular momentum.
28 *
29 * Computes Y_lm(Ĝ) for each G-vector in the basis and each (l,m) pair
30 * with l ∈ [0, maximum_angular_momentum] and m ∈ [-l, l].
31 */
32 void init(const Crystal& crystal_structure,
33 const PlanewaveBasis& planewave_basis,
35 maximum_angular_momentum_ = maximum_angular_momentum;
38 int number_of_g_vectors = planewave_basis.number_of_g_vectors();
39 Real two_pi_over_lattice_parameter = crystal_structure.two_pi_over_lattice_parameter();
40
41 spherical_harmonics_at_g_.resize(number_of_g_vectors);
42 for (int g_index = 0; g_index < number_of_g_vectors; g_index++) {
43 spherical_harmonics_at_g_[g_index].resize(number_of_lm_components, 0.0);
44 const auto& g_vector = planewave_basis.g_vectors()[g_index];
45 Vector3D g_cartesian{g_vector.g_cart.x * two_pi_over_lattice_parameter,
46 g_vector.g_cart.y * two_pi_over_lattice_parameter,
47 g_vector.g_cart.z * two_pi_over_lattice_parameter};
48
49 for (int angular_momentum = 0; angular_momentum <= maximum_angular_momentum;
50 angular_momentum++) {
51 for (int magnetic_projection = -angular_momentum;
52 magnetic_projection <= angular_momentum;
53 magnetic_projection++) {
54 int combined_index =
55 harmonic_combined_degree_order_index(angular_momentum, magnetic_projection);
56 if (combined_index < number_of_lm_components) {
57 spherical_harmonics_at_g_[g_index][combined_index] =
59 angular_momentum, magnetic_projection, g_cartesian);
60 }
61 }
62 }
63 }
64 }
65
66 /**
67 * Access Y_lm(Ĝ) for a given G-vector index and combined (l,m) index.
68 */
69 [[nodiscard]] Real value(int g_index, int combined_lm_index) const {
70 if (combined_lm_index < static_cast<int>(spherical_harmonics_at_g_[g_index].size())) {
71 return spherical_harmonics_at_g_[g_index][combined_lm_index];
72 }
73 return 0.0;
74 }
75
76 /**
77 * Number of (l,m) components: (lmax+1)².
78 */
79 [[nodiscard]] int number_of_lm_components() const {
80 return (maximum_angular_momentum_ + 1) * (maximum_angular_momentum_ + 1);
81 }
82
83 [[nodiscard]] int maximum_angular_momentum() const {
84 return maximum_angular_momentum_;
85 }
86
87 private:
88 int maximum_angular_momentum_{0};
89 std::vector<std::vector<Real>> spherical_harmonics_at_g_;
90};
91
92} // namespace q3
Real two_pi_over_lattice_parameter() const
Definition crystal.hpp:196
int number_of_g_vectors() const
Definition init.hpp:145
const std::vector< GVector > & g_vectors() const
Definition init.hpp:148
void init(const Crystal &crystal_structure, const PlanewaveBasis &planewave_basis, int maximum_angular_momentum)
Real value(int g_index, int combined_lm_index) const
int harmonic_combined_degree_order_index(int degree, int order)
Definition harmonics.hpp:61
double Real
Real compute_real_spherical_harmonic(int degree, int order, const Vector3D &direction)
Definition harmonics.hpp:85