482 int number_of_plane_waves,
484 const std::vector<int>& g_vector_indices,
485 const std::vector<Real>& kinetic_energy_squared,
486 const std::vector<Real>& real_space_potential,
487 const Crystal& crystal_structure,
493 ensure_hamiltonian_applicator_initialized(
494 crystal_structure, planewave_basis, kpoint_grid, pseudopotential_quantum_system);
496 auto& applicator = get_hamiltonian_applicator();
497 auto& subspace = get_subspace_manager();
510 applicator.set_spin_channel(spin_channel);
513 if (!applicator.is_smooth_potential_cache_valid()) {
514 applicator.update_potential(real_space_potential);
518 applicator.prepare_kpoint(
519 kpoint_index, number_of_plane_waves, g_vector_indices, kinetic_energy_squared);
522 bool is_gamma_only = applicator.is_gamma_only_current();
527 subspace.set_gamma_origin_is_local(applicator.gamma_origin_is_local_current());
532 if (applicator.get_cached_projectors(kpoint_index) !=
nullptr) {
533 kleinman_bylander_potential_ptr = applicator.get_cached_projectors(kpoint_index);
535 Vector3D kpoint_coordinates = kpoint_grid[kpoint_index].coordinates;
543 number_of_plane_waves,
545 computed_projectors);
546 kleinman_bylander_potential_ptr = &computed_projectors;
548 const auto& kleinman_bylander_potential = *kleinman_bylander_potential_ptr;
551 pseudopotential_quantum_system,
552 kleinman_bylander_potential,
554 bool is_identity_overlap = overlap_operator->is_identity();
556 int global_number_of_plane_waves =
558 int maximum_basis_size =
559 std::max(std::min(davidson_basis_expansion_factor * number_of_bands,
560 global_number_of_plane_waves),
564 if (workspace_ ==
nullptr) {
565 if (gpu_device_backend_ !=
nullptr) {
566 workspace_ = std::make_unique<GPUDavidsonWorkspace>(gpu_device_backend_);
568 workspace_ = std::make_unique<SerialDavidsonWorkspace>();
572 maximum_basis_size, number_of_plane_waves, number_of_bands, is_identity_overlap);
573 log_davidson_memory(
"after workspace resize", maximum_basis_size, number_of_plane_waves);
576 auto timer_seed_start = std::chrono::high_resolution_clock::now();
577 int basis_size = seed_basis_from_wavefunctions(number_of_plane_waves,
582 overlap_operator.get(),
585 workspace_->basis_vectors(),
586 workspace_->hamiltonian_basis_vectors(),
587 workspace_->overlap_basis_vectors());
588 auto timer_seed_end = std::chrono::high_resolution_clock::now();
590 std::chrono::duration<double, std::milli>(timer_seed_end - timer_seed_start).count();
593 if (basis_size < number_of_bands) {
594 basis_size = seed_basis_from_kinetic_energy(basis_size,
595 number_of_plane_waves,
597 kinetic_energy_squared,
599 overlap_operator.get(),
602 workspace_->basis_vectors(),
603 workspace_->hamiltonian_basis_vectors(),
604 workspace_->overlap_basis_vectors());
608 synchronize_basis_across_bands(0,
610 number_of_plane_waves,
611 workspace_->basis_vectors(),
612 workspace_->hamiltonian_basis_vectors(),
613 workspace_->overlap_basis_vectors());
616 subspace.update_subspace_matrices(0,
620 number_of_plane_waves,
622 workspace_->basis_vectors(),
623 workspace_->hamiltonian_basis_vectors(),
624 workspace_->overlap_basis_vectors(),
625 workspace_->subspace_hamiltonian(),
626 workspace_->subspace_overlap());
629 std::vector<Real> previous_eigenvalues(number_of_bands, 0.0);
630 bool has_stored_eigenvalues =
false;
631 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
632 Real stored = quantum_system.
eigenvalue(kpoint_index_state, band_index);
634 has_stored_eigenvalues =
true;
638 if (has_stored_eigenvalues) {
639 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
640 previous_eigenvalues[band_index] =
641 quantum_system.
eigenvalue(kpoint_index_state, band_index);
644 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
645 previous_eigenvalues[band_index] =
646 workspace_->subspace_hamiltonian()[band_index * maximum_basis_size + band_index]
652 number_of_unconverged_bands_ = number_of_bands;
653 for (
int iteration = 0; iteration < max_iterations_; iteration++) {
655 auto timer_diag_start = std::chrono::high_resolution_clock::now();
656 std::vector<Complex> eigenvector_matrix(maximum_basis_size * maximum_basis_size);
657 int diagonalization_info =
658 subspace.diagonalize_subspace(basis_size,
661 workspace_->subspace_hamiltonian(),
662 workspace_->subspace_overlap(),
663 workspace_->local_eigenvalues(),
664 eigenvector_matrix.data());
666 synchronize_eigenpairs_across_bands(basis_size,
668 workspace_->local_eigenvalues(),
669 eigenvector_matrix.data());
670 auto timer_diag_end = std::chrono::high_resolution_clock::now();
672 std::chrono::duration<double, std::milli>(timer_diag_end - timer_diag_start)
676 if (diagonalization_info != 0 && basis_size > number_of_bands) {
677 log::warn(
" Davidson: zhegv failed (info={}), forcing subspace collapse",
678 diagonalization_info);
679 auto timer_collapse_start = std::chrono::high_resolution_clock::now();
680 basis_size = subspace.collapse_subspace(basis_size,
681 number_of_plane_waves,
686 overlap_operator.get(),
689 workspace_->basis_vectors(),
690 workspace_->hamiltonian_basis_vectors(),
691 workspace_->overlap_basis_vectors(),
692 workspace_->band_scratch());
700 std::memset(workspace_->subspace_hamiltonian(),
702 maximum_basis_size * maximum_basis_size *
sizeof(
Complex));
703 std::memset(workspace_->subspace_overlap(),
705 maximum_basis_size * maximum_basis_size *
sizeof(
Complex));
706 subspace.update_subspace_matrices(0,
710 number_of_plane_waves,
712 workspace_->basis_vectors(),
713 workspace_->hamiltonian_basis_vectors(),
714 workspace_->overlap_basis_vectors(),
715 workspace_->subspace_hamiltonian(),
716 workspace_->subspace_overlap());
717 auto timer_collapse_end = std::chrono::high_resolution_clock::now();
719 std::chrono::duration<double, std::milli>(timer_collapse_end -
720 timer_collapse_start)
722 log_davidson_memory(
"after collapse", maximum_basis_size, number_of_plane_waves);
723 diagonalization_info =
724 subspace.diagonalize_subspace(basis_size,
727 workspace_->subspace_hamiltonian(),
728 workspace_->subspace_overlap(),
729 workspace_->local_eigenvalues(),
730 eigenvector_matrix.data());
732 synchronize_eigenpairs_across_bands(basis_size,
734 workspace_->local_eigenvalues(),
735 eigenvector_matrix.data());
736 if (diagonalization_info != 0) {
737 log::warn(
" Davidson: zhegv still failed after collapse (info={}), "
738 "using previous eigenvalues",
739 diagonalization_info);
740 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
741 workspace_->local_eigenvalues()[band_index] =
742 previous_eigenvalues[band_index];
747 bool converged =
true;
755 auto timer_ritz_start = std::chrono::high_resolution_clock::now();
756 std::vector<bool> band_converged(number_of_bands,
true);
757 auto timer_ritz_end = std::chrono::high_resolution_clock::now();
759 std::chrono::duration<double, std::milli>(timer_ritz_end - timer_ritz_start)
762 auto timer_residual_start = std::chrono::high_resolution_clock::now();
763 bool skip_convergence_check = (iteration == 0);
766 Real empty_band_tolerance =
770 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
771 Real eigenvalue_change = std::abs(workspace_->local_eigenvalues()[band_index] -
772 previous_eigenvalues[band_index]);
773 Real band_tolerance =
774 (band_index < number_of_occupied_bands) ? tolerance_ : empty_band_tolerance;
775 bool this_band_converged =
776 (!skip_convergence_check && eigenvalue_change < band_tolerance);
778 if (this_band_converged) {
783 band_converged[band_index] =
false;
786 int number_unconverged = 0;
787 Real max_eigenvalue_change = 0.0;
788 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
789 if (!band_converged[band_index])
790 number_unconverged++;
791 Real change = std::abs(workspace_->local_eigenvalues()[band_index] -
792 previous_eigenvalues[band_index]);
793 max_eigenvalue_change = std::max(max_eigenvalue_change, change);
795 number_of_unconverged_bands_ = number_unconverged;
796 log::debug(
" Davidson iter {}: basis={} unconv={}/{} tol={:.2e} max_de={:.4e}",
802 max_eigenvalue_change);
805 auto timer_residual_end = std::chrono::high_resolution_clock::now();
807 std::chrono::duration<double, std::milli>(timer_residual_end -
808 timer_residual_start)
810 subspace.extract_eigenvectors(basis_size,
811 number_of_plane_waves,
815 eigenvector_matrix.data(),
816 workspace_->basis_vectors(),
817 workspace_->local_eigenvalues(),
818 workspace_->band_scratch(),
828 gpu_workspace->sync_to_device();
831 auto timer_residual_end = std::chrono::high_resolution_clock::now();
833 std::chrono::duration<double, std::milli>(timer_residual_end - timer_residual_start)
836 auto timer_ortho_start = std::chrono::high_resolution_clock::now();
837 int start_new_vectors = new_vectors;
838 workspace_->sync_to_host();
844 int number_of_candidates = subspace.build_correction_vectors(
846 number_of_plane_waves,
848 maximum_basis_size - (basis_size + new_vectors),
850 eigenvector_matrix.data(),
852 workspace_->local_eigenvalues(),
854 kinetic_energy_squared.data(),
855 workspace_->hamiltonian_basis_vectors(),
856 workspace_->overlap_basis_vectors(),
857 workspace_->basis_vectors() +
858 static_cast<std::size_t
>(basis_size + new_vectors) * number_of_plane_waves);
860 int accepted_candidates =
861 subspace.orthogonalize_batch(basis_size + new_vectors,
862 number_of_candidates,
863 number_of_plane_waves,
865 overlap_operator.get(),
866 workspace_->basis_vectors(),
867 workspace_->overlap_basis_vectors());
870 synchronize_basis_across_bands(basis_size + new_vectors,
872 number_of_plane_waves,
873 workspace_->basis_vectors(),
875 workspace_->overlap_basis_vectors());
876 new_vectors += accepted_candidates;
877 int added_vectors = new_vectors - start_new_vectors;
878 auto timer_ortho_end = std::chrono::high_resolution_clock::now();
880 std::chrono::duration<double, std::milli>(timer_ortho_end - timer_ortho_start)
883 if (added_vectors > 0) {
884 auto timer_hpsi_start = std::chrono::high_resolution_clock::now();
885 applicator.apply_batch(
886 workspace_->basis_vectors() + basis_size * number_of_plane_waves,
887 workspace_->hamiltonian_basis_vectors() + basis_size * number_of_plane_waves,
889 auto timer_hpsi_end = std::chrono::high_resolution_clock::now();
891 std::chrono::duration<double, std::milli>(timer_hpsi_end - timer_hpsi_start)
895 int old_basis_size = basis_size;
896 basis_size += new_vectors;
898 if (new_vectors > 0) {
899 auto timer_update_start = std::chrono::high_resolution_clock::now();
900 subspace.update_subspace_matrices(old_basis_size,
904 number_of_plane_waves,
906 workspace_->basis_vectors(),
907 workspace_->hamiltonian_basis_vectors(),
908 workspace_->overlap_basis_vectors(),
909 workspace_->subspace_hamiltonian(),
910 workspace_->subspace_overlap());
911 auto timer_update_end = std::chrono::high_resolution_clock::now();
913 std::chrono::duration<double, std::milli>(timer_update_end - timer_update_start)
918 if (basis_size >= maximum_basis_size) {
919 auto timer_collapse_start = std::chrono::high_resolution_clock::now();
920 basis_size = subspace.collapse_subspace(basis_size,
921 number_of_plane_waves,
926 overlap_operator.get(),
927 workspace_->subspace_hamiltonian(),
928 workspace_->subspace_overlap(),
929 workspace_->basis_vectors(),
930 workspace_->hamiltonian_basis_vectors(),
931 workspace_->overlap_basis_vectors(),
932 workspace_->band_scratch());
940 std::memset(workspace_->subspace_hamiltonian(),
942 maximum_basis_size * maximum_basis_size *
sizeof(
Complex));
943 std::memset(workspace_->subspace_overlap(),
945 maximum_basis_size * maximum_basis_size *
sizeof(
Complex));
946 subspace.update_subspace_matrices(0,
950 number_of_plane_waves,
952 workspace_->basis_vectors(),
953 workspace_->hamiltonian_basis_vectors(),
954 workspace_->overlap_basis_vectors(),
955 workspace_->subspace_hamiltonian(),
956 workspace_->subspace_overlap());
957 auto timer_collapse_end = std::chrono::high_resolution_clock::now();
959 std::chrono::duration<double, std::milli>(timer_collapse_end -
960 timer_collapse_start)
962 log_davidson_memory(
"after collapse", maximum_basis_size, number_of_plane_waves);
965 for (
int band_index = 0; band_index < number_of_bands; band_index++) {
966 previous_eigenvalues[band_index] = workspace_->local_eigenvalues()[band_index];
968 log_davidson_memory(
"at end of iteration", basis_size, number_of_plane_waves);
972 std::vector<Complex> eigenvector_matrix(maximum_basis_size * maximum_basis_size);
973 subspace.diagonalize_subspace(basis_size,
976 workspace_->subspace_hamiltonian(),
977 workspace_->subspace_overlap(),
978 workspace_->local_eigenvalues(),
979 eigenvector_matrix.data());
980 synchronize_eigenpairs_across_bands(basis_size,
982 workspace_->local_eigenvalues(),
983 eigenvector_matrix.data());
984 subspace.extract_eigenvectors(basis_size,
985 number_of_plane_waves,
989 eigenvector_matrix.data(),
990 workspace_->basis_vectors(),
991 workspace_->local_eigenvalues(),
992 workspace_->band_scratch(),