62 [[nodiscard]] std::vector<Vector3D>
compute()
const {
65 std::vector<Vector3D> nonlocal_force(crystal_structure_.
number_of_atoms(), {0.0, 0.0, 0.0});
66 int total_number_of_kpoint_sets =
70 for (
int kpoint_spin_index = 0; kpoint_spin_index < total_number_of_kpoint_sets;
71 kpoint_spin_index++) {
72 int kpoint_index = (kpoint_spin_index % number_of_kpoints);
75 Vector3D kpoint_vector = kpoint_grid_[kpoint_index].coordinates;
76 Real kpoint_weight = kpoint_grid_[kpoint_index].weight;
78 const Matrix3x3& reciprocal_lattice_vectors =
81 for (
int direction = 0; direction < 3; direction++) {
82 kpoint_cartesian[direction] =
83 kpoint_vector.
x * reciprocal_lattice_vectors[0][direction] +
84 kpoint_vector.
y * reciprocal_lattice_vectors[1][direction] +
85 kpoint_vector.
z * reciprocal_lattice_vectors[2][direction];
96 number_of_plane_waves,
101 std::vector<int> occupied_band_indices;
102 std::vector<Real> occupied_band_weights;
103 std::vector<Real> occupied_band_occupations;
108 std::vector<Real> occupied_band_eigenvalues;
109 for (
int band_index = 0; band_index < scf_state_.
number_of_bands(); band_index++) {
110 Real occupation = scf_state_.
occupation(kpoint_spin_index, band_index);
113 occupied_band_indices.push_back(band_index);
114 occupied_band_weights.push_back(kpoint_weight * occupation);
115 occupied_band_occupations.push_back(occupation);
116 occupied_band_eigenvalues.push_back(
117 scf_state_.
eigenvalue(kpoint_spin_index, band_index));
119 int number_of_occupied_bands =
static_cast<int>(occupied_band_indices.size());
120 if (number_of_occupied_bands == 0)
123 int number_of_projectors =
127 std::vector<std::vector<Complex>> minus_i_k_plus_g(
128 3, std::vector<Complex>(number_of_plane_waves));
129 for (
int plane_wave_index = 0; plane_wave_index < number_of_plane_waves;
130 plane_wave_index++) {
131 const auto& g_vector =
132 planewave_basis_.
g_vectors()[plane_wave_indices[plane_wave_index]];
133 for (
int direction = 0; direction < 3; direction++) {
134 Real k_plus_g_direction =
135 (g_vector.g_cart[direction] + kpoint_cartesian[direction]) *
137 minus_i_k_plus_g[direction][plane_wave_index] =
138 Complex(0.0, -k_plus_g_direction);
147 std::vector<std::vector<Complex>> batched_overlaps(
148 4, std::vector<Complex>(number_of_projectors * number_of_occupied_bands));
150 std::vector<Complex> modified_wavefunction(number_of_plane_waves *
151 number_of_occupied_bands);
155 int blas_rows = number_of_projectors;
156 int blas_columns = number_of_occupied_bands;
157 int blas_inner_dimension = number_of_plane_waves;
159 for (
int component = 0; component < 4; component++) {
160 for (
int occupied_band_index = 0; occupied_band_index < number_of_occupied_bands;
161 occupied_band_index++) {
162 int band_index = occupied_band_indices[occupied_band_index];
163 int offset = occupied_band_index * number_of_plane_waves;
164 for (
int g_index = 0; g_index < number_of_plane_waves; g_index++) {
166 kpoint_spin_index, band_index, g_index);
167 if (component == 0) {
168 modified_wavefunction[offset + g_index] = psi;
170 modified_wavefunction[offset + g_index] =
171 psi * minus_i_k_plus_g[component - 1][g_index];
180 &blas_inner_dimension,
181 reinterpret_cast<const std::complex<double>*
>(&alpha_blas),
182 reinterpret_cast<const std::complex<double>*
>(projector_functions.
data()),
183 &blas_inner_dimension,
184 reinterpret_cast<const std::complex<double>*
>(modified_wavefunction.data()),
185 &blas_inner_dimension,
186 reinterpret_cast<const std::complex<double>*
>(&beta_blas),
187 reinterpret_cast<std::complex<double>*
>(batched_overlaps[component].data()),
203 for (
auto& component_overlaps : batched_overlaps)
205 component_overlaps.data(),
static_cast<int>(component_overlaps.size()));
227 std::vector<Real> gamma_g0_overlap;
229 gamma_g0_overlap.assign(
230 static_cast<size_t>(number_of_projectors) * number_of_occupied_bands, 0.0);
232 for (
int plane_wave_index = 0; plane_wave_index < number_of_plane_waves;
233 plane_wave_index++) {
234 if (planewave_basis_.
g_vectors()[plane_wave_indices[plane_wave_index]]
236 g0_index = plane_wave_index;
241 for (
int projector = 0; projector < number_of_projectors; projector++) {
242 for (
int occupied_band_index = 0;
243 occupied_band_index < number_of_occupied_bands;
244 occupied_band_index++) {
247 occupied_band_indices[occupied_band_index],
249 gamma_g0_overlap[
static_cast<size_t>(projector) *
250 number_of_occupied_bands +
251 occupied_band_index] =
252 (std::conj(projector_functions[projector][g0_index]) * psi).real();
259 int current_projector_index = 0;
260 for (
int atom_index = 0; atom_index < crystal_structure_.
number_of_atoms();
263 int number_of_beta_functions =
267 std::vector<int> beta_indices, magnetic_quantum_numbers, angular_momenta;
268 int starting_projector_index = current_projector_index;
269 for (
int beta_function_index = 0; beta_function_index < number_of_beta_functions;
270 beta_function_index++) {
271 int angular_momentum =
273 species_index, beta_function_index);
275 beta_indices.push_back(beta_function_index);
276 magnetic_quantum_numbers.push_back(magnetic_projection);
277 angular_momenta.push_back(angular_momentum);
278 current_projector_index++;
281 int number_of_projectors_on_atom =
static_cast<int>(beta_indices.size());
283 for (
int projector_a_index = 0; projector_a_index < number_of_projectors_on_atom;
284 projector_a_index++) {
285 for (
int projector_b_index = 0;
286 projector_b_index < number_of_projectors_on_atom;
287 projector_b_index++) {
293 Real hamiltonian_d_coefficient =
325 Real augmentation_overlap = 0.0;
331 angular_momenta[projector_a_index] ==
332 angular_momenta[projector_b_index] &&
333 magnetic_quantum_numbers[projector_a_index] ==
334 magnetic_quantum_numbers[projector_b_index]) {
335 augmentation_overlap =
339 .augmentation_overlap_integral(species_index,
340 beta_indices[projector_a_index],
341 beta_indices[projector_b_index]);
344 if (std::abs(hamiltonian_d_coefficient) <
346 std::abs(augmentation_overlap) <
351 int global_projector_a_index = starting_projector_index + projector_a_index;
352 int global_projector_b_index = starting_projector_index + projector_b_index;
354 Vector3D force_sum = {0.0, 0.0, 0.0};
355 Vector3D eigenvalue_weighted_sum = {0.0, 0.0, 0.0};
357 for (
int occupied_band_index = 0;
358 occupied_band_index < number_of_occupied_bands;
359 occupied_band_index++) {
360 Real weight = occupied_band_weights[occupied_band_index];
361 Real eigenvalue = occupied_band_eigenvalues[occupied_band_index];
364 batched_overlaps[0][occupied_band_index * number_of_projectors +
365 global_projector_b_index];
366 Complex overlap_b_0_conj = std::conj(overlap_b_0);
368 for (
int direction = 0; direction < 3; direction++) {
370 batched_overlaps[direction + 1]
371 [occupied_band_index * number_of_projectors +
372 global_projector_a_index];
374 Complex spin_summed_force_contribution =
375 overlap_a_dir * overlap_b_0_conj;
380 ? (2.0 * overlap_a_dir.real()) *
381 (2.0 * overlap_b_0.real() -
382 gamma_g0_overlap[
static_cast<size_t>(
383 global_projector_b_index) *
384 number_of_occupied_bands +
385 occupied_band_index])
386 : spin_summed_force_contribution.real();
387 force_sum[direction] += weight * term;
388 eigenvalue_weighted_sum[direction] += weight * eigenvalue * term;
392 for (
int direction = 0; direction < 3; direction++) {
393 nonlocal_force[atom_index][direction] +=
394 2.0 * (hamiltonian_d_coefficient * force_sum[direction] -
395 augmentation_overlap * eigenvalue_weighted_sum[direction]);
402 return nonlocal_force;