72 const std::vector<std::vector<Complex>>& potential_g_by_spin,
75 std::vector<Vector3D> forces(number_of_atoms, {0.0, 0.0, 0.0});
79 if (potential_g_by_spin.size() != coefficients_by_spin.size())
80 throw std::runtime_error(
81 "augmentation force: " + std::to_string(potential_g_by_spin.size()) +
82 " potential channels against " + std::to_string(coefficients_by_spin.size()) +
83 " occupancy channels; they must pair up spin by spin");
85 const auto& ultrasoft_basis =
99 std::vector<Complex> augmentation_g(number_of_g_vectors);
101 for (
size_t spin_index = 0; spin_index < potential_g_by_spin.size(); spin_index++) {
102 const std::vector<Complex>& total_potential_g = potential_g_by_spin[spin_index];
103 const Matrix<Real>& projector_overlap_coefficients = coefficients_by_spin[spin_index];
105 for (
int atom_index = 0; atom_index < number_of_atoms; atom_index++) {
107 if (!ultrasoft_basis.has_q_functions_g(species_index))
110 int number_of_channels =
119 std::fill(augmentation_g.begin(), augmentation_g.end(),
Complex(0.0, 0.0));
120 for (
int channel_i = 0; channel_i < number_of_channels; channel_i++) {
121 int diagonal_pair = channel_i * number_of_channels + channel_i;
122 Real diagonal_projector_overlap_coefficient =
123 projector_overlap_coefficients(atom_index, diagonal_pair);
124 if (std::abs(diagonal_projector_overlap_coefficient) >=
126 const Complex* q_g = ultrasoft_basis.q_function_g_data(
127 species_index, diagonal_pair, number_of_g_vectors);
128 for (
int g_index = 0; g_index < number_of_g_vectors; g_index++)
129 augmentation_g[g_index] +=
130 diagonal_projector_overlap_coefficient * q_g[g_index];
133 for (
int channel_j = channel_i + 1; channel_j < number_of_channels;
135 int pair_ij = channel_i * number_of_channels + channel_j;
136 int pair_ji = channel_j * number_of_channels + channel_i;
137 Real combined_projector_overlap_coefficient =
138 projector_overlap_coefficients(atom_index, pair_ij) +
139 projector_overlap_coefficients(atom_index, pair_ji);
140 if (std::abs(combined_projector_overlap_coefficient) <
143 const Complex* q_g = ultrasoft_basis.q_function_g_data(
144 species_index, pair_ij, number_of_g_vectors);
145 for (
int g_index = 0; g_index < number_of_g_vectors; g_index++)
146 augmentation_g[g_index] +=
147 combined_projector_overlap_coefficient * q_g[g_index];
163 g_index < number_of_g_vectors;
165 const auto& g_vector = planewave_basis_.
g_vectors()[g_index];
167 Complex contribution = std::conj(total_potential_g[g_index]) *
169 Real weight = half_sphere_scale * cell_volume * contribution.imag();
171 for (
int direction = 0; direction < 3; direction++) {
172 Real g_cartesian_component =
173 g_vector.g_cart[direction] * two_pi_over_lattice_parameter;
174 forces[atom_index][direction] -= g_cartesian_component * weight;