Loading...
Searching...
No Matches
projector_mapping_table.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * ProjectorMappingTable — Kleinman-Bylander projector channel mapping tables.
5 *
6 * Expands the radial beta projectors into (l,m)-resolved projector channels
7 * and provides the reverse mapping from channel index back to radial index,
8 * angular momentum, magnetic quantum number, and combined (l,m) index.
9 */
10
11#include <vector>
12
17
18namespace q3 {
19
21 public:
23
24 /**
25 * Build the projector expansion tables for all species and compute total projector count.
26 * @param crystal_structure Crystal (needed for atom→species mapping)
27 * @param pseudopotential_set The pseudopotentials
28 * @param number_of_species_types Number of distinct species
29 */
30 void build(const Crystal& crystal_structure,
31 const PseudopotentialSet& pseudopotential_set,
32 int number_of_species_types) {
33 total_number_of_projectors_ = 0;
34 channels_per_type_.resize(number_of_species_types);
35 to_beta_index_.resize(number_of_species_types);
36 angular_momentum_.resize(number_of_species_types);
37 magnetic_quantum_number_.resize(number_of_species_types);
38 combined_lm_index_.resize(number_of_species_types);
39
40 for (int type_index = 0; type_index < number_of_species_types; type_index++) {
41 int channel_count = 0;
42 for (int projector_index = 0;
43 projector_index <
44 static_cast<int>(pseudopotential_set[type_index].projectors.size());
45 projector_index++) {
46 int angular_momentum_value =
47 pseudopotential_set[type_index].projectors[projector_index].angular_momentum;
48 for (int magnetic_projection : harmonic_order_sequence(angular_momentum_value)) {
49 to_beta_index_[type_index].push_back(projector_index);
50 angular_momentum_[type_index].push_back(angular_momentum_value);
51 magnetic_quantum_number_[type_index].push_back(magnetic_projection);
52 combined_lm_index_[type_index].push_back(harmonic_combined_degree_order_index(
53 angular_momentum_value, magnetic_projection));
54 channel_count++;
55 }
56 }
57 channels_per_type_[type_index] = channel_count;
58 }
59
60 for (int atom_index = 0; atom_index < crystal_structure.number_of_atoms(); atom_index++) {
61 int species_type = crystal_structure.species_type_index(atom_index);
62 total_number_of_projectors_ += channels_per_type_[species_type];
63 }
64 }
65
66 // ─── Accessors ─────────────────────────────────────────────────
67
68 /**
69 * Total Kleinman-Bylander projectors across all atoms.
70 */
71 [[nodiscard]] int total_number_of_projectors() const {
72 return total_number_of_projectors_;
73 }
74
75 /**
76 * Number of expanded projector channels for a species (sum of 2l+1).
77 */
78 [[nodiscard]] int number_of_channels(int species_type) const {
79 return channels_per_type_[species_type];
80 }
81
82 /**
83 * Map an expanded channel back to its radial beta projector index.
84 */
85 [[nodiscard]] int to_beta_index(int species_type, int channel_index) const {
86 return to_beta_index_[species_type][channel_index];
87 }
88
89 /**
90 * Angular momentum l of an expanded channel.
91 */
92 [[nodiscard]] int angular_momentum(int species_type, int channel_index) const {
93 return angular_momentum_[species_type][channel_index];
94 }
95
96 /**
97 * Magnetic quantum number m of an expanded channel.
98 */
99 [[nodiscard]] int magnetic_quantum_number(int species_type, int channel_index) const {
100 return magnetic_quantum_number_[species_type][channel_index];
101 }
102
103 /**
104 * Combined (l,m) index for an expanded channel (QE convention: l² + offset).
105 */
106 [[nodiscard]] int combined_lm_index(int species_type, int channel_index) const {
107 return combined_lm_index_[species_type][channel_index];
108 }
109
110 /**
111 * Raw access to the channels-per-type table (needed by USPP newd).
112 */
113 [[nodiscard]] const std::vector<int>& channels_per_type_table() const {
114 return channels_per_type_;
115 }
116
117 /**
118 * Raw access to the to_beta_index table (needed by USPP newd).
119 */
120 [[nodiscard]] const std::vector<std::vector<int>>& to_beta_index_table() const {
121 return to_beta_index_;
122 }
123
124 /**
125 * Raw access to the combined_lm_index table (needed by USPP newd).
126 */
127 [[nodiscard]] const std::vector<std::vector<int>>& combined_lm_index_table() const {
128 return combined_lm_index_;
129 }
130
131 /**
132 * Raw access to the angular_momentum table (needed by USPP newd).
133 */
134 [[nodiscard]] const std::vector<std::vector<int>>& angular_momentum_table() const {
135 return angular_momentum_;
136 }
137
138 private:
139 int total_number_of_projectors_{};
140 std::vector<int> channels_per_type_;
141 std::vector<std::vector<int>> to_beta_index_;
142 std::vector<std::vector<int>> angular_momentum_;
143 std::vector<std::vector<int>> magnetic_quantum_number_;
144 std::vector<std::vector<int>> combined_lm_index_;
145};
146
147} // namespace q3
int species_type_index(int atom_index) const
Definition crystal.hpp:273
int number_of_atoms() const
Definition crystal.hpp:209
int number_of_channels(int species_type) const
int to_beta_index(int species_type, int channel_index) const
const std::vector< std::vector< int > > & combined_lm_index_table() const
int magnetic_quantum_number(int species_type, int channel_index) const
const std::vector< std::vector< int > > & to_beta_index_table() const
void build(const Crystal &crystal_structure, const PseudopotentialSet &pseudopotential_set, int number_of_species_types)
const std::vector< std::vector< int > > & angular_momentum_table() const
int angular_momentum(int species_type, int channel_index) const
int combined_lm_index(int species_type, int channel_index) const
const std::vector< int > & channels_per_type_table() const
int size() const
Definition set.hpp:98
int harmonic_combined_degree_order_index(int degree, int order)
Definition harmonics.hpp:61
std::vector< int > harmonic_order_sequence(int degree)
Definition harmonics.hpp:40