103 : crystal_structure_(crystal_structure)
104 , planewave_basis_(planewave_basis)
105 , kpoint_grid_(kpoint_grid)
106 , scf_state_(scf_state)
127 if (manifolds.empty() || !
supports(scf_state_))
130 compute_with_orthogonal_projectors();
144 int total_projectors = has_overlap_operator ? basis.total_number_of_projectors() : 0;
146 constexpr Real q_spacing = 0.01;
147 constexpr int number_of_q_points = 900;
149 pseudopotential_set, crystal_structure_.
cell_volume(), q_spacing, number_of_q_points);
151 auto orbital_descriptors = enumerate_atomic_orbital_descriptors();
153 size_t number_of_manifolds = manifolds.size();
154 std::vector<int> manifold_row_offsets(number_of_manifolds);
155 int total_hubbard_orbitals = 0;
156 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds; manifold_index++) {
157 manifold_row_offsets[manifold_index] = total_hubbard_orbitals;
158 total_hubbard_orbitals +=
159 static_cast<int>(manifolds[manifold_index].orbital_indices.size());
161 if (total_hubbard_orbitals == 0)
165 std::vector<AtomicOrbitalDescriptor> hubbard_descriptors(
166 static_cast<size_t>(total_hubbard_orbitals));
167 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds; manifold_index++) {
168 const auto& manifold = manifolds[manifold_index];
169 int row_offset = manifold_row_offsets[manifold_index];
170 for (
size_t m = 0; m < manifold.orbital_indices.size(); m++)
171 hubbard_descriptors[
static_cast<size_t>(row_offset) + m] =
172 orbital_descriptors[
static_cast<size_t>(manifold.orbital_indices[m])];
176 std::vector<int> projector_offset_by_atom(number_of_atoms, 0);
177 std::vector<int> channels_by_atom(number_of_atoms, 0);
179 if (total_projectors > 0) {
181 for (
int atom_index = 0; atom_index < number_of_atoms; atom_index++) {
183 int number_of_channels = basis.number_of_projector_channels(species_index);
184 projector_offset_by_atom[atom_index] = offset;
185 channels_by_atom[atom_index] = number_of_channels;
186 offset += number_of_channels;
190 auto augmentation_charge = [&](
int atom_index,
int channel_i,
int channel_j) ->
Real {
204 const Matrix3x3& reciprocal_lattice_vectors =
208 for (
int kpoint_index_state = 0; kpoint_index_state < number_of_kpoint_states;
209 kpoint_index_state++) {
210 int spin_index = kpoint_index_state / number_of_kpoints;
211 int kpoint_index = kpoint_index_state % number_of_kpoints;
214 Real kpoint_weight = kpoint_grid_[kpoint_index].weight;
218 number_of_plane_waves)
223 Vector3D kpoint_vector = kpoint_grid_[kpoint_index].coordinates;
224 for (
int direction = 0; direction < 3; direction++)
225 kpoint_cartesian[direction] =
226 kpoint_vector.
x * reciprocal_lattice_vectors[0][direction] +
227 kpoint_vector.
y * reciprocal_lattice_vectors[1][direction] +
228 kpoint_vector.
z * reciprocal_lattice_vectors[2][direction];
231 PlaneWaveGeometry geometry = build_plane_wave_geometry(
232 kpoint_cartesian, plane_wave_indices, number_of_plane_waves);
234 std::vector<Real> band_occupations(number_of_bands);
235 std::vector<int> occupied_band_indices;
236 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
237 band_occupations[band_index] =
238 scf_state_.
occupation(kpoint_index_state, band_index);
240 occupied_band_indices.push_back(band_index);
242 int number_of_occupied_bands =
static_cast<int>(occupied_band_indices.size());
243 if (number_of_occupied_bands == 0)
247 std::vector<Complex> wavefunctions(
static_cast<size_t>(number_of_plane_waves) *
248 number_of_occupied_bands);
249 for (
int occupied_index = 0; occupied_index < number_of_occupied_bands;
251 for (
int g_index = 0; g_index < number_of_plane_waves; g_index++)
252 wavefunctions[
static_cast<size_t>(occupied_index) * number_of_plane_waves +
256 occupied_band_indices[
static_cast<size_t>(occupied_index)],
259 std::vector<Complex> orbitals;
260 std::vector<Complex> orbital_radial_derivative;
261 std::array<std::vector<Complex>, 3> orbital_angular_derivative;
262 build_atomic_orbital_strain_parts(kpoint_index,
264 number_of_plane_waves,
267 atomic_wavefunction_table,
271 orbital_radial_derivative,
272 orbital_angular_derivative);
274 std::vector<Complex> beta_projectors;
275 std::vector<Complex> beta_radial_derivative;
276 std::array<std::vector<Complex>, 3> beta_angular_derivative;
277 build_beta_strain_parts(kpoint_index,
279 number_of_plane_waves,
283 beta_radial_derivative,
284 beta_angular_derivative);
286 auto contract = [&](
const Complex* left,
289 int number_of_right) {
290 std::vector<Complex> result;
292 number_of_plane_waves, number_of_left, number_of_right, left, right, result);
294 complete_gamma_only_overlaps(number_of_plane_waves,
303 result.data(),
static_cast<int>(result.size()));
308 auto orbital_band = [&](
int orbital,
int band) {
309 return static_cast<size_t>(orbital) +
310 static_cast<size_t>(band) * total_hubbard_orbitals;
312 auto orbital_projector = [&](
int orbital,
int projector) {
313 return static_cast<size_t>(orbital) +
314 static_cast<size_t>(projector) * total_hubbard_orbitals;
316 auto projector_band = [&](
int projector,
int band) {
317 return static_cast<size_t>(projector) +
318 static_cast<size_t>(band) * total_projectors;
321 auto phi_psi = contract(orbitals.data(),
322 total_hubbard_orbitals,
323 wavefunctions.data(),
324 number_of_occupied_bands);
325 auto phi_beta = contract(
326 orbitals.data(), total_hubbard_orbitals, beta_projectors.data(), total_projectors);
327 auto beta_psi = contract(beta_projectors.data(),
329 wavefunctions.data(),
330 number_of_occupied_bands);
333 std::vector<Complex> projection = phi_psi;
334 accumulate_augmentation(number_of_atoms,
336 projector_offset_by_atom,
338 total_hubbard_orbitals,
339 number_of_occupied_bands,
347 std::vector<Complex> strained_orbitals(orbitals.size());
348 std::vector<Complex> strained_betas(beta_projectors.size());
350 for (
int direction_a = 0; direction_a < 3; direction_a++) {
351 for (
int direction_b = 0; direction_b < 3; direction_b++) {
352 apply_strain_derivative(number_of_plane_waves,
353 total_hubbard_orbitals,
358 orbital_radial_derivative,
359 orbital_angular_derivative[direction_a],
361 apply_strain_derivative(number_of_plane_waves,
367 beta_radial_derivative,
368 beta_angular_derivative[direction_a],
378 auto derivative_projection = contract(strained_orbitals.data(),
379 total_hubbard_orbitals,
380 wavefunctions.data(),
381 number_of_occupied_bands);
382 auto strained_orbital_beta = contract(strained_orbitals.data(),
383 total_hubbard_orbitals,
384 beta_projectors.data(),
386 auto orbital_strained_beta = contract(orbitals.data(),
387 total_hubbard_orbitals,
388 strained_betas.data(),
390 auto strained_beta_psi = contract(strained_betas.data(),
392 wavefunctions.data(),
393 number_of_occupied_bands);
395 accumulate_augmentation(number_of_atoms,
397 projector_offset_by_atom,
399 total_hubbard_orbitals,
400 number_of_occupied_bands,
401 strained_orbital_beta,
406 derivative_projection);
407 accumulate_augmentation(number_of_atoms,
409 projector_offset_by_atom,
411 total_hubbard_orbitals,
412 number_of_occupied_bands,
413 orbital_strained_beta,
418 derivative_projection);
419 accumulate_augmentation(number_of_atoms,
421 projector_offset_by_atom,
423 total_hubbard_orbitals,
424 number_of_occupied_bands,
430 derivative_projection);
432 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds;
434 const auto& manifold = manifolds[manifold_index];
435 int manifold_size =
static_cast<int>(manifold.orbital_indices.size());
436 int row_offset = manifold_row_offsets[manifold_index];
438 Matrix<Complex> manifold_overlaps(
static_cast<size_t>(number_of_bands),
439 static_cast<size_t>(manifold_size));
440 Matrix<Complex> derivative_overlaps(
static_cast<size_t>(number_of_bands),
441 static_cast<size_t>(manifold_size));
442 for (
int m = 0; m < manifold_size; m++)
443 for (
int occupied_index = 0; occupied_index < number_of_occupied_bands;
445 size_t band_row =
static_cast<size_t>(
446 occupied_band_indices[
static_cast<size_t>(occupied_index)]);
447 manifold_overlaps(band_row,
static_cast<size_t>(m)) =
448 projection[orbital_band(row_offset + m, occupied_index)];
449 derivative_overlaps(band_row,
static_cast<size_t>(m)) =
450 derivative_projection[orbital_band(row_offset + m,
454 const auto& combined_d_matrix =
456 std::vector<Complex> manifold_d_matrix(
static_cast<size_t>(manifold_size) *
458 for (
int m = 0; m < manifold_size; m++)
459 for (
int m_prime = 0; m_prime < manifold_size; m_prime++)
460 manifold_d_matrix[
static_cast<size_t>(m * manifold_size +
462 combined_d_matrix[
static_cast<size_t>(row_offset + m) +
463 static_cast<size_t>(row_offset + m_prime) *
464 total_hubbard_orbitals];
470 result_.
hubbard[direction_a][direction_b] -=
471 inverse_cell_volume *
484 symmetrize_stress_tensor(result_.
hubbard);
489 struct AtomicOrbitalDescriptor {
490 int global_orbital_index{};
492 int species_type_index{};
493 int wavefunction_index{};
494 int angular_momentum{};
495 int combined_lm_index{};
499 struct PlaneWaveGeometry {
500 std::vector<std::array<Real, 3>> reciprocal_units;
501 std::vector<Real> magnitude_squared_reciprocal_units;
502 std::vector<std::array<Real, 3>> cartesian;
503 std::vector<Real> magnitude_bohr;
504 std::vector<Real> inverse_magnitude_bohr;
505 std::vector<std::vector<Real>> spherical_harmonics;
506 std::array<std::vector<std::vector<Real>>, 3>
507 spherical_harmonic_derivatives;
508 std::vector<std::vector<Complex>> structure_factors;
529 void compute_with_orthogonal_projectors() {
535 constexpr Real q_spacing = 0.01;
536 constexpr int number_of_q_points = 900;
538 pseudopotential_set, crystal_structure_.
cell_volume(), q_spacing, number_of_q_points);
540 auto atomic_orbital_descriptors = enumerate_atomic_orbital_descriptors();
541 int number_of_atomic_orbitals =
static_cast<int>(atomic_orbital_descriptors.size());
543 size_t number_of_manifolds = manifolds.size();
544 std::vector<int> manifold_row_offsets(number_of_manifolds);
545 int total_hubbard_orbitals = 0;
546 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds; manifold_index++) {
547 manifold_row_offsets[manifold_index] = total_hubbard_orbitals;
548 total_hubbard_orbitals +=
549 static_cast<int>(manifolds[manifold_index].orbital_indices.size());
551 if (number_of_atomic_orbitals == 0 || total_hubbard_orbitals == 0)
555 int total_projectors = pseudopotential_basis.total_number_of_projectors();
556 std::vector<int> projector_offset_by_atom(number_of_atoms, 0);
557 std::vector<int> projector_channels_by_atom(number_of_atoms, 0);
559 int projector_offset = 0;
560 for (
int atom_index = 0; atom_index < number_of_atoms; atom_index++) {
562 int number_of_projector_channels =
563 pseudopotential_basis.number_of_projector_channels(species_index);
564 projector_offset_by_atom[atom_index] = projector_offset;
565 projector_channels_by_atom[atom_index] = number_of_projector_channels;
566 projector_offset += number_of_projector_channels;
569 auto augmentation_overlap = [&](
int atom_index,
int channel_row,
int channel_column) {
571 static_cast<const UltrasoftPlanewaveKohnShamQuantumSystem&
>(
574 pseudopotential_basis,
583 const Matrix3x3& reciprocal_lattice_vectors =
587 auto orbital_matrix_element = [number_of_atomic_orbitals](
int row,
int column) {
588 return static_cast<size_t>(row + column * number_of_atomic_orbitals);
591 for (
int kpoint_index_state = 0; kpoint_index_state < number_of_kpoint_states;
592 kpoint_index_state++) {
593 int spin_index = kpoint_index_state / number_of_kpoints;
594 int kpoint_index = kpoint_index_state % number_of_kpoints;
597 Real kpoint_weight = kpoint_grid_[kpoint_index].weight;
601 number_of_plane_waves)
604 Vector3D kpoint_cartesian;
605 Vector3D kpoint_vector = kpoint_grid_[kpoint_index].coordinates;
606 for (
int direction = 0; direction < 3; direction++)
607 kpoint_cartesian[direction] =
608 kpoint_vector.x * reciprocal_lattice_vectors[0][direction] +
609 kpoint_vector.y * reciprocal_lattice_vectors[1][direction] +
610 kpoint_vector.z * reciprocal_lattice_vectors[2][direction];
612 PlaneWaveGeometry geometry = build_plane_wave_geometry(
613 kpoint_cartesian, plane_wave_indices, number_of_plane_waves);
615 std::vector<Real> band_occupations(number_of_bands);
616 std::vector<int> occupied_band_indices;
617 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
618 band_occupations[band_index] =
619 scf_state_.
occupation(kpoint_index_state, band_index);
621 occupied_band_indices.push_back(band_index);
623 int number_of_occupied_bands =
static_cast<int>(occupied_band_indices.size());
624 if (number_of_occupied_bands == 0)
627 std::vector<Complex> wavefunctions(
static_cast<size_t>(number_of_plane_waves) *
628 number_of_occupied_bands);
629 for (
int occupied_band_index = 0; occupied_band_index < number_of_occupied_bands;
630 occupied_band_index++)
631 for (
int g_index = 0; g_index < number_of_plane_waves; g_index++)
632 wavefunctions[
static_cast<size_t>(occupied_band_index) * number_of_plane_waves +
636 occupied_band_indices[
static_cast<size_t>(occupied_band_index)],
639 std::vector<Complex> atomic_orbitals;
640 std::vector<Complex> atomic_orbital_radial_derivative;
641 std::array<std::vector<Complex>, 3> atomic_orbital_angular_derivative;
642 build_atomic_orbital_strain_parts(kpoint_index,
644 number_of_plane_waves,
646 atomic_orbital_descriptors,
647 atomic_wavefunction_table,
651 atomic_orbital_radial_derivative,
652 atomic_orbital_angular_derivative);
654 std::vector<Complex> beta_projectors;
655 std::vector<Complex> beta_radial_derivative;
656 std::array<std::vector<Complex>, 3> beta_angular_derivative;
657 if (has_augmented_overlap) {
658 build_beta_strain_parts(kpoint_index,
660 number_of_plane_waves,
664 beta_radial_derivative,
665 beta_angular_derivative);
668 auto contract = [&](
const Complex* left,
671 int number_of_right) {
672 std::vector<Complex> contraction;
680 complete_gamma_only_overlaps(number_of_plane_waves,
689 contraction.data(),
static_cast<int>(contraction.size()));
693 if (has_augmented_overlap) {
695 throw std::runtime_error(
696 "Ortho-atomic ultrasoft Hubbard stress requires an execution policy");
699 Matrix<Complex> canonical_beta_projectors(
700 static_cast<size_t>(total_projectors),
701 static_cast<size_t>(number_of_plane_waves));
702 std::copy(beta_projectors.begin(),
703 beta_projectors.end(),
704 canonical_beta_projectors.data());
707 canonical_beta_projectors,
710 std::vector<Complex> overlap_applied_orbitals(atomic_orbitals.size());
711 overlap_operator->apply_batch(number_of_plane_waves,
712 number_of_atomic_orbitals,
713 atomic_orbitals.data(),
714 overlap_applied_orbitals.data());
715 std::vector<Complex> overlap_applied_wavefunctions(wavefunctions.size());
716 overlap_operator->apply_batch(number_of_plane_waves,
717 number_of_occupied_bands,
718 wavefunctions.data(),
719 overlap_applied_wavefunctions.data());
721 auto overlap_matrix = contract(atomic_orbitals.data(),
722 number_of_atomic_orbitals,
723 overlap_applied_orbitals.data(),
724 number_of_atomic_orbitals);
725 auto lowdin_transform =
727 auto atomic_band_overlaps = contract(atomic_orbitals.data(),
728 number_of_atomic_orbitals,
729 overlap_applied_wavefunctions.data(),
730 number_of_occupied_bands);
732 std::vector<Complex> projection(
static_cast<size_t>(number_of_atomic_orbitals) *
733 number_of_occupied_bands,
735 for (
int occupied_band_index = 0; occupied_band_index < number_of_occupied_bands;
736 occupied_band_index++) {
737 for (
int orbital_index = 0; orbital_index < number_of_atomic_orbitals;
739 for (
int inner_orbital_index = 0;
740 inner_orbital_index < number_of_atomic_orbitals;
741 inner_orbital_index++) {
742 projection[orbital_matrix_element(orbital_index,
743 occupied_band_index)] +=
744 lowdin_transform.inverse_square_root[orbital_matrix_element(
745 orbital_index, inner_orbital_index)] *
746 atomic_band_overlaps[orbital_matrix_element(inner_orbital_index,
747 occupied_band_index)];
752 auto apply_overlap_derivative = [&](
const Complex* input_vectors,
753 int number_of_vectors,
754 const std::vector<Complex>&
755 strained_beta_projectors) {
756 auto projector_overlaps = contract(
757 beta_projectors.data(), total_projectors, input_vectors, number_of_vectors);
758 auto strained_projector_overlaps = contract(strained_beta_projectors.data(),
762 std::vector<Complex> result(
static_cast<size_t>(number_of_plane_waves) *
765 for (
int atom_index = 0; atom_index < number_of_atoms; atom_index++) {
766 int projector_offset = projector_offset_by_atom[atom_index];
767 int number_of_projector_channels = projector_channels_by_atom[atom_index];
768 for (
int channel_row = 0; channel_row < number_of_projector_channels;
770 int projector_row = projector_offset + channel_row;
771 for (
int channel_column = 0;
772 channel_column < number_of_projector_channels;
775 augmentation_overlap(atom_index, channel_row, channel_column);
776 if (std::abs(overlap_value) <
780 int projector_column = projector_offset + channel_column;
781 for (
int vector_index = 0; vector_index < number_of_vectors;
783 size_t projector_overlap_index =
784 static_cast<size_t>(projector_column) +
785 static_cast<size_t>(vector_index) * total_projectors;
786 Complex strained_projector_coefficient =
787 overlap_value * projector_overlaps[projector_overlap_index];
788 Complex projector_coefficient =
790 strained_projector_overlaps[projector_overlap_index];
791 for (
int g_index = 0; g_index < number_of_plane_waves;
793 size_t result_index =
static_cast<size_t>(vector_index) *
794 number_of_plane_waves +
796 result[result_index] +=
797 strained_beta_projectors[
static_cast<size_t>(
799 number_of_plane_waves +
801 strained_projector_coefficient +
802 beta_projectors[
static_cast<size_t>(projector_row) *
803 number_of_plane_waves +
805 projector_coefficient;
814 std::vector<Complex> strained_atomic_orbitals(atomic_orbitals.size());
815 std::vector<Complex> strained_beta_projectors(beta_projectors.size());
816 for (
int direction_a = 0; direction_a < 3; direction_a++) {
817 for (
int direction_b = 0; direction_b < 3; direction_b++) {
818 apply_strain_derivative(number_of_plane_waves,
819 number_of_atomic_orbitals,
824 atomic_orbital_radial_derivative,
825 atomic_orbital_angular_derivative[direction_a],
826 strained_atomic_orbitals);
827 apply_strain_derivative(number_of_plane_waves,
833 beta_radial_derivative,
834 beta_angular_derivative[direction_a],
835 strained_beta_projectors);
837 std::vector<Complex> overlap_applied_strained_orbitals(
838 strained_atomic_orbitals.size());
839 overlap_operator->apply_batch(number_of_plane_waves,
840 number_of_atomic_orbitals,
841 strained_atomic_orbitals.data(),
842 overlap_applied_strained_orbitals.data());
843 auto overlap_derivative_on_orbitals =
844 apply_overlap_derivative(atomic_orbitals.data(),
845 number_of_atomic_orbitals,
846 strained_beta_projectors);
847 auto overlap_derivative_on_wavefunctions =
848 apply_overlap_derivative(wavefunctions.data(),
849 number_of_occupied_bands,
850 strained_beta_projectors);
852 auto left_orbital_metric_derivative =
853 contract(strained_atomic_orbitals.data(),
854 number_of_atomic_orbitals,
855 overlap_applied_orbitals.data(),
856 number_of_atomic_orbitals);
857 auto overlap_metric_derivative =
858 contract(atomic_orbitals.data(),
859 number_of_atomic_orbitals,
860 overlap_derivative_on_orbitals.data(),
861 number_of_atomic_orbitals);
862 auto right_orbital_metric_derivative =
863 contract(atomic_orbitals.data(),
864 number_of_atomic_orbitals,
865 overlap_applied_strained_orbitals.data(),
866 number_of_atomic_orbitals);
867 std::vector<Complex> metric_derivative(overlap_matrix.size());
868 for (
size_t matrix_index = 0; matrix_index < metric_derivative.size();
870 metric_derivative[matrix_index] =
871 left_orbital_metric_derivative[matrix_index] +
872 overlap_metric_derivative[matrix_index] +
873 right_orbital_metric_derivative[matrix_index];
875 for (
int column = 0; column < number_of_atomic_orbitals; column++) {
876 for (
int row = 0; row <= column; row++) {
879 (metric_derivative[orbital_matrix_element(row, column)] +
881 metric_derivative[orbital_matrix_element(column, row)]));
882 metric_derivative[orbital_matrix_element(row, column)] =
884 metric_derivative[orbital_matrix_element(column, row)] =
885 std::conj(hermitian_value);
889 lowdin_transform, metric_derivative);
891 auto left_orbital_projection_derivative =
892 contract(strained_atomic_orbitals.data(),
893 number_of_atomic_orbitals,
894 overlap_applied_wavefunctions.data(),
895 number_of_occupied_bands);
896 auto overlap_projection_derivative =
897 contract(atomic_orbitals.data(),
898 number_of_atomic_orbitals,
899 overlap_derivative_on_wavefunctions.data(),
900 number_of_occupied_bands);
901 std::vector<Complex> raw_projection_derivative(atomic_band_overlaps.size());
902 for (
size_t overlap_index = 0;
903 overlap_index < raw_projection_derivative.size();
905 raw_projection_derivative[overlap_index] =
906 left_orbital_projection_derivative[overlap_index] +
907 overlap_projection_derivative[overlap_index];
910 std::vector<Complex> projection_derivative(projection.size(),
912 for (
int occupied_band_index = 0;
913 occupied_band_index < number_of_occupied_bands;
914 occupied_band_index++) {
915 for (
int orbital_index = 0; orbital_index < number_of_atomic_orbitals;
917 for (
int inner_orbital_index = 0;
918 inner_orbital_index < number_of_atomic_orbitals;
919 inner_orbital_index++) {
920 projection_derivative[orbital_matrix_element(
921 orbital_index, occupied_band_index)] +=
922 inverse_square_root_derivative[orbital_matrix_element(
923 orbital_index, inner_orbital_index)] *
924 atomic_band_overlaps[orbital_matrix_element(
925 inner_orbital_index, occupied_band_index)] +
926 lowdin_transform.inverse_square_root[orbital_matrix_element(
927 orbital_index, inner_orbital_index)] *
928 raw_projection_derivative[orbital_matrix_element(
929 inner_orbital_index, occupied_band_index)];
934 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds;
936 const auto& manifold = manifolds[manifold_index];
937 int manifold_size =
static_cast<int>(manifold.orbital_indices.size());
938 int row_offset = manifold_row_offsets[manifold_index];
939 Matrix<Complex> manifold_overlaps(
static_cast<size_t>(number_of_bands),
940 static_cast<size_t>(manifold_size));
941 Matrix<Complex> derivative_overlaps(
942 static_cast<size_t>(number_of_bands),
943 static_cast<size_t>(manifold_size));
944 for (
int orbital_within_manifold = 0;
945 orbital_within_manifold < manifold_size;
946 orbital_within_manifold++) {
947 int orbital_index = manifold.orbital_indices[
static_cast<size_t>(
948 orbital_within_manifold)];
949 for (
int occupied_band_index = 0;
950 occupied_band_index < number_of_occupied_bands;
951 occupied_band_index++) {
952 size_t band_row =
static_cast<size_t>(
953 occupied_band_indices[
static_cast<size_t>(
954 occupied_band_index)]);
956 band_row,
static_cast<size_t>(orbital_within_manifold)) =
957 projection[orbital_matrix_element(orbital_index,
958 occupied_band_index)];
960 band_row,
static_cast<size_t>(orbital_within_manifold)) =
961 projection_derivative[orbital_matrix_element(
962 orbital_index, occupied_band_index)];
966 const auto& combined_d_matrix =
968 std::vector<Complex> manifold_d_matrix(
969 static_cast<size_t>(manifold_size) * manifold_size);
970 for (
int row = 0; row < manifold_size; row++) {
971 for (
int column = 0; column < manifold_size; column++) {
972 manifold_d_matrix[
static_cast<size_t>(row * manifold_size +
974 combined_d_matrix[
static_cast<size_t>(row_offset + row) +
975 static_cast<size_t>(row_offset + column) *
976 total_hubbard_orbitals];
980 result_.
hubbard[direction_a][direction_b] -=
981 inverse_cell_volume *
995 auto overlap_matrix = contract(atomic_orbitals.data(),
996 number_of_atomic_orbitals,
997 atomic_orbitals.data(),
998 number_of_atomic_orbitals);
999 auto lowdin_transform =
1001 auto atomic_band_overlaps = contract(atomic_orbitals.data(),
1002 number_of_atomic_orbitals,
1003 wavefunctions.data(),
1004 number_of_occupied_bands);
1006 std::vector<Complex> projection(
static_cast<size_t>(number_of_atomic_orbitals) *
1007 number_of_occupied_bands,
1009 for (
int occupied_band_index = 0; occupied_band_index < number_of_occupied_bands;
1010 occupied_band_index++)
1011 for (
int orbital_index = 0; orbital_index < number_of_atomic_orbitals;
1013 for (
int inner_orbital_index = 0;
1014 inner_orbital_index < number_of_atomic_orbitals;
1015 inner_orbital_index++)
1016 projection[orbital_matrix_element(orbital_index, occupied_band_index)] +=
1017 lowdin_transform.inverse_square_root[orbital_matrix_element(
1018 orbital_index, inner_orbital_index)] *
1019 atomic_band_overlaps[orbital_matrix_element(inner_orbital_index,
1020 occupied_band_index)];
1022 std::vector<Complex> strained_atomic_orbitals(atomic_orbitals.size());
1023 for (
int direction_a = 0; direction_a < 3; direction_a++) {
1024 for (
int direction_b = 0; direction_b < 3; direction_b++) {
1025 apply_strain_derivative(number_of_plane_waves,
1026 number_of_atomic_orbitals,
1031 atomic_orbital_radial_derivative,
1032 atomic_orbital_angular_derivative[direction_a],
1033 strained_atomic_orbitals);
1035 auto atomic_band_derivative = contract(strained_atomic_orbitals.data(),
1036 number_of_atomic_orbitals,
1037 wavefunctions.data(),
1038 number_of_occupied_bands);
1039 auto left_overlap_derivative = contract(strained_atomic_orbitals.data(),
1040 number_of_atomic_orbitals,
1041 atomic_orbitals.data(),
1042 number_of_atomic_orbitals);
1043 std::vector<Complex> overlap_derivative(
1044 static_cast<size_t>(number_of_atomic_orbitals) * number_of_atomic_orbitals);
1045 for (
int column = 0; column < number_of_atomic_orbitals; column++)
1046 for (
int row = 0; row < number_of_atomic_orbitals; row++)
1047 overlap_derivative[orbital_matrix_element(row, column)] =
1048 left_overlap_derivative[orbital_matrix_element(row, column)] +
1050 left_overlap_derivative[orbital_matrix_element(column, row)]);
1052 auto inverse_square_root_derivative =
1054 std::vector<Complex> projection_derivative(
1055 static_cast<size_t>(number_of_atomic_orbitals) * number_of_occupied_bands,
1057 for (
int occupied_band_index = 0;
1058 occupied_band_index < number_of_occupied_bands;
1059 occupied_band_index++)
1060 for (
int orbital_index = 0; orbital_index < number_of_atomic_orbitals;
1062 for (
int inner_orbital_index = 0;
1063 inner_orbital_index < number_of_atomic_orbitals;
1064 inner_orbital_index++)
1065 projection_derivative[orbital_matrix_element(
1066 orbital_index, occupied_band_index)] +=
1067 inverse_square_root_derivative[orbital_matrix_element(
1068 orbital_index, inner_orbital_index)] *
1069 atomic_band_overlaps[orbital_matrix_element(
1070 inner_orbital_index, occupied_band_index)] +
1071 lowdin_transform.inverse_square_root[orbital_matrix_element(
1072 orbital_index, inner_orbital_index)] *
1073 atomic_band_derivative[orbital_matrix_element(
1074 inner_orbital_index, occupied_band_index)];
1076 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds;
1078 const auto& manifold = manifolds[manifold_index];
1079 int manifold_size =
static_cast<int>(manifold.orbital_indices.size());
1080 int row_offset = manifold_row_offsets[manifold_index];
1081 Matrix<Complex> manifold_overlaps(
static_cast<size_t>(number_of_bands),
1082 static_cast<size_t>(manifold_size));
1083 Matrix<Complex> derivative_overlaps(
static_cast<size_t>(number_of_bands),
1084 static_cast<size_t>(manifold_size));
1085 for (
int orbital_within_manifold = 0;
1086 orbital_within_manifold < manifold_size;
1087 orbital_within_manifold++) {
1090 .orbital_indices[
static_cast<size_t>(orbital_within_manifold)];
1091 for (
int occupied_band_index = 0;
1092 occupied_band_index < number_of_occupied_bands;
1093 occupied_band_index++) {
1095 static_cast<size_t>(occupied_band_indices[
static_cast<size_t>(
1096 occupied_band_index)]);
1097 manifold_overlaps(band_row,
1098 static_cast<size_t>(orbital_within_manifold)) =
1099 projection[orbital_matrix_element(orbital_index,
1100 occupied_band_index)];
1101 derivative_overlaps(band_row,
1102 static_cast<size_t>(orbital_within_manifold)) =
1103 projection_derivative[orbital_matrix_element(
1104 orbital_index, occupied_band_index)];
1108 const auto& combined_d_matrix =
1110 std::vector<Complex> manifold_d_matrix(
static_cast<size_t>(manifold_size) *
1112 for (
int row = 0; row < manifold_size; row++)
1113 for (
int column = 0; column < manifold_size; column++)
1114 manifold_d_matrix[
static_cast<size_t>(row * manifold_size +
1116 combined_d_matrix[
static_cast<size_t>(row_offset + row) +
1117 static_cast<size_t>(row_offset + column) *
1118 total_hubbard_orbitals];
1120 result_.
hubbard[direction_a][direction_b] -=
1121 inverse_cell_volume *
1125 derivative_overlaps,
1134 symmetrize_stress_tensor(result_.
hubbard);
1144 [[nodiscard]] std::vector<AtomicOrbitalDescriptor>
1145 enumerate_atomic_orbital_descriptors()
const {
1146 const auto& pseudopotential_set =
1148 std::vector<AtomicOrbitalDescriptor> descriptors;
1149 for (
int atom_index = 0; atom_index < crystal_structure_.
number_of_atoms(); atom_index++) {
1151 const auto& pseudopotential = pseudopotential_set[species_type_index];
1152 for (
int wavefunction_index = 0;
1153 wavefunction_index < static_cast<int>(pseudopotential.wavefunctions_atomic.size());
1154 wavefunction_index++) {
1155 const auto& atomic_wavefunction =
1156 pseudopotential.wavefunctions_atomic[
static_cast<size_t>(wavefunction_index)];
1157 if (atomic_wavefunction.occupations < 0.0)
1159 int angular_momentum = atomic_wavefunction.angular_momentum;
1160 for (
int magnetic_index = 0; magnetic_index < 2 * angular_momentum + 1;
1162 descriptors.push_back({
static_cast<int>(descriptors.size()),
1167 angular_momentum * angular_momentum + magnetic_index});
1181 [[nodiscard]] PlaneWaveGeometry
1182 build_plane_wave_geometry(
const Vector3D& kpoint_cartesian,
1183 const std::vector<int>& plane_wave_indices,
1184 int number_of_plane_waves)
const {
1185 const auto& basis = scf_state_.quantum_system().pseudopotential_basis();
1186 const auto& pseudopotential_set = basis.pseudopotential_set();
1187 Real two_pi_over_lattice_parameter = crystal_structure_.two_pi_over_lattice_parameter();
1189 PlaneWaveGeometry geometry;
1190 geometry.reciprocal_units.resize(number_of_plane_waves);
1191 geometry.magnitude_squared_reciprocal_units.resize(number_of_plane_waves);
1192 geometry.cartesian.resize(number_of_plane_waves);
1193 geometry.magnitude_bohr.resize(number_of_plane_waves);
1194 geometry.inverse_magnitude_bohr.resize(number_of_plane_waves);
1196 for (
int g_index = 0; g_index < number_of_plane_waves; g_index++) {
1197 const auto& g_vector =
1198 planewave_basis_.g_vectors()[plane_wave_indices[
static_cast<size_t>(g_index)]];
1199 std::array<Real, 3> k_plus_g = {kpoint_cartesian.x + g_vector.g_cart.x,
1200 kpoint_cartesian.y + g_vector.g_cart.y,
1201 kpoint_cartesian.z + g_vector.g_cart.z};
1202 geometry.reciprocal_units[g_index] = k_plus_g;
1203 Real magnitude_squared =
1204 k_plus_g[0] * k_plus_g[0] + k_plus_g[1] * k_plus_g[1] + k_plus_g[2] * k_plus_g[2];
1205 geometry.magnitude_squared_reciprocal_units[g_index] = magnitude_squared;
1206 for (
int direction = 0; direction < 3; direction++)
1207 geometry.cartesian[g_index][direction] =
1208 k_plus_g[direction] * two_pi_over_lattice_parameter;
1209 Real magnitude_bohr = std::sqrt(magnitude_squared) * two_pi_over_lattice_parameter;
1210 geometry.magnitude_bohr[g_index] = magnitude_bohr;
1211 geometry.inverse_magnitude_bohr[g_index] =
1213 ? 1.0 / magnitude_bohr
1217 int maximum_angular_momentum = 0;
1218 for (
int species_index = 0; species_index < static_cast<int>(pseudopotential_set.size());
1220 for (
const auto& atomic_wavefunction :
1221 pseudopotential_set[species_index].wavefunctions_atomic)
1222 if (atomic_wavefunction.occupations >= 0.0)
1223 maximum_angular_momentum =
1224 std::max(maximum_angular_momentum, atomic_wavefunction.angular_momentum);
1225 for (
const auto& projector : pseudopotential_set[species_index].projectors)
1226 maximum_angular_momentum =
1227 std::max(maximum_angular_momentum, projector.angular_momentum);
1229 int number_of_lm_components =
1230 (maximum_angular_momentum + 1) * (maximum_angular_momentum + 1);
1233 number_of_plane_waves,
1234 geometry.reciprocal_units,
1235 geometry.magnitude_squared_reciprocal_units,
1236 geometry.spherical_harmonics);
1237 for (
int direction = 0; direction < 3; direction++)
1239 number_of_lm_components,
1240 number_of_plane_waves,
1241 geometry.reciprocal_units,
1242 geometry.magnitude_squared_reciprocal_units,
1244 geometry.spherical_harmonic_derivatives[
static_cast<size_t>(direction)]);
1246 geometry.structure_factors.resize(
1247 static_cast<size_t>(crystal_structure_.number_of_atoms()));
1248 for (
int atom_index = 0; atom_index < crystal_structure_.number_of_atoms(); atom_index++) {
1249 Vector3D atomic_position =
1250 crystal_structure_.convert_from_crystal_to_cartesian(atom_index);
1251 auto& factors = geometry.structure_factors[
static_cast<size_t>(atom_index)];
1252 factors.resize(number_of_plane_waves);
1253 for (
int g_index = 0; g_index < number_of_plane_waves; g_index++) {
1254 const auto& k_plus_g = geometry.reciprocal_units[g_index];
1256 (k_plus_g[0] * atomic_position.x + k_plus_g[1] * atomic_position.y +
1257 k_plus_g[2] * atomic_position.z);
1274 void build_atomic_orbital_strain_parts(
1276 const std::vector<int>& plane_wave_indices,
1277 int number_of_plane_waves,
1278 const PlaneWaveGeometry& geometry,
1279 const std::vector<AtomicOrbitalDescriptor>& hubbard_descriptors,
1280 const std::vector<std::vector<std::vector<Real>>>& atomic_wavefunction_table,
1282 int number_of_q_points,
1283 std::vector<Complex>& orbitals,
1284 std::vector<Complex>& radial_derivative,
1285 std::array<std::vector<Complex>, 3>& angular_derivative)
const {
1286 const auto& pseudopotential_set =
1287 scf_state_.quantum_system().pseudopotential_basis().pseudopotential_set();
1288 int total_hubbard_orbitals =
static_cast<int>(hubbard_descriptors.size());
1289 Real two_pi_over_lattice_parameter = crystal_structure_.two_pi_over_lattice_parameter();
1291 std::vector<std::vector<Complex>> all_atomic_orbitals;
1293 number_of_plane_waves,
1298 pseudopotential_set,
1299 atomic_wavefunction_table,
1302 all_atomic_orbitals);
1304 size_t block =
static_cast<size_t>(number_of_plane_waves) * total_hubbard_orbitals;
1305 orbitals.assign(block,
Complex(0.0, 0.0));
1307 for (
int direction = 0; direction < 3; direction++)
1308 angular_derivative[
static_cast<size_t>(direction)].assign(block,
Complex(0.0, 0.0));
1310 for (
int packed = 0; packed < total_hubbard_orbitals; packed++) {
1311 const auto& descriptor = hubbard_descriptors[
static_cast<size_t>(packed)];
1312 int global_orbital = descriptor.global_orbital_index;
1325 const auto& structure_factor =
1326 geometry.structure_factors[
static_cast<size_t>(descriptor.atom_index)];
1327 const auto& radial_table =
1328 atomic_wavefunction_table[
static_cast<size_t>(descriptor.species_type_index)]
1329 [
static_cast<size_t>(descriptor.wavefunction_index)];
1330 size_t column =
static_cast<size_t>(packed) * number_of_plane_waves;
1332 for (
int g_index = 0; g_index < number_of_plane_waves; g_index++) {
1333 orbitals[column + g_index] =
1334 all_atomic_orbitals[
static_cast<size_t>(global_orbital)]
1335 [
static_cast<size_t>(g_index)];
1337 Real magnitude = geometry.magnitude_bohr[g_index];
1339 radial_table, magnitude, q_spacing, number_of_q_points);
1341 radial_table, magnitude, q_spacing, number_of_q_points);
1343 geometry.spherical_harmonics[
static_cast<size_t>(g_index)]
1344 [
static_cast<size_t>(descriptor.combined_lm_index)];
1345 Complex common = structure_factor[
static_cast<size_t>(g_index)] * angular_phase;
1348 for (
int direction = 0; direction < 3; direction++) {
1349 Real harmonic_slope =
1350 geometry.spherical_harmonic_derivatives[
static_cast<size_t>(direction)]
1351 [
static_cast<size_t>(g_index)]
1352 [
static_cast<size_t>(
1353 descriptor.combined_lm_index)];
1354 angular_derivative[
static_cast<size_t>(direction)][column + g_index] =
1355 (radial_value / two_pi_over_lattice_parameter) * harmonic_slope * common;
1373 void build_beta_strain_parts(
int kpoint_index,
1374 const std::vector<int>& plane_wave_indices,
1375 int number_of_plane_waves,
1376 int total_projectors,
1377 const PlaneWaveGeometry& geometry,
1378 std::vector<Complex>& beta_projectors,
1379 std::vector<Complex>& radial_derivative,
1380 std::array<std::vector<Complex>, 3>& angular_derivative)
const {
1381 size_t block =
static_cast<size_t>(number_of_plane_waves) * total_projectors;
1382 beta_projectors.assign(block,
Complex(0.0, 0.0));
1384 for (
int direction = 0; direction < 3; direction++)
1385 angular_derivative[
static_cast<size_t>(direction)].assign(block,
Complex(0.0, 0.0));
1386 if (total_projectors == 0)
1389 const auto& basis = scf_state_.quantum_system().pseudopotential_basis();
1390 Matrix<Complex> canonical_projectors;
1394 basis.pseudopotential_set(),
1395 basis.beta_function_table(),
1397 number_of_plane_waves,
1399 canonical_projectors);
1400 for (
int projector = 0; projector < total_projectors; projector++)
1401 for (
int g_index = 0; g_index < number_of_plane_waves; g_index++)
1402 beta_projectors[
static_cast<size_t>(projector) * number_of_plane_waves + g_index] =
1403 canonical_projectors[projector][g_index];
1405 Real inverse_sqrt_cell_volume = 1.0 / std::sqrt(crystal_structure_.cell_volume());
1406 Real two_pi_over_lattice_parameter = crystal_structure_.two_pi_over_lattice_parameter();
1408 int projector_index = 0;
1409 for (
int atom_index = 0; atom_index < crystal_structure_.number_of_atoms(); atom_index++) {
1410 int species_type_index = crystal_structure_.species_type_index(atom_index);
1411 const auto& structure_factor =
1412 geometry.structure_factors[
static_cast<size_t>(atom_index)];
1413 for (
int beta_index = 0; beta_index < basis.number_of_projectors(species_type_index);
1415 int angular_momentum = basis.beta_angular_momentum(species_type_index, beta_index);
1417 Complex prefactor = inverse_sqrt_cell_volume * angular_phase;
1422 size_t column =
static_cast<size_t>(projector_index) * number_of_plane_waves;
1423 for (
int g_index = 0; g_index < number_of_plane_waves; g_index++) {
1424 Real magnitude = geometry.magnitude_bohr[g_index];
1426 basis.interpolate_beta(species_type_index, beta_index, magnitude);
1428 basis.interpolate_dbeta(species_type_index, beta_index, magnitude);
1429 Real harmonic = geometry.spherical_harmonics[
static_cast<size_t>(g_index)]
1430 [
static_cast<size_t>(lm_index)];
1431 Complex common = structure_factor[
static_cast<size_t>(g_index)] * prefactor;
1434 for (
int direction = 0; direction < 3; direction++) {
1435 Real harmonic_slope =
1437 .spherical_harmonic_derivatives[
static_cast<size_t>(direction)]
1438 [
static_cast<size_t>(g_index)]
1439 [
static_cast<size_t>(lm_index)];
1440 angular_derivative[
static_cast<size_t>(direction)][column + g_index] =
1441 (beta_value / two_pi_over_lattice_parameter) * harmonic_slope *
1459 static void apply_strain_derivative(
int number_of_plane_waves,
1460 int number_of_functions,
1461 const PlaneWaveGeometry& geometry,
1464 const std::vector<Complex>& base,
1465 const std::vector<Complex>& radial,
1466 const std::vector<Complex>& angular,
1467 std::vector<Complex>& strained) {
1468 strained.assign(base.size(),
Complex(0.0, 0.0));
1469 Real diagonal = (direction_a == direction_b) ? 0.5 : 0.0;
1470 for (
int function_index = 0; function_index < number_of_functions; function_index++) {
1471 size_t column =
static_cast<size_t>(function_index) * number_of_plane_waves;
1472 for (
int g_index = 0; g_index < number_of_plane_waves; g_index++) {
1473 Real component_a = geometry.cartesian[g_index][
static_cast<size_t>(direction_a)];
1474 Real component_b = geometry.cartesian[g_index][
static_cast<size_t>(direction_b)];
1475 Real radial_weight =
1476 component_a * component_b * geometry.inverse_magnitude_bohr[g_index];
1477 strained[column + g_index] = -(radial[column + g_index] * radial_weight +
1478 angular[column + g_index] * component_b) -
1479 diagonal * base[column + g_index];
1489 template <
typename AugmentationCharge,
1490 typename OrbitalProjectorIndex,
1491 typename ProjectorBandIndex,
1492 typename OrbitalBandIndex>
1493 static void accumulate_augmentation(
int number_of_atoms,
1494 const std::vector<int>& channels_by_atom,
1495 const std::vector<int>& projector_offset_by_atom,
1496 const AugmentationCharge& augmentation_charge,
1497 int total_hubbard_orbitals,
1498 int number_of_bands,
1499 const std::vector<Complex>& left,
1500 const std::vector<Complex>& right,
1501 const OrbitalProjectorIndex& orbital_projector,
1502 const ProjectorBandIndex& projector_band,
1503 const OrbitalBandIndex& orbital_band,
1504 std::vector<Complex>& target) {
1505 for (
int atom_index = 0; atom_index < number_of_atoms; atom_index++) {
1506 int offset = projector_offset_by_atom[
static_cast<size_t>(atom_index)];
1507 int number_of_channels = channels_by_atom[
static_cast<size_t>(atom_index)];
1508 for (
int channel_i = 0; channel_i < number_of_channels; channel_i++) {
1509 for (
int channel_j = 0; channel_j < number_of_channels; channel_j++) {
1510 Real q_value = augmentation_charge(atom_index, channel_i, channel_j);
1513 int projector_i = offset + channel_i;
1514 int projector_j = offset + channel_j;
1515 for (
int orbital = 0; orbital < total_hubbard_orbitals; orbital++) {
1516 Complex left_value = left[orbital_projector(orbital, projector_i)];
1517 if (left_value ==
Complex(0.0, 0.0))
1519 for (
int band = 0; band < number_of_bands; band++)
1520 target[orbital_band(orbital, band)] +=
1521 q_value * left_value * right[projector_band(projector_j, band)];
1537 static void complete_gamma_only_overlaps(
int number_of_plane_waves,
1539 int number_of_right,
1543 std::vector<Complex>& overlaps) {
1544 for (
int left_index = 0; left_index < number_of_left; left_index++) {
1545 for (
int right_index = 0; right_index < number_of_right; right_index++) {
1546 Real g_zero_product =
1548 ? (std::conj(left[
static_cast<size_t>(left_index) * number_of_plane_waves +
1550 right[
static_cast<size_t>(right_index) * number_of_plane_waves +
1554 size_t flat_index =
static_cast<size_t>(left_index) +
1555 static_cast<size_t>(right_index) * number_of_left;
1556 overlaps[flat_index] =
1569 static void symmetrize_stress_tensor(
Real stress[3][3]) {
1570 for (
int direction_a = 0; direction_a < 3; direction_a++) {
1571 for (
int direction_b = direction_a + 1; direction_b < 3; direction_b++) {
1573 0.5 * (stress[direction_a][direction_b] + stress[direction_b][direction_a]);
1574 stress[direction_a][direction_b] = average;
1575 stress[direction_b][direction_a] = average;
1580 const Crystal& crystal_structure_;
1581 const PlanewaveBasis& planewave_basis_;
1582 const KPointsGrid& kpoint_grid_;
1583 const NormConservingPlanewaveKohnShamSCFState& scf_state_;
1584 StressTensorContributions& result_;