51 const Crystal& crystal_structure,
54 const std::vector<std::vector<Complex>>& potential_g_by_spin,
57 : crystal_structure_(crystal_structure)
58 , planewave_basis_(planewave_basis)
59 , quantum_system_(quantum_system)
60 , potential_g_by_spin_(potential_g_by_spin)
61 , coefficients_by_spin_(coefficients_by_spin)
65 for (
int index_a = 0; index_a < 3; index_a++)
66 for (
int index_b = 0; index_b < 3; index_b++)
71 if (potential_g_by_spin_.size() != coefficients_by_spin_.size())
72 throw std::runtime_error(
73 "augmentation stress: " + std::to_string(potential_g_by_spin_.size()) +
74 " potential channels against " + std::to_string(coefficients_by_spin_.size()) +
75 " occupancy channels; they must pair up spin by spin");
77 for (
size_t spin_index = 0; spin_index < potential_g_by_spin_.size(); spin_index++)
78 accumulate_spin_channel(potential_g_by_spin_[spin_index],
79 coefficients_by_spin_[spin_index]);
86 for (
int index_a = 0; index_a < 3; index_a++) {
87 for (
int index_b = index_a + 1; index_b < 3; index_b++) {
91 result_.
augmentation[index_a][index_b] = average_stress_component;
92 result_.
augmentation[index_b][index_a] = average_stress_component;
106 void accumulate_spin_channel(
const std::vector<Complex>& total_potential_g,
113 auto& ultrasoft_system =
115 const auto& augmentation_q_table =
117 const auto& spherical_harmonics_table =
118 ultrasoft_system.ultrasoft_basis().spherical_harmonics_table();
119 const auto& gaunt_table = ultrasoft_system.ultrasoft_basis().gaunt_table();
120 int number_of_lm_components = spherical_harmonics_table.number_of_lm_components();
121 const auto& projector_mapping_table =
125 std::vector<std::array<Real, 3>> g_cartesian_vectors(number_of_g_vectors);
126 std::vector<Real> g_squared_values(number_of_g_vectors);
129 for (
int g_index = 0; g_index < number_of_g_vectors; g_index++) {
130 const auto& g_vector = planewave_basis_.
g_vectors()[g_index];
131 g_cartesian_vectors[g_index] = {g_vector.g_cart.x * two_pi_over_lattice_parameter,
132 g_vector.g_cart.y * two_pi_over_lattice_parameter,
133 g_vector.g_cart.z * two_pi_over_lattice_parameter};
134 g_squared_values[g_index] =
135 g_cartesian_vectors[g_index][0] * g_cartesian_vectors[g_index][0] +
136 g_cartesian_vectors[g_index][1] * g_cartesian_vectors[g_index][1] +
137 g_cartesian_vectors[g_index][2] * g_cartesian_vectors[g_index][2];
141 std::vector<Real> inverse_g_magnitude(number_of_g_vectors, 0.0);
142 for (
int g_index = first_nonzero_g_index; g_index < number_of_g_vectors; g_index++) {
144 inverse_g_magnitude[g_index] = 1.0 / g_vector_magnitudes[g_index];
155 for (
int polarization_index_b = 0; polarization_index_b < 3; polarization_index_b++) {
158 std::vector<std::vector<Real>> spherical_harmonic_derivatives_beta;
163 polarization_index_b,
164 spherical_harmonic_derivatives_beta);
167 int number_of_species =
static_cast<int>(
169 for (
int species_type_index = 0; species_type_index < number_of_species;
170 species_type_index++) {
176 int number_of_projectors =
177 projector_mapping_table.number_of_channels(species_type_index);
180 .number_of_projectors;
181 int maximum_angular_momentum_q_plus_one =
182 augmentation_q_table.maximum_angular_momentum_q() + 1;
183 int number_of_lm_projectors =
184 maximum_angular_momentum_q_plus_one * maximum_angular_momentum_q_plus_one;
192 int number_of_triangle_pairs =
193 number_of_projectors * (number_of_projectors + 1) / 2;
195 std::vector<Complex> dqg(
static_cast<size_t>(number_of_triangle_pairs) *
199 int triangle_pair_index = 0;
200 for (
int projector_index_i = 0; projector_index_i < number_of_projectors;
201 projector_index_i++) {
202 for (
int projector_index_j = projector_index_i;
203 projector_index_j < number_of_projectors;
204 projector_index_j++, triangle_pair_index++) {
206 int combined_lm_index_i = projector_mapping_table.combined_lm_index(
207 species_type_index, projector_index_i);
208 int combined_lm_index_j = projector_mapping_table.combined_lm_index(
209 species_type_index, projector_index_j);
210 int angular_momentum_i = projector_mapping_table.angular_momentum(
211 species_type_index, projector_index_i);
212 int angular_momentum_j = projector_mapping_table.angular_momentum(
213 species_type_index, projector_index_j);
214 int beta_index_i = projector_mapping_table.to_beta_index(species_type_index,
216 int beta_index_j = projector_mapping_table.to_beta_index(species_type_index,
218 int projector_pair_index =
219 beta_index_i * number_of_beta_functions + beta_index_j;
221 if (combined_lm_index_i >= number_of_lm_projectors ||
222 combined_lm_index_j >= number_of_lm_projectors)
224 if (gaunt_table.number_of_nonzero_product_indices[combined_lm_index_i]
225 [combined_lm_index_j] == 0)
229 &dqg[
static_cast<size_t>(triangle_pair_index) * number_of_g_vectors];
232 for (
int gaunt_index = 0;
234 gaunt_table.number_of_nonzero_product_indices[combined_lm_index_i]
235 [combined_lm_index_j];
237 int product_lm_index =
239 .nonzero_product_indices[combined_lm_index_i]
240 [combined_lm_index_j][gaunt_index];
241 Real gaunt_coefficient_value =
242 gaunt_table.coefficients[product_lm_index][combined_lm_index_i]
243 [combined_lm_index_j];
244 int angular_momentum =
245 static_cast<int>(std::sqrt(
static_cast<double>(product_lm_index)));
246 if (angular_momentum <
247 std::abs(angular_momentum_i - angular_momentum_j) ||
248 angular_momentum > angular_momentum_i + angular_momentum_j ||
249 (angular_momentum + angular_momentum_i + angular_momentum_j) % 2 !=
253 int phase_type = angular_momentum % 4;
256 for (
int g_index = first_nonzero_g_index; g_index < number_of_g_vectors;
258 Real g_abs = g_vector_magnitudes[g_index];
262 Real augmentation_function_value =
263 augmentation_q_table.interpolate_augmentation_function(
265 projector_pair_index,
269 Real augmentation_function_derivative_value =
271 .interpolate_augmentation_function_derivative(
273 projector_pair_index,
278 spherical_harmonics_table.value(g_index, product_lm_index);
280 spherical_harmonic_derivatives_beta[g_index][product_lm_index];
282 Real g_beta = g_cartesian_vectors[g_index][polarization_index_b];
283 Real derivative_contribution =
284 dylm_value * augmentation_function_value +
285 ylm_value * augmentation_function_derivative_value * g_beta *
286 inverse_g_magnitude[g_index];
288 Real weighted = gaunt_coefficient_value * derivative_contribution;
290 switch (phase_type) {
292 dqg_pair[g_index] +=
Complex(weighted, 0.0);
295 dqg_pair[g_index] +=
Complex(0.0, -weighted);
298 dqg_pair[g_index] +=
Complex(-weighted, 0.0);
301 dqg_pair[g_index] +=
Complex(0.0, weighted);
310 for (
int atom_index = 0; atom_index < number_of_atoms; atom_index++) {
315 std::vector<Complex> aux(number_of_g_vectors,
Complex(0.0, 0.0));
317 triangle_pair_index = 0;
318 for (
int projector_index_i = 0; projector_index_i < number_of_projectors;
319 projector_index_i++) {
320 for (
int projector_index_j = projector_index_i;
321 projector_index_j < number_of_projectors;
322 projector_index_j++, triangle_pair_index++) {
323 int projector_pair_linear =
324 projector_index_i * number_of_projectors + projector_index_j;
325 Real projector_overlap_coefficient =
326 (projector_pair_linear <
327 static_cast<int>(projector_overlap_coefficients.
cols()))
328 ? projector_overlap_coefficients(atom_index,
329 projector_pair_linear)
331 if (std::abs(projector_overlap_coefficient) <
334 Real symmetry_factor =
335 (projector_index_i == projector_index_j) ? 1.0 : 2.0;
336 Real coefficient = projector_overlap_coefficient * symmetry_factor;
339 &dqg[
static_cast<size_t>(triangle_pair_index) *
340 number_of_g_vectors];
341 for (
int g_index = 0; g_index < number_of_g_vectors; g_index++) {
342 aux[g_index] += coefficient * dqg_pair[g_index];
348 Vector3D atomic_position =
350 for (
int g_index = first_nonzero_g_index; g_index < number_of_g_vectors;
352 const auto& g_vector = planewave_basis_.
g_vectors()[g_index];
355 aux[g_index] *= std::conj(total_potential_g[g_index]) * structure_factor;
359 for (
int polarization_index_a = 0; polarization_index_a < 3;
360 polarization_index_a++) {
361 Real sigma_component = 0.0;
362 Real reciprocal_space_multiplicity =
364 for (
int g_index = first_nonzero_g_index; g_index < number_of_g_vectors;
366 Real g_alpha = g_cartesian_vectors[g_index][polarization_index_a];
367 sigma_component += reciprocal_space_multiplicity *
368 (
Complex(g_alpha, 0.0) * aux[g_index]).real();
370 result_.
augmentation[polarization_index_a][polarization_index_b] +=
378 const Crystal& crystal_structure_;
379 const PlanewaveBasis& planewave_basis_;
380 const NormConservingPlanewaveKohnShamQuantumSystem& quantum_system_;
381 const std::vector<std::vector<Complex>>& potential_g_by_spin_;
382 const std::vector<Matrix<Real>>& coefficients_by_spin_;
383 StressTensorContributions& result_;