40 const std::vector<int>& mesh_sizes,
41 int number_of_q_points,
44 number_of_q_points_ = number_of_q_points;
45 q_spacing_ = q_spacing;
46 cell_volume_ = cell_volume;
48 int number_of_species_types =
static_cast<int>(pseudopotential_set.
size());
50 determine_maximum_angular_momentum_q(pseudopotential_set, number_of_species_types);
51 build_all_tables(pseudopotential_set, mesh_sizes, number_of_species_types);
59 int projector_pair_index,
61 Real q_value)
const override {
62 if (species_type_index >=
static_cast<int>(augmentation_q_radial_table_.size()) ||
63 projector_pair_index >=
64 static_cast<int>(augmentation_q_radial_table_[species_type_index].size()) ||
67 augmentation_q_radial_table_[species_type_index][projector_pair_index]
69 augmentation_q_radial_table_[species_type_index][projector_pair_index][angular_momentum]
74 augmentation_q_radial_table_[species_type_index][projector_pair_index]
86 int projector_pair_index,
88 Real q_value)
const override {
89 if (species_type_index >=
static_cast<int>(augmentation_q_radial_table_.size()) ||
90 projector_pair_index >=
91 static_cast<int>(augmentation_q_radial_table_[species_type_index].size()) ||
94 augmentation_q_radial_table_[species_type_index][projector_pair_index]
96 augmentation_q_radial_table_[species_type_index][projector_pair_index][angular_momentum]
101 augmentation_q_radial_table_[species_type_index][projector_pair_index]
105 number_of_q_points_);
112 int projector_pair_index,
113 Real q_value)
const override {
114 if (q_function_table_.empty() || q_function_table_[species_type_index].empty())
117 q_function_table_[species_type_index][projector_pair_index],
120 number_of_q_points_);
124 return maximum_angular_momentum_q_;
129 void determine_maximum_angular_momentum_q(
const PseudopotentialSet& pseudopotential_set,
130 int number_of_species_types) {
131 maximum_angular_momentum_q_ = 0;
132 for (
int species_type_index = 0; species_type_index < number_of_species_types;
133 species_type_index++) {
141 if (!pseudopotential_set[species_type_index].has_augmentation_charges()) {
144 const auto& ultrasoft_pseudopotential =
146 if (ultrasoft_pseudopotential.number_of_q_angular_momenta > 0) {
147 maximum_angular_momentum_q_ =
148 std::max(maximum_angular_momentum_q_,
149 ultrasoft_pseudopotential.number_of_q_angular_momenta - 1);
152 if (maximum_angular_momentum_q_ == 0) {
153 for (
int species_type_index = 0; species_type_index < number_of_species_types;
154 species_type_index++) {
155 maximum_angular_momentum_q_ =
156 std::max(maximum_angular_momentum_q_,
157 2 * pseudopotential_set[species_type_index].maximum_angular_momentum);
163 void build_all_tables(
const PseudopotentialSet& pseudopotential_set,
164 const std::vector<int>& mesh_sizes,
165 int number_of_species_types) {
166 augmentation_q_radial_table_.resize(number_of_species_types);
167 q_function_table_.resize(number_of_species_types);
168 for (
int species_type_index = 0; species_type_index < number_of_species_types;
169 species_type_index++) {
177 if (!pseudopotential_set[species_type_index].has_augmentation_charges()) {
180 build_tables_for_species(pseudopotential_set.as_ultrasoft(species_type_index),
181 mesh_sizes[species_type_index],
194 void build_tables_for_species(
const UltrasoftPseudopotential& pseudopotential,
196 int species_type_index) {
197 int number_of_projectors = pseudopotential.number_of_projectors;
198 int number_of_q_angular_momenta = pseudopotential.number_of_q_angular_momenta > 0
199 ? pseudopotential.number_of_q_angular_momenta
200 : (2 * pseudopotential.maximum_angular_momentum + 1);
202 augmentation_q_radial_table_[species_type_index].resize(number_of_projectors *
203 number_of_projectors);
204 q_function_table_[species_type_index].resize(number_of_projectors * number_of_projectors);
207 for (
int beta_index_i = 0; beta_index_i < number_of_projectors; beta_index_i++) {
208 for (
int beta_index_j = beta_index_i; beta_index_j < number_of_projectors;
210 int projector_pair_index = beta_index_i * number_of_projectors + beta_index_j;
211 int reverse_projector_pair_index =
212 beta_index_j * number_of_projectors + beta_index_i;
213 augmentation_q_radial_table_[species_type_index][projector_pair_index].resize(
214 number_of_q_angular_momenta);
215 augmentation_q_radial_table_[species_type_index][reverse_projector_pair_index]
216 .resize(number_of_q_angular_momenta);
217 for (
int angular_momentum = 0; angular_momentum < number_of_q_angular_momenta;
218 angular_momentum++) {
219 augmentation_q_radial_table_[species_type_index][projector_pair_index]
221 .assign(number_of_q_points_, 0.0);
222 augmentation_q_radial_table_[species_type_index][reverse_projector_pair_index]
224 .assign(number_of_q_points_, 0.0);
230 struct ProjectorPairInfo {
233 int projector_pair_index;
234 int reverse_projector_pair_index;
235 const std::vector<Real>* augmentation_function_data;
241 std::vector<Real> bessel_values(mesh_size);
242 std::vector<Real> integrand(mesh_size);
248 for (
int angular_momentum = 0; angular_momentum < number_of_q_angular_momenta;
249 angular_momentum++) {
252 std::vector<ProjectorPairInfo> active_pairs;
253 for (
int beta_index_i = 0; beta_index_i < number_of_projectors; beta_index_i++) {
254 for (
int beta_index_j = beta_index_i; beta_index_j < number_of_projectors;
256 int angular_momentum_i =
257 pseudopotential.projectors[beta_index_i].angular_momentum;
258 int angular_momentum_j =
259 pseudopotential.projectors[beta_index_j].angular_momentum;
262 if (angular_momentum < std::abs(angular_momentum_i - angular_momentum_j) ||
263 angular_momentum > angular_momentum_i + angular_momentum_j ||
264 (angular_momentum + angular_momentum_i + angular_momentum_j) % 2 != 0) {
268 int projector_pair_index = beta_index_i * number_of_projectors + beta_index_j;
269 int reverse_projector_pair_index =
270 beta_index_j * number_of_projectors + beta_index_i;
273 const std::vector<Real>* augmentation_function_data =
nullptr;
274 if (!pseudopotential.augmentation_function_by_angular_momentum.empty() &&
275 projector_pair_index <
277 pseudopotential.augmentation_function_by_angular_momentum.size()) &&
281 .augmentation_function_by_angular_momentum[projector_pair_index]
284 .augmentation_function_by_angular_momentum[projector_pair_index]
287 augmentation_function_data =
289 .augmentation_function_by_angular_momentum[projector_pair_index]
291 }
else if (projector_pair_index <
292 static_cast<int>(pseudopotential.augmentation_function.size()) &&
293 !pseudopotential.augmentation_function[projector_pair_index]
309 augmentation_function_data =
310 &pseudopotential.augmentation_function[projector_pair_index];
313 if (!augmentation_function_data ||
314 static_cast<int>(augmentation_function_data->size()) < mesh_size) {
318 active_pairs.push_back({beta_index_i,
320 projector_pair_index,
321 reverse_projector_pair_index,
322 augmentation_function_data});
326 if (active_pairs.empty())
330 for (
int q_index = 0; q_index < number_of_q_points_; q_index++) {
331 Real q_value = q_index * q_spacing_;
336 pseudopotential.radial_grid.data(),
338 bessel_values.data());
341 for (
const auto& pair : active_pairs) {
343 const auto& q_func = *pair.augmentation_function_data;
344 for (
int radial_index = 0; radial_index < mesh_size; radial_index++) {
345 Real integrand_value = q_func[radial_index] * bessel_values[radial_index] *
346 pseudopotential.radial_grid_derivative[radial_index];
348 if (radial_index == 0 || radial_index == mesh_size - 1)
350 else if (radial_index % 2 == 1)
354 sum += weight * integrand_value;
356 Real table_value = sum / 3.0 * prefactor;
357 augmentation_q_radial_table_[species_type_index][pair.projector_pair_index]
358 [angular_momentum][q_index] = table_value;
359 augmentation_q_radial_table_[species_type_index]
360 [pair.reverse_projector_pair_index]
361 [angular_momentum][q_index] = table_value;
367 for (
int beta_index_i = 0; beta_index_i < number_of_projectors; beta_index_i++) {
368 for (
int beta_index_j = beta_index_i; beta_index_j < number_of_projectors;
370 int projector_pair_index = beta_index_i * number_of_projectors + beta_index_j;
371 int reverse_projector_pair_index =
372 beta_index_j * number_of_projectors + beta_index_i;
374 if (!augmentation_q_radial_table_[species_type_index][projector_pair_index]
376 !augmentation_q_radial_table_[species_type_index][projector_pair_index][0]
378 q_function_table_[species_type_index][projector_pair_index] =
379 augmentation_q_radial_table_[species_type_index][projector_pair_index][0];
380 q_function_table_[species_type_index][reverse_projector_pair_index] =
381 augmentation_q_radial_table_[species_type_index][projector_pair_index][0];
383 q_function_table_[species_type_index][projector_pair_index].assign(
384 number_of_q_points_, 0.0);
385 q_function_table_[species_type_index][reverse_projector_pair_index].assign(
386 number_of_q_points_, 0.0);
393 std::vector<std::vector<std::vector<std::vector<Real>>>> augmentation_q_radial_table_;
396 std::vector<std::vector<std::vector<Real>>> q_function_table_;
398 int maximum_angular_momentum_q_{0};
399 int number_of_q_points_{};