LCOV - code coverage report
Current view: top level - src - qs_scf_diagonalization.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 87.7 % 1394 1222
Test Date: 2026-11-04 00:58:17 Functions: 100.0 % 32 32

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Different diagonalization schemes that can be used
      10              : !>        for the iterative solution of the eigenvalue problem
      11              : !> \par History
      12              : !>      started from routines previously located in the qs_scf module
      13              : !>      05.2009
      14              : ! **************************************************************************************************
      15              : MODULE qs_scf_diagonalization
      16              :    USE cp_array_utils,                  ONLY: cp_1d_r_p_type
      17              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      18              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_column_scale,&
      19              :                                               cp_cfm_scale_and_add,&
      20              :                                               cp_cfm_scale_and_add_fm,&
      21              :                                               cp_cfm_transpose,&
      22              :                                               cp_cfm_triangular_multiply
      23              :    USE cp_cfm_cholesky,                 ONLY: cp_cfm_cholesky_decompose
      24              :    USE cp_cfm_diag,                     ONLY: cp_cfm_diag_workspace_type,&
      25              :                                               cp_cfm_geeig,&
      26              :                                               cp_cfm_geeig_canon,&
      27              :                                               cp_cfm_geeig_canon_local,&
      28              :                                               cp_cfm_geeig_local,&
      29              :                                               cp_cfm_heevd,&
      30              :                                               cp_cfm_local_workspace_prepare
      31              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      32              :                                               cp_cfm_release,&
      33              :                                               cp_cfm_set_all,&
      34              :                                               cp_cfm_to_cfm,&
      35              :                                               cp_cfm_to_fm,&
      36              :                                               cp_cfm_type,&
      37              :                                               cp_fm_to_cfm
      38              :    USE cp_control_types,                ONLY: dft_control_type,&
      39              :                                               hairy_probes_type
      40              :    USE cp_dbcsr_api,                    ONLY: &
      41              :         dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_init_p, dbcsr_p_type, &
      42              :         dbcsr_release_p, dbcsr_set, dbcsr_type, dbcsr_type_symmetric
      43              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      44              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      45              :                                               copy_fm_to_dbcsr,&
      46              :                                               cp_dbcsr_sm_fm_multiply,&
      47              :                                               dbcsr_allocate_matrix_set
      48              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      49              :                                               cp_fm_scale_and_add,&
      50              :                                               cp_fm_symm,&
      51              :                                               cp_fm_uplo_to_full
      52              :    USE cp_fm_cholesky,                  ONLY: cp_fm_cholesky_reduce,&
      53              :                                               cp_fm_cholesky_restore
      54              :    USE cp_fm_diag,                      ONLY: choose_eigv_solver,&
      55              :                                               cp_fm_geeig,&
      56              :                                               cp_fm_geeig_canon,&
      57              :                                               diag_check_requested,&
      58              :                                               diag_lib_explicit,&
      59              :                                               direct_generalized_diagonalization
      60              :    USE cp_fm_pool_types,                ONLY: cp_fm_pool_type,&
      61              :                                               fm_pool_create_fm,&
      62              :                                               fm_pool_get_el_struct,&
      63              :                                               fm_pool_give_back_fm
      64              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      65              :                                               cp_fm_struct_release,&
      66              :                                               cp_fm_struct_type
      67              :    USE cp_fm_types,                     ONLY: cp_fm_add_to_element,&
      68              :                                               cp_fm_create,&
      69              :                                               cp_fm_get_info,&
      70              :                                               cp_fm_release,&
      71              :                                               cp_fm_to_fm,&
      72              :                                               cp_fm_type
      73              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      74              :                                               cp_logger_get_default_unit_nr,&
      75              :                                               cp_logger_type
      76              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      77              :                                               cp_print_key_unit_nr,&
      78              :                                               debug_print_level
      79              :    USE dft_plus_u,                      ONLY: lowdin_kp_apply
      80              :    USE ieee_arithmetic,                 ONLY: ieee_is_finite
      81              :    USE input_constants,                 ONLY: &
      82              :         cholesky_dbcsr, cholesky_inverse, cholesky_off, cholesky_reduce, cholesky_restore, &
      83              :         core_guess, diag_update_method_adiis, general_roks, high_spin_roks, ot_precond_full_all, &
      84              :         ot_precond_full_kinetic, ot_precond_full_single_inverse, ot_precond_none, &
      85              :         ot_precond_s_inverse, restart_guess
      86              :    USE input_cp2k_kpoints,              ONLY: lattice_fft_auto,&
      87              :                                               lattice_fft_off,&
      88              :                                               lattice_fft_on
      89              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      90              :                                               section_vals_type
      91              :    USE kinds,                           ONLY: dp,&
      92              :                                               int_8
      93              :    USE kpoint_methods,                  ONLY: kpoint_density_matrices,&
      94              :                                               kpoint_density_transform,&
      95              :                                               kpoint_set_mo_occupation,&
      96              :                                               rskp_grid_type,&
      97              :                                               rskp_transform_grid_prepare,&
      98              :                                               rskp_transform_grid_release
      99              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
     100              :                                               kpoint_env_type,&
     101              :                                               kpoint_type
     102              :    USE local_gemm_api,                  ONLY: LOCAL_GEMM_PU_GPU,&
     103              :                                               local_gemm_ctxt_type
     104              :    USE machine,                         ONLY: m_flush,&
     105              :                                               m_walltime
     106              :    USE mathconstants,                   ONLY: z_one,&
     107              :                                               z_zero
     108              :    USE message_passing,                 ONLY: mp_para_env_type
     109              :    USE parallel_gemm_api,               ONLY: parallel_gemm
     110              :    USE preconditioner,                  ONLY: dbcsr_pair_to_cfm,&
     111              :                                               make_preconditioner_complex_full_kinetic,&
     112              :                                               make_preconditioner_complex_full_s_inverse,&
     113              :                                               prepare_preconditioner,&
     114              :                                               restart_preconditioner
     115              :    USE preconditioner_makes,            ONLY: make_complex_full_all,&
     116              :                                               make_complex_full_single_inverse
     117              :    USE preconditioner_types,            ONLY: destroy_preconditioner,&
     118              :                                               init_preconditioner
     119              :    USE qs_density_matrices,             ONLY: calculate_density_matrix
     120              :    USE qs_density_mixing_types,         ONLY: direct_mixing_nr,&
     121              :                                               gspace_mixing_nr
     122              :    USE qs_diis,                         ONLY: qs_diis_b_calc_err_kp,&
     123              :                                               qs_diis_b_check_i_alloc_kp,&
     124              :                                               qs_diis_b_clear,&
     125              :                                               qs_diis_b_clear_kp,&
     126              :                                               qs_diis_b_info_kp,&
     127              :                                               qs_diis_b_step,&
     128              :                                               qs_diis_b_step_kp
     129              :    USE qs_energy_types,                 ONLY: qs_energy_type
     130              :    USE qs_environment_types,            ONLY: get_qs_env,&
     131              :                                               qs_environment_type
     132              :    USE qs_gspace_mixing,                ONLY: gspace_mixing
     133              :    USE qs_kpoint_operators,             ONLY: &
     134              :         kpoint_operator_batch_size, kpoint_operator_context_create, &
     135              :         kpoint_operator_context_release, kpoint_operator_context_type, kpoint_operator_evaluate, &
     136              :         kpoint_operator_evaluate_batch, kpoint_operator_finish, kpoint_operator_get, &
     137              :         kpoint_operator_get_local, kpoint_operator_prepare, kpoint_operator_start, &
     138              :         kpoint_operator_store, kpoint_operator_work_size, kpoint_slot_ks, kpoint_slot_s, &
     139              :         kpoint_slot_t, kpoint_spin_free
     140              :    USE qs_ks_methods,                   ONLY: qs_ks_update_qs_env
     141              :    USE qs_ks_types,                     ONLY: qs_ks_did_change,&
     142              :                                               qs_ks_env_type
     143              :    USE qs_matrix_pools,                 ONLY: mpools_get,&
     144              :                                               qs_matrix_pools_type
     145              :    USE qs_mixing_utils,                 ONLY: charge_mixing_init,&
     146              :                                               mixing_allocate,&
     147              :                                               mixing_init,&
     148              :                                               self_consistency_check
     149              :    USE qs_mo_methods,                   ONLY: calculate_subspace_eigenvalues
     150              :    USE qs_mo_occupation,                ONLY: set_mo_occupation
     151              :    USE qs_mo_types,                     ONLY: get_mo_set,&
     152              :                                               mo_set_type
     153              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
     154              :    USE qs_ot_eigensolver,               ONLY: ot_eigensolver,&
     155              :                                               ot_eigensolver_complex
     156              :    USE qs_rho_atom_types,               ONLY: rho_atom_type
     157              :    USE qs_rho_methods,                  ONLY: qs_rho_update_rho
     158              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
     159              :                                               qs_rho_type
     160              :    USE qs_scf_block_davidson,           ONLY: generate_extended_space,&
     161              :                                               generate_extended_space_c,&
     162              :                                               generate_extended_space_sparse
     163              :    USE qs_scf_lanczos,                  ONLY: lanczos_refinement,&
     164              :                                               lanczos_refinement_2v
     165              :    USE qs_scf_lanczos_c,                ONLY: lanczos_channel_begin,&
     166              :                                               lanczos_channel_end,&
     167              :                                               lanczos_sweep_suffix,&
     168              :                                               lanczos_workspace_create,&
     169              :                                               lanczos_workspace_release,&
     170              :                                               lanczos_workspace_type
     171              :    USE qs_scf_methods,                  ONLY: combine_ks_matrices,&
     172              :                                               eigensolver,&
     173              :                                               eigensolver_dbcsr,&
     174              :                                               eigensolver_generalized,&
     175              :                                               eigensolver_simple,&
     176              :                                               eigensolver_symm,&
     177              :                                               scf_env_density_mixing
     178              :    USE qs_scf_types,                    ONLY: qs_scf_env_type,&
     179              :                                               subspace_env_type
     180              :    USE scf_control_types,               ONLY: scf_control_type
     181              : 
     182              : !$ USE OMP_LIB, ONLY: omp_get_max_threads, &
     183              : !$                    omp_get_thread_num
     184              : #include "./base/base_uses.f90"
     185              : 
     186              :    IMPLICIT NONE
     187              : 
     188              :    PRIVATE
     189              : 
     190              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_diagonalization'
     191              : 
     192              :    ! occupation below this weight sits beyond the thermal smearing tail
     193              :    ! and converges at the relaxed empty threshold. The Davidson k-point
     194              :    ! driver and both Lanczos k-point paths below use this rule
     195              :    REAL(KIND=dp), PARAMETER, PRIVATE :: occ_tol = 1.0E-3_dp
     196              : 
     197              :    TYPE, PRIVATE :: kp_diag_workspace_type
     198              :       TYPE(cp_cfm_type) :: cksmat, cmos, csmat, csmat_base, cwork
     199              :       TYPE(cp_cfm_diag_workspace_type) :: solver
     200              :       TYPE(lanczos_workspace_type) :: lan_ws
     201              :       TYPE(local_gemm_ctxt_type) :: gemm_ctx
     202              :       COMPLEX(KIND=dp), ALLOCATABLE :: phase(:, :)
     203              :    END TYPE kp_diag_workspace_type
     204              : 
     205              :    PUBLIC :: do_general_diag, do_general_diag_kp, do_roks_diag, &
     206              :              do_special_diag, do_ot_diag, do_ot_diag_kp, do_block_davidson_diag, &
     207              :              do_block_davidson_diag_kp, &
     208              :              do_block_krylov_diag, do_block_krylov_diag_kp, do_scf_diag_subspace, diag_subspace_allocate, &
     209              :              general_eigenproblem, diag_kp_smat, diag_kp_basic
     210              : 
     211              : CONTAINS
     212              : 
     213              : ! **************************************************************************************************
     214              : !> \brief Fade candidate regularization through handover; never regularize a raw-map check.
     215              : !> \param scf_env Current SCF state.
     216              : !> \return ...
     217              : ! **************************************************************************************************
     218          206 :    FUNCTION adiis_candidate_shift(scf_env) RESULT(shift)
     219              :       TYPE(qs_scf_env_type), INTENT(IN)                  :: scf_env
     220              :       REAL(KIND=dp)                                      :: shift
     221              : 
     222          206 :       shift = 0.0_dp
     223          206 :       IF (scf_env%iter_count <= 1 .OR. scf_env%adiis_check_next) RETURN
     224          190 :       IF (.NOT. ASSOCIATED(scf_env%scf_subspace_buffer)) RETURN
     225          190 :       shift = scf_env%adiis_shift*(1.0_dp - scf_env%scf_subspace_buffer%diis_weight)
     226          190 :    END FUNCTION adiis_candidate_shift
     227              : 
     228              : ! **************************************************************************************************
     229              : !> \brief Add -shift*S*C*(occupation/maxocc)*C^T*S to a candidate Fock matrix.
     230              : !>        The occupied projector does not require any stored virtual orbitals.
     231              : !> \param fock Candidate matrix; physical F[P] and all history matrices remain unchanged.
     232              : !> \param overlap AO overlap.
     233              : !> \param mos Previous physical orbitals and occupations.
     234              : !> \param shift Nonnegative regularization parameter in hartree.
     235              : ! **************************************************************************************************
     236           84 :    SUBROUTINE shift_candidate_real(fock, overlap, mos, shift)
     237              :       TYPE(cp_fm_type), INTENT(INOUT)                    :: fock
     238              :       TYPE(cp_fm_type), INTENT(IN)                       :: overlap
     239              :       TYPE(mo_set_type), INTENT(IN)                      :: mos
     240              :       REAL(KIND=dp), INTENT(IN)                          :: shift
     241              : 
     242              :       INTEGER                                            :: nao, nmo
     243              :       REAL(KIND=dp)                                      :: maxocc
     244           28 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: occupation
     245              :       TYPE(cp_fm_type)                                   :: sc
     246              :       TYPE(cp_fm_type), POINTER                          :: coeff
     247              : 
     248            0 :       IF (shift == 0.0_dp) RETURN
     249           28 :       CALL get_mo_set(mos, nao=nao, nmo=nmo, maxocc=maxocc, occupation_numbers=occupation, mo_coeff=coeff)
     250           28 :       CALL cp_fm_create(sc, coeff%matrix_struct)
     251           28 :       CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, overlap, coeff, 0.0_dp, sc)
     252          406 :       CALL cp_fm_column_scale(sc, SQRT(MAX(0.0_dp, occupation/maxocc)))
     253           28 :       CALL parallel_gemm("N", "T", nao, nao, nmo, -shift, sc, sc, 1.0_dp, fock)
     254           28 :       CALL cp_fm_release(sc)
     255           28 :    END SUBROUTINE shift_candidate_real
     256              : 
     257              : ! **************************************************************************************************
     258              : !> \brief Complex occupied-space shift, using conjugate transpose and existing eigensolver workspaces.
     259              : !> \param fock Candidate Fock matrix, modified in place.
     260              : !> \param overlap AO overlap, unchanged.
     261              : !> \param mos Previous complex MOs.
     262              : !> \param coeff AO/MO eigensolver workspace.
     263              : !> \param work AO/AO eigensolver workspace.
     264              : !> \param shift Nonnegative regularization parameter in hartree.
     265              : !> \param local Whether the matrices are complete on this rank.
     266              : !> \param gemm_ctx Private local GEMM context, unused for distributed groups.
     267              : ! **************************************************************************************************
     268          158 :    SUBROUTINE shift_candidate_complex(fock, overlap, mos, coeff, work, shift, local, gemm_ctx)
     269              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: fock
     270              :       TYPE(cp_cfm_type), INTENT(IN)                      :: overlap
     271              :       TYPE(mo_set_type), INTENT(IN)                      :: mos
     272              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: coeff, work
     273              :       REAL(KIND=dp), INTENT(IN)                          :: shift
     274              :       LOGICAL, INTENT(IN)                                :: local
     275              :       TYPE(local_gemm_ctxt_type), INTENT(INOUT)          :: gemm_ctx
     276              : 
     277              :       INTEGER                                            :: nao, nmo
     278              :       REAL(KIND=dp)                                      :: maxocc
     279          138 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: occupation
     280              :       TYPE(cp_cfm_type), POINTER                         :: cmos
     281              : 
     282          118 :       IF (shift == 0.0_dp) RETURN
     283           20 :       CALL get_mo_set(mos, nao=nao, nmo=nmo, maxocc=maxocc, occupation_numbers=occupation, cmo_coeff=cmos)
     284           20 :       CALL cp_cfm_to_cfm(cmos, coeff)
     285          320 :       CALL cp_cfm_column_scale(coeff, CMPLX(SQRT(MAX(0.0_dp, occupation/maxocc)), KIND=dp))
     286           20 :       IF (local) THEN
     287           60 :          CPASSERT(PRODUCT(overlap%matrix_struct%context%num_pe) == 1)
     288           60 :          CPASSERT(PRODUCT(coeff%matrix_struct%context%num_pe) == 1)
     289           60 :          CPASSERT(PRODUCT(work%matrix_struct%context%num_pe) == 1)
     290           60 :          CPASSERT(PRODUCT(fock%matrix_struct%context%num_pe) == 1)
     291              :          CALL gemm_ctx%gemm("N", "N", nao, nmo, nao, z_one, &
     292              :                             overlap%local_data, SIZE(overlap%local_data, 1), &
     293              :                             coeff%local_data, SIZE(coeff%local_data, 1), z_zero, &
     294           20 :                             work%local_data, SIZE(work%local_data, 1))
     295              :          CALL gemm_ctx%gemm("N", "C", nao, nao, nmo, CMPLX(-shift, KIND=dp), &
     296              :                             work%local_data, SIZE(work%local_data, 1), &
     297              :                             work%local_data, SIZE(work%local_data, 1), z_one, &
     298           20 :                             fock%local_data, SIZE(fock%local_data, 1))
     299              :       ELSE
     300            0 :          CALL parallel_gemm("N", "N", nao, nmo, nao, z_one, overlap, coeff, z_zero, work)
     301            0 :          CALL parallel_gemm("N", "C", nao, nao, nmo, CMPLX(-shift, KIND=dp), work, work, z_one, fock)
     302              :       END IF
     303          138 :    END SUBROUTINE shift_candidate_complex
     304              : 
     305              : ! **************************************************************************************************
     306              : !> \brief the inner loop of scf, specific to diagonalization with S matrix
     307              : !>       basically, in goes the ks matrix out goes a new p matrix
     308              : !> \param scf_env ...
     309              : !> \param mos ...
     310              : !> \param matrix_ks ...
     311              : !> \param matrix_s ...
     312              : !> \param scf_control ...
     313              : !> \param scf_section ...
     314              : !> \param diis_step ...
     315              : !> \par History
     316              : !>      03.2006 created [Joost VandeVondele]
     317              : ! **************************************************************************************************
     318              : 
     319       103013 :    SUBROUTINE general_eigenproblem(scf_env, mos, matrix_ks, &
     320              :                                    matrix_s, scf_control, scf_section, &
     321              :                                    diis_step)
     322              : 
     323              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     324              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos
     325              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     326              :       TYPE(scf_control_type), POINTER                    :: scf_control
     327              :       TYPE(section_vals_type), POINTER                   :: scf_section
     328              :       LOGICAL, INTENT(INOUT)                             :: diis_step
     329              : 
     330              :       INTEGER                                            :: cdiis_cholesky_method, cdiis_ncall, &
     331              :                                                             ispin, nspin
     332              :       LOGICAL                                            :: cdiis_step, do_level_shift, owns_ortho, &
     333              :                                                             use_adiis, use_cdiis, use_jacobi, &
     334              :                                                             use_subspace_fock
     335              :       REAL(KIND=dp)                                      :: candidate_shift, cdiis_error, &
     336              :                                                             diis_error, diis_weight, eps_diis
     337              :       TYPE(cp_fm_type), POINTER                          :: ortho
     338              :       TYPE(dbcsr_type), POINTER                          :: effective_ks_dbcsr, ortho_dbcsr
     339              : 
     340       103013 :       nspin = SIZE(matrix_ks)
     341       103013 :       NULLIFY (effective_ks_dbcsr, ortho, ortho_dbcsr)
     342              : 
     343       103013 :       use_adiis = scf_control%diagonalization%update_method == diag_update_method_adiis
     344       103013 :       use_subspace_fock = .FALSE.
     345       103013 :       IF (use_adiis) THEN
     346           68 :          IF (.NOT. ASSOCIATED(scf_env%scf_subspace_buffer)) THEN
     347            0 :             CPABORT("ADIIS is only available in the main Quickstep SCF workflow")
     348              :          END IF
     349           68 :          use_subspace_fock = scf_env%scf_subspace_buffer%use_combined_fock
     350              :       END IF
     351              : 
     352       103013 :       eps_diis = scf_control%eps_diis
     353       103013 :       use_cdiis = .FALSE.
     354       103013 :       IF (use_adiis .AND. ASSOCIATED(scf_env%scf_diis_buffer)) THEN
     355              :          IF (.NOT. scf_env%skip_diis .AND. scf_env%iter_count > 1 .AND. &
     356              :              .NOT. scf_env%adiis_check_next .AND. &
     357           68 :              .NOT. scf_env%scf_subspace_buffer%last_restart .AND. &
     358              :              scf_env%scf_subspace_buffer%nstored > 0) THEN
     359           62 :             use_cdiis = scf_env%iter_delta < eps_diis .OR. scf_env%scf_diis_buffer%ncall > 0
     360              :          END IF
     361              :       END IF
     362              : 
     363       224794 :       DO ispin = 1, nspin
     364       224794 :          IF (use_subspace_fock .AND. .NOT. use_cdiis) THEN
     365              :             CALL copy_dbcsr_to_fm(scf_env%scf_subspace_buffer%combined_fock(ispin, 1)%matrix, &
     366           20 :                                   scf_env%scf_work1(ispin), scf_env%fm_copy_plan(ispin), check_plan=.TRUE.)
     367              :          ELSE
     368              :             CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, scf_env%scf_work1(ispin), &
     369       121761 :                                   scf_env%fm_copy_plan(ispin), check_plan=.TRUE.)
     370              :          END IF
     371              :       END DO
     372              : 
     373       103013 :       IF (use_adiis) THEN
     374           68 :          diis_step = .FALSE.
     375           68 :          diis_error = scf_env%scf_subspace_buffer%last_old_fock_weight
     376           68 :          diis_weight = scf_env%scf_subspace_buffer%diis_weight
     377           68 :          IF (use_cdiis) THEN
     378           46 :             cdiis_ncall = scf_env%scf_diis_buffer%ncall
     379              :             CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
     380              :                                 scf_env%scf_work2, scf_env%iter_delta, cdiis_error, cdiis_step, &
     381           46 :                                 eps_diis, 2, s_matrix=matrix_s, scf_section=scf_section)
     382           46 :             IF (.NOT. ieee_is_finite(cdiis_error) .OR. cdiis_error >= eps_diis) THEN
     383            6 :                cdiis_step = .FALSE.
     384            6 :                IF (cdiis_ncall < scf_env%scf_diis_buffer%nbuffer) THEN
     385              :                   ! The rejected state has not overwritten a full circular buffer.
     386            6 :                   scf_env%scf_diis_buffer%ncall = cdiis_ncall
     387              :                ELSE
     388            0 :                   CALL qs_diis_b_clear(scf_env%scf_diis_buffer)
     389            0 :                   diis_weight = 0.0_dp
     390              :                END IF
     391              :             END IF
     392           46 :             IF (cdiis_step) THEN
     393              :                ! Use one half-weight handover step; MAX_DIIS only controls the buffer capacity.
     394           34 :                diis_weight = MIN(1.0_dp, diis_weight + 0.5_dp)
     395              :             ELSE
     396              :                ! A rejected or deferred CDIIS step must not leave a partial raw-Fock blend active.
     397           12 :                diis_weight = 0.0_dp
     398              :             END IF
     399           46 :             IF (diis_weight < 1.0_dp) THEN
     400           54 :                DO ispin = 1, nspin
     401           36 :                   IF (use_subspace_fock) THEN
     402              :                      CALL copy_dbcsr_to_fm( &
     403              :                         scf_env%scf_subspace_buffer%combined_fock(ispin, 1)%matrix, scf_env%scf_work2, &
     404           32 :                         scf_env%fm_copy_plan(ispin), check_plan=.TRUE.)
     405              :                   ELSE
     406              :                      CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, scf_env%scf_work2, &
     407            4 :                                            scf_env%fm_copy_plan(ispin), check_plan=.TRUE.)
     408              :                   END IF
     409              :                   CALL cp_fm_scale_and_add(diis_weight, scf_env%scf_work1(ispin), &
     410           54 :                                            1.0_dp - diis_weight, scf_env%scf_work2)
     411              :                END DO
     412              :             END IF
     413           46 :             diis_step = cdiis_step .AND. diis_weight >= 1.0_dp
     414           46 :             IF (diis_step) diis_error = cdiis_error
     415           22 :          ELSE IF (ASSOCIATED(scf_env%scf_diis_buffer)) THEN
     416           22 :             IF (scf_env%scf_diis_buffer%ncall > 0) CALL qs_diis_b_clear(scf_env%scf_diis_buffer)
     417           22 :             diis_weight = 0.0_dp
     418              :          END IF
     419           68 :          scf_env%scf_subspace_buffer%diis_weight = diis_weight
     420              :       ELSE
     421       102945 :          IF (scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis) THEN
     422              :             CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
     423              :                                 scf_env%scf_work2, scf_env%iter_delta, diis_error, diis_step, &
     424              :                                 eps_diis, scf_control%nmixing, &
     425              :                                 s_matrix=matrix_s, &
     426        82855 :                                 scf_section=scf_section)
     427              :          ELSE
     428        20090 :             diis_step = .FALSE.
     429              :          END IF
     430              :       END IF
     431              : 
     432       103013 :       candidate_shift = 0.0_dp
     433       103013 :       IF (use_adiis) candidate_shift = adiis_candidate_shift(scf_env)
     434       103013 :       IF (candidate_shift > 0.0_dp) THEN
     435           14 :          CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, scf_env%scf_work2, scf_env%fm_copy_plan(0), check_plan=.TRUE.)
     436           42 :          DO ispin = 1, nspin
     437           42 :             CALL shift_candidate_real(scf_env%scf_work1(ispin), scf_env%scf_work2, mos(ispin), candidate_shift)
     438              :          END DO
     439              :       END IF
     440              : 
     441              :       do_level_shift = ((scf_control%level_shift /= 0.0_dp) .AND. &
     442              :                         ((scf_control%density_guess == core_guess) .OR. &
     443       103013 :                          (scf_env%iter_count > 1)))
     444              : 
     445       103013 :       IF (.NOT. use_adiis .AND. (scf_env%iter_count > 1) .AND. &
     446              :           (scf_env%iter_delta < scf_control%diagonalization%eps_jacobi)) THEN
     447            0 :          use_jacobi = .TRUE.
     448              :       ELSE
     449       102945 :          use_jacobi = .FALSE.
     450              :       END IF
     451              : 
     452           68 :       IF (use_adiis .AND. .NOT. diis_step) THEN
     453           40 :          scf_env%iter_param = diis_error
     454           40 :          IF (scf_env%scf_subspace_buffer%last_restart) THEN
     455            0 :             scf_env%iter_method = "ADIIS/Rst."
     456              :          ELSE
     457           40 :             scf_env%iter_method = "ADIIS/Diag."
     458              :          END IF
     459       102973 :       ELSE IF (diis_step) THEN
     460        51449 :          scf_env%iter_param = diis_error
     461        51449 :          IF (use_jacobi) THEN
     462            0 :             scf_env%iter_method = "DIIS/Jacobi"
     463              :          ELSE
     464        51449 :             scf_env%iter_method = "DIIS/Diag."
     465              :          END IF
     466              :       ELSE
     467        51524 :          IF (scf_env%mixing_method == 0) THEN
     468            0 :             scf_env%iter_method = "NoMix/Diag."
     469        51524 :          ELSE IF (scf_env%mixing_method == 1) THEN
     470        45472 :             scf_env%iter_param = scf_env%p_mix_alpha
     471        45472 :             IF (use_jacobi) THEN
     472            0 :                scf_env%iter_method = "P_Mix/Jacobi"
     473              :             ELSE
     474        45472 :                scf_env%iter_method = "P_Mix/Diag."
     475              :             END IF
     476         6052 :          ELSE IF (scf_env%mixing_method > 1) THEN
     477         6052 :             scf_env%iter_param = scf_env%mixing_store%alpha
     478         6052 :             IF (use_jacobi) THEN
     479            0 :                scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Jacobi"
     480              :             ELSE
     481         6052 :                scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
     482              :             END IF
     483              :          END IF
     484              :       END IF
     485              : 
     486       103013 :       IF (scf_env%cholesky_method == cholesky_dbcsr .AND. .NOT. use_cdiis) THEN
     487         1236 :          ortho_dbcsr => scf_env%ortho_dbcsr
     488         3690 :          DO ispin = 1, nspin
     489         2454 :             effective_ks_dbcsr => matrix_ks(ispin)%matrix
     490         2454 :             IF (use_subspace_fock) THEN
     491            0 :                effective_ks_dbcsr => scf_env%scf_subspace_buffer%combined_fock(ispin, 1)%matrix
     492              :             END IF
     493              :             CALL eigensolver_dbcsr(matrix_ks=effective_ks_dbcsr, matrix_ks_fm=scf_env%scf_work1(ispin), &
     494              :                                    mo_set=mos(ispin), &
     495              :                                    ortho_dbcsr=ortho_dbcsr, &
     496         3690 :                                    ksbuf1=scf_env%buf1_dbcsr, ksbuf2=scf_env%buf2_dbcsr)
     497              :          END DO
     498              : 
     499       101777 :       ELSE IF (scf_env%cholesky_method > cholesky_off) THEN
     500       101337 :          cdiis_cholesky_method = scf_env%cholesky_method
     501       101337 :          IF (cdiis_cholesky_method == cholesky_dbcsr) THEN
     502            0 :             cdiis_cholesky_method = cholesky_inverse
     503              :          END IF
     504       101337 :          IF (scf_env%cholesky_method == cholesky_inverse) THEN
     505          612 :             ortho => scf_env%ortho_m1
     506              :          ELSE
     507       100725 :             ortho => scf_env%ortho
     508              :          END IF
     509              : 
     510       101337 :          owns_ortho = .FALSE.
     511       101337 :          IF (.NOT. ASSOCIATED(ortho)) THEN
     512            0 :             ALLOCATE (ortho)
     513            0 :             owns_ortho = .TRUE.
     514              :          END IF
     515              : 
     516       220136 :          DO ispin = 1, nspin
     517       220136 :             IF (direct_generalized_diagonalization .AND. .NOT. do_level_shift) THEN
     518              :                CALL eigensolver_generalized(matrix_ks_fm=scf_env%scf_work1(ispin), &
     519              :                                             matrix_s=matrix_s(ispin)%matrix, &
     520              :                                             mo_set=mos(ispin), &
     521            0 :                                             work=scf_env%scf_work2)
     522              :             ELSE
     523       118799 :                IF (do_level_shift) THEN
     524              :                   CALL eigensolver(matrix_ks_fm=scf_env%scf_work1(ispin), &
     525              :                                    mo_set=mos(ispin), &
     526              :                                    ortho=ortho, &
     527              :                                    work=scf_env%scf_work2, &
     528              :                                    cholesky_method=cdiis_cholesky_method, &
     529              :                                    do_level_shift=do_level_shift, &
     530              :                                    level_shift=scf_control%level_shift, &
     531              :                                    matrix_u_fm=scf_env%ortho, &
     532          158 :                                    use_jacobi=use_jacobi)
     533              :                ELSE
     534              :                   CALL eigensolver(matrix_ks_fm=scf_env%scf_work1(ispin), &
     535              :                                    mo_set=mos(ispin), &
     536              :                                    ortho=ortho, &
     537              :                                    work=scf_env%scf_work2, &
     538              :                                    cholesky_method=cdiis_cholesky_method, &
     539              :                                    do_level_shift=do_level_shift, &
     540              :                                    level_shift=scf_control%level_shift, &
     541       118641 :                                    use_jacobi=use_jacobi)
     542              :                END IF
     543              :             END IF
     544              :          END DO
     545              : 
     546       101337 :          IF (scf_env%cholesky_method /= cholesky_dbcsr) THEN
     547       101337 :             scf_env%cholesky_method = cdiis_cholesky_method
     548              :          END IF
     549              : 
     550       101337 :          IF (owns_ortho) DEALLOCATE (ortho)
     551              :       ELSE
     552          440 :          ortho => scf_env%ortho
     553              : 
     554          440 :          owns_ortho = .FALSE.
     555          440 :          IF (.NOT. ASSOCIATED(ortho)) THEN
     556            0 :             ALLOCATE (ortho)
     557            0 :             owns_ortho = .TRUE.
     558              :          END IF
     559              : 
     560          440 :          IF (do_level_shift) THEN
     561          172 :          DO ispin = 1, nspin
     562              :          IF (ASSOCIATED(scf_env%scf_work1_red) .AND. ASSOCIATED(scf_env%scf_work2_red) &
     563          172 :              .AND. ASSOCIATED(scf_env%ortho_red) .AND. ASSOCIATED(scf_env%ortho_m1_red)) THEN
     564              :             CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
     565              :                                   mo_set=mos(ispin), &
     566              :                                   ortho=ortho, &
     567              :                                   work=scf_env%scf_work2, &
     568              :                                   do_level_shift=do_level_shift, &
     569              :                                   level_shift=scf_control%level_shift, &
     570              :                                   matrix_u_fm=scf_env%ortho_m1, &
     571              :                                   use_jacobi=use_jacobi, &
     572              :                                   jacobi_threshold=scf_control%diagonalization%jacobi_threshold, &
     573              :                                   matrix_ks_fm_red=scf_env%scf_work1_red(ispin), &
     574              :                                   ortho_red=scf_env%ortho_red, &
     575              :                                   work_red=scf_env%scf_work2_red, &
     576           86 :                                   matrix_u_fm_red=scf_env%ortho_m1_red)
     577              :          ELSE
     578              :             CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
     579              :                                   mo_set=mos(ispin), &
     580              :                                   ortho=ortho, &
     581              :                                   work=scf_env%scf_work2, &
     582              :                                   do_level_shift=do_level_shift, &
     583              :                                   level_shift=scf_control%level_shift, &
     584              :                                   matrix_u_fm=scf_env%ortho_m1, &
     585              :                                   use_jacobi=use_jacobi, &
     586            0 :                                   jacobi_threshold=scf_control%diagonalization%jacobi_threshold)
     587              :          END IF
     588              :          END DO
     589              :          ELSE
     590          796 :          DO ispin = 1, nspin
     591              :          IF (ASSOCIATED(scf_env%scf_work1_red) .AND. ASSOCIATED(scf_env%scf_work2_red) &
     592          796 :              .AND. ASSOCIATED(scf_env%ortho_red)) THEN
     593              :             CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
     594              :                                   mo_set=mos(ispin), &
     595              :                                   ortho=ortho, &
     596              :                                   work=scf_env%scf_work2, &
     597              :                                   do_level_shift=do_level_shift, &
     598              :                                   level_shift=scf_control%level_shift, &
     599              :                                   use_jacobi=use_jacobi, &
     600              :                                   jacobi_threshold=scf_control%diagonalization%jacobi_threshold, &
     601              :                                   matrix_ks_fm_red=scf_env%scf_work1_red(ispin), &
     602              :                                   ortho_red=scf_env%ortho_red, &
     603          442 :                                   work_red=scf_env%scf_work2_red)
     604              :          ELSE
     605              :             CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
     606              :                                   mo_set=mos(ispin), &
     607              :                                   ortho=ortho, &
     608              :                                   work=scf_env%scf_work2, &
     609              :                                   do_level_shift=do_level_shift, &
     610              :                                   level_shift=scf_control%level_shift, &
     611              :                                   use_jacobi=use_jacobi, &
     612            0 :                                   jacobi_threshold=scf_control%diagonalization%jacobi_threshold)
     613              :          END IF
     614              :          END DO
     615              :          END IF
     616              : 
     617          440 :          IF (owns_ortho) DEALLOCATE (ortho)
     618              :       END IF
     619              : 
     620       103013 :    END SUBROUTINE general_eigenproblem
     621              : 
     622              : ! **************************************************************************************************
     623              : !> \brief ...
     624              : !> \param scf_env ...
     625              : !> \param mos ...
     626              : !> \param matrix_ks ...
     627              : !> \param matrix_s ...
     628              : !> \param scf_control ...
     629              : !> \param scf_section ...
     630              : !> \param diis_step ...
     631              : !> \param probe ...
     632              : ! **************************************************************************************************
     633       101955 :    SUBROUTINE do_general_diag(scf_env, mos, matrix_ks, &
     634              :                               matrix_s, scf_control, scf_section, &
     635              :                               diis_step, probe)
     636              : 
     637              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     638              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
     639              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     640              :       TYPE(scf_control_type), POINTER                    :: scf_control
     641              :       TYPE(section_vals_type), POINTER                   :: scf_section
     642              :       LOGICAL, INTENT(INOUT)                             :: diis_step
     643              :       TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
     644              :          POINTER                                         :: probe
     645              : 
     646              :       INTEGER                                            :: ispin, nspin
     647              :       REAL(KIND=dp)                                      :: total_zeff_corr
     648              : 
     649       101955 :       nspin = SIZE(matrix_ks)
     650              : 
     651              :       CALL general_eigenproblem(scf_env, mos, matrix_ks, &
     652       101955 :                                 matrix_s, scf_control, scf_section, diis_step)
     653              : 
     654              :       total_zeff_corr = 0.0_dp
     655       101955 :       total_zeff_corr = scf_env%sum_zeff_corr
     656              : 
     657       101955 :       IF (ABS(total_zeff_corr) > 0.0_dp) THEN
     658              :          CALL set_mo_occupation(mo_array=mos, &
     659           40 :                                 smear=scf_control%smear, tot_zeff_corr=total_zeff_corr)
     660              :       ELSE
     661       101915 :          IF (PRESENT(probe) .EQV. .TRUE.) THEN
     662           14 :             scf_control%smear%do_smear = .FALSE.
     663              :             CALL set_mo_occupation(mo_array=mos, &
     664              :                                    smear=scf_control%smear, &
     665           14 :                                    probe=probe)
     666              :          ELSE
     667       101901 :             IF (.NOT. scf_control%gce%do_gce) THEN
     668              :                CALL set_mo_occupation(mo_array=mos, &
     669       101533 :                                       smear=scf_control%smear)
     670              :             ELSE
     671              :                CALL set_mo_occupation(mo_array=mos, &
     672              :                                       smear=scf_control%smear, &
     673          368 :                                       gce=scf_control%gce)
     674              :             END IF
     675              :          END IF
     676              :       END IF
     677              : 
     678       221620 :       DO ispin = 1, nspin
     679              :          CALL calculate_density_matrix(mos(ispin), &
     680       221620 :                                        scf_env%p_mix_new(ispin, 1)%matrix)
     681              :       END DO
     682              : 
     683       101955 :    END SUBROUTINE do_general_diag
     684              : 
     685              : ! **************************************************************************************************
     686              : !> \brief Kpoint diagonalization routine
     687              : !>        Transforms matrices to kpoint, distributes kpoint groups, performs
     688              : !>        general diagonalization (no storgae of overlap decomposition), stores
     689              : !>        MOs, calculates occupation numbers, calculates density matrices
     690              : !>        in kpoint representation, transforms density matrices to real space
     691              : !> \param matrix_ks    Kohn-sham matrices (RS indices, global)
     692              : !> \param matrix_s     Overlap matrices (RS indices, global)
     693              : !> \param kpoints      Kpoint environment
     694              : !> \param scf_env      SCF environment
     695              : !> \param scf_control  SCF control variables
     696              : !> \param update_p ...
     697              : !> \param diis_step ...
     698              : !> \param diis_error ...
     699              : !> \param qs_env ...
     700              : !> \param probe ...
     701              : !> \param added_mos_auto_grow true when the adaptive virtual-space buffer must grow
     702              : !> \param potential Fixed Lowdin orbital potential for non-self-consistent k points.
     703              : !> \par History
     704              : !>      08.2014 created [JGH]
     705              : ! **************************************************************************************************
     706        36280 :    SUBROUTINE do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, update_p, &
     707        36280 :                                  diis_step, diis_error, qs_env, probe, added_mos_auto_grow, potential)
     708              : 
     709              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks, matrix_s
     710              :       TYPE(kpoint_type), POINTER                         :: kpoints
     711              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     712              :       TYPE(scf_control_type), POINTER                    :: scf_control
     713              :       LOGICAL, INTENT(IN)                                :: update_p
     714              :       LOGICAL, INTENT(INOUT)                             :: diis_step
     715              :       REAL(dp), INTENT(INOUT), OPTIONAL                  :: diis_error
     716              :       TYPE(qs_environment_type), OPTIONAL, POINTER       :: qs_env
     717              :       TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
     718              :          POINTER                                         :: probe
     719              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: added_mos_auto_grow
     720              :       REAL(dp), INTENT(IN), OPTIONAL, TARGET             :: potential(:, :)
     721              : 
     722              :       CHARACTER(len=*), PARAMETER :: routineN = 'do_general_diag_kp'
     723              : 
     724        36280 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: coeffs
     725        36280 :       REAL(dp), POINTER :: effective_u(:, :), adiis_u(:, :)
     726              :       INTEGER :: cdiis_ncall, handle, ib, ikp, ispin, kplocal, kpmax, &
     727              :                  lattice_fft, nb, nkp, nspin, omp_threads, nworkers, fft_ready
     728              :       INTEGER, DIMENSION(2)                              :: kp_range
     729              :       INTEGER, DIMENSION(3)                              :: nkp_grid
     730        36280 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
     731        36280 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     732              :       LOGICAL :: adiis_cdiis, cache_smat, cdiis_step, do_diis, my_added_mos_auto_grow, prepared_ops, prepared_part, &
     733              :                  reuse_smat, spin_grid_fft, use_adiis, use_grid_fft, use_local_kpoints, use_real_wfn
     734              :       REAL(KIND=dp)                                      :: diis_weight
     735        36280 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues
     736        36280 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
     737              :       TYPE(cp_cfm_type), POINTER :: cksmat, cmos, csmat, cwork
     738        36280 :       TYPE(kp_diag_workspace_type), ALLOCATABLE, TARGET :: workspace(:)
     739              :       TYPE(cp_fm_pool_type), POINTER     :: ao_ao_fm_pool
     740              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct, mo_struct
     741              :       TYPE(cp_fm_type)                                   :: fmlocal, rksmat, rsmat
     742        36280 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
     743              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     744        36280 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: adiis_ks, effective_ks
     745              :       TYPE(dbcsr_type), POINTER                          :: rmatrix
     746              :       TYPE(kpoint_env_type), POINTER                     :: kp
     747        36280 :       TYPE(kpoint_operator_context_type)                 :: op_ctx
     748              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     749              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     750        36280 :          POINTER                                         :: sab_nl
     751              :       TYPE(qs_matrix_pools_type), POINTER                :: mpools
     752        36280 :       TYPE(rskp_grid_type)                               :: s_grid
     753        36280 :       TYPE(rskp_grid_type), ALLOCATABLE, DIMENSION(:)    :: ks_grid
     754              :       TYPE(section_vals_type), POINTER                   :: scf_section
     755              : 
     756        36280 :       CALL timeset(routineN, handle)
     757              : 
     758        36280 :       my_added_mos_auto_grow = .FALSE.
     759        36280 :       IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .FALSE.
     760              : 
     761        36280 :       NULLIFY (adiis_ks, effective_ks, sab_nl)
     762              :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, use_real_wfn=use_real_wfn, kp_range=kp_range, &
     763              :                            kp_dist=kp_dist, sab_nl=sab_nl, &
     764        36280 :                            cell_to_index=cell_to_index, nkp_grid=nkp_grid, lattice_fft=lattice_fft)
     765        36280 :       CPASSERT(ASSOCIATED(sab_nl))
     766        36280 :       kplocal = kp_range(2) - kp_range(1) + 1
     767        97852 :       kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
     768              : 
     769              :       !Whether we use DIIS for k-points
     770        36280 :       do_diis = .FALSE.
     771        36280 :       use_adiis = update_p .AND. scf_control%diagonalization%update_method == diag_update_method_adiis
     772        36280 :       IF (use_adiis) THEN
     773           80 :          CPASSERT(ASSOCIATED(scf_env%scf_subspace_buffer))
     774              :       END IF
     775        36280 :       adiis_cdiis = .FALSE.
     776        36280 :       IF (use_adiis .AND. ASSOCIATED(kpoints%scf_diis_buffer)) THEN
     777              :          IF (scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis .AND. &
     778              :              .NOT. scf_env%adiis_check_next .AND. &
     779              :              .NOT. scf_env%scf_subspace_buffer%last_restart .AND. &
     780              :              scf_env%scf_subspace_buffer%nstored > 0 .AND. &
     781           80 :              PRESENT(diis_error) .AND. PRESENT(qs_env)) THEN
     782              :             adiis_cdiis = scf_env%iter_delta < scf_control%eps_diis .OR. &
     783           74 :                           kpoints%scf_diis_buffer%ncall > 0
     784              :          END IF
     785              :       END IF
     786              :       IF ((.NOT. use_adiis .AND. scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis .AND. &
     787        36280 :            .NOT. use_real_wfn .AND. PRESENT(diis_error) .AND. PRESENT(qs_env)) .OR. &
     788        27450 :           adiis_cdiis) do_diis = .TRUE.
     789              : 
     790        36280 :       adiis_ks => matrix_ks
     791        36280 :       NULLIFY (adiis_u)
     792        36280 :       IF (ALLOCATED(kpoints%lowdin_v)) adiis_u => kpoints%lowdin_v
     793        36280 :       IF (use_adiis) THEN
     794           80 :          IF (scf_env%scf_subspace_buffer%use_combined_fock) THEN
     795           32 :             adiis_ks => scf_env%scf_subspace_buffer%combined_fock
     796           32 :             IF (ASSOCIATED(adiis_u)) adiis_u => scf_env%scf_subspace_buffer%combined_aux
     797              :          END IF
     798              :       END IF
     799        36280 :       effective_ks => matrix_ks
     800        36280 :       NULLIFY (effective_u)
     801        36280 :       IF (ALLOCATED(kpoints%lowdin_v)) effective_u => kpoints%lowdin_v
     802        36280 :       IF (PRESENT(potential)) THEN
     803            0 :          CPASSERT(.NOT. update_p)
     804            0 :          effective_u => potential
     805              :       END IF
     806        36280 :       IF (use_adiis .AND. .NOT. adiis_cdiis) THEN
     807           30 :          effective_ks => adiis_ks
     808           30 :          effective_u => adiis_u
     809              :       END IF
     810        36280 :       IF (use_adiis .AND. .NOT. do_diis) THEN
     811           30 :          scf_env%scf_subspace_buffer%diis_weight = 0.0_dp
     812           30 :          IF (ASSOCIATED(kpoints%scf_diis_buffer)) THEN
     813           30 :             IF (kpoints%scf_diis_buffer%ncall > 0) CALL qs_diis_b_clear_kp(kpoints%scf_diis_buffer)
     814              :          END IF
     815              :       END IF
     816              : 
     817        36280 :       para_env => kpoints%blacs_env_all%para_env
     818        36280 :       nspin = SIZE(matrix_ks, 1)
     819        36280 :       omp_threads = 1
     820        36280 : !$    omp_threads = omp_get_max_threads()
     821              :       ! One-rank groups use the same worker path for MPI, OpenMP and hybrid jobs.
     822        36280 :       use_local_kpoints = kpoints%para_env_kp%num_pe == 1 .AND. .NOT. use_real_wfn
     823        36280 :       IF (diag_check_requested()) use_local_kpoints = .FALSE.
     824        36280 :       ib = 0
     825        36280 :       nb = 0
     826        36280 :       NULLIFY (scf_section)
     827              : 
     828        36280 :       NULLIFY (rmatrix)
     829              : 
     830        36280 :       fmwork => scf_env%scf_work1
     831              :       ! Both real and complex operators share the same assembly and transfer context.
     832        36280 :       CALL kpoint_operator_context_create(op_ctx, kpoints, fmwork(1), nspin)
     833              : 
     834              :       ! fm pools to be used within a kpoint group
     835        36280 :       CALL get_kpoint_info(kpoints, mpools=mpools)
     836        36280 :       CALL mpools_get(mpools, ao_ao_fm_pool=ao_ao_fm_pool)
     837              : 
     838        36280 :       CALL fm_pool_create_fm(ao_ao_fm_pool, fmlocal)
     839        36280 :       CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
     840              : 
     841        36280 :       IF (use_real_wfn) THEN
     842              :          CALL cp_fm_create(rksmat, matrix_struct)
     843              :          CALL cp_fm_create(rsmat, matrix_struct)
     844              :       END IF
     845              :       ! Retain the unmodified S(k) for this SCF run, outside the driver-local
     846              :       ! operator context. Solvers receive work copies because they overwrite S.
     847        36280 :       cache_smat = update_p .AND. .NOT. use_real_wfn
     848        36280 :       reuse_smat = .FALSE.
     849        36280 :       IF (cache_smat) THEN
     850        35958 :          reuse_smat = ALLOCATED(kpoints%scf_smat)
     851        35958 :          IF (.NOT. reuse_smat) THEN
     852        19044 :             ALLOCATE (kpoints%scf_smat(kplocal))
     853        11496 :             DO ikp = 1, kplocal
     854        11496 :                CALL cp_cfm_create(kpoints%scf_smat(ikp), matrix_struct)
     855              :             END DO
     856              :          END IF
     857        35958 :          CPASSERT(SIZE(kpoints%scf_smat) == kplocal)
     858              :       END IF
     859              : 
     860              :       ! Prepare H/S before starting any round. ADIIS can replace only the idle KS slot.
     861              :       prepared_ops = .FALSE.
     862              :       ! A single distributed group can also assemble its prepared local tiles.
     863        36280 :       CALL kpoint_operator_prepare(op_ctx, effective_ks, kpoint_slot_ks, prepared_ops)
     864        36280 :       IF (.NOT. reuse_smat) THEN
     865         4096 :          CALL kpoint_operator_prepare(op_ctx, matrix_s, kpoint_slot_s, prepared_part, matrix_row=kpoint_spin_free)
     866         4106 :          prepared_ops = prepared_ops .AND. prepared_part
     867              :       END IF
     868              : 
     869        36280 :       use_local_kpoints = use_local_kpoints .AND. prepared_ops
     870        36280 :       nworkers = 1
     871        36280 :       IF (use_local_kpoints) nworkers = MIN(omp_threads, kplocal)
     872        36280 :       IF (.NOT. use_real_wfn .OR. do_diis) THEN
     873        36150 :          kp => kpoints%kp_env(1)%kpoint_env
     874        36150 :          IF (use_real_wfn) THEN
     875            0 :             CALL get_mo_set(kp%mos(1), mo_coeff=mo_coeff)
     876            0 :             CALL cp_fm_get_info(mo_coeff, matrix_struct=mo_struct)
     877              :          ELSE
     878        36150 :             mo_struct => kp%mos(1)%cmo_coeff%matrix_struct
     879              :          END IF
     880              :          CALL kp_diag_workspaces_create(workspace, nworkers, matrix_struct, mo_struct, 0, &
     881        36150 :                                         use_local_kpoints, scf_env%cholesky_method == cholesky_off)
     882        36150 :          cksmat => workspace(1)%cksmat
     883        36150 :          csmat => workspace(1)%csmat
     884        36150 :          cwork => workspace(1)%cwork
     885        36150 :          cmos => workspace(1)%cmos
     886              :       END IF
     887              : 
     888              :       ! Prepared operators select FFT or direct assembly inside their common route.
     889              :       ! Only an unprepared operator needs the sparse-grid/transfer fallback below.
     890              :       ! Divide its conservative memory budget between H spins and S.
     891       147348 :       ALLOCATE (ks_grid(nspin))
     892        36272 :       SELECT CASE (lattice_fft)
     893              :       CASE (lattice_fft_auto)
     894        36272 :          use_grid_fft = nkp >= 27
     895              :       CASE (lattice_fft_on)
     896            8 :          use_grid_fft = .TRUE.
     897              :       CASE (lattice_fft_off)
     898            0 :          use_grid_fft = .FALSE.
     899              :       CASE DEFAULT
     900        36280 :          CPABORT("Unknown lattice FFT selection mode")
     901              :       END SELECT
     902        36280 :       use_grid_fft = use_grid_fft .AND. .NOT. prepared_ops
     903              :       ! The driver needs sparse scratch only for forward lattice-FFT preparation.
     904        36280 :       IF (use_grid_fft) THEN
     905            0 :          ALLOCATE (rmatrix)
     906            0 :          CALL dbcsr_create(rmatrix, template=matrix_ks(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
     907            0 :          CALL cp_dbcsr_alloc_block_from_nbl(rmatrix, sab_nl)
     908              :       END IF
     909        36280 :       IF (use_grid_fft .AND. .NOT. reuse_smat) THEN
     910              :          CALL rskp_transform_grid_prepare(s_grid, rmatrix, matrix_s, 1, xkp, nkp_grid, &
     911              :                                           cell_to_index, sab_nl, use_grid_fft, &
     912            0 :                                           max_storage_bytes=512_int_8*1024_int_8**2/INT(nspin + 1, int_8))
     913            0 :          fft_ready = MERGE(1, 0, use_grid_fft)
     914            0 :          CALL para_env%min(fft_ready)
     915            0 :          use_grid_fft = fft_ready == 1
     916              :       END IF
     917        36280 :       IF (use_grid_fft) THEN
     918            0 :          DO ispin = 1, nspin
     919              :             CALL rskp_transform_grid_prepare(ks_grid(ispin), rmatrix, effective_ks, ispin, xkp, nkp_grid, &
     920              :                                              cell_to_index, sab_nl, spin_grid_fft, &
     921            0 :                                              max_storage_bytes=512_int_8*1024_int_8**2/INT(nspin + 1, int_8))
     922            0 :             use_grid_fft = use_grid_fft .AND. spin_grid_fft
     923              :          END DO
     924            0 :          fft_ready = MERGE(1, 0, use_grid_fft)
     925            0 :          CALL para_env%min(fft_ready)
     926            0 :          use_grid_fft = fft_ready == 1
     927              :       END IF
     928        36280 :       IF (.NOT. use_grid_fft) THEN
     929        36280 :          CALL rskp_transform_grid_release(s_grid)
     930        74788 :          DO ispin = 1, nspin
     931        74788 :             CALL rskp_transform_grid_release(ks_grid(ispin))
     932              :          END DO
     933              :       END IF
     934              : 
     935              :       ! Setup and start all the communication.
     936        36280 :       IF (.NOT. use_local_kpoints) THEN
     937        32656 :          DO ikp = 1, kpmax
     938        58162 :             DO ispin = 1, nspin
     939              :                CALL kpoint_operator_start(op_ctx, ikp, ispin, effective_ks, kpoint_slot_ks, &
     940        25506 :                                           ks_grid(ispin), use_grid_fft, matrix_row=ispin)
     941        47174 :                IF (.NOT. cache_smat .OR. (.NOT. reuse_smat .AND. ispin == 1)) THEN
     942              :                   CALL kpoint_operator_start(op_ctx, ikp, ispin, matrix_s, kpoint_slot_s, s_grid, &
     943         3648 :                                              use_grid_fft, matrix_row=kpoint_spin_free)
     944              :                END IF
     945              :             END DO
     946              :          END DO
     947              :       END IF
     948              : 
     949              :       ! Finish communication then diagonalise in each group
     950        36280 :       diis_weight = 1.0_dp
     951        36280 :       IF (do_diis) THEN
     952        27450 :          scf_section => section_vals_get_subs_vals(qs_env%input, "DFT%SCF")
     953        27450 :          cdiis_ncall = kpoints%scf_diis_buffer%ncall
     954        27450 :          CALL qs_diis_b_info_kp(kpoints%scf_diis_buffer, ib, nb)
     955        27450 :          CALL qs_diis_b_check_i_alloc_kp(kpoints%scf_diis_buffer, matrix_struct, nspin, kplocal, scf_section)
     956        27450 :          IF (use_local_kpoints) THEN
     957              :             CALL kp_diag_local_phase(op_ctx, kpoints, workspace, scf_env, scf_control, nspin, &
     958        19708 :                                      cache_smat, reuse_smat, use_adiis, ib, .TRUE., 1.0_dp, potential=effective_u)
     959              :          ELSE
     960        19540 :             DO ikp = 1, kpmax
     961        34482 :                DO ispin = 1, nspin
     962        14942 :                   CALL harvest_operators(ikp, ispin)
     963        14942 :                   IF (ikp > kplocal) CYCLE
     964              :                   CALL qs_diis_b_calc_err_kp(kpoints%scf_diis_buffer, ib, kp%mos, cksmat, csmat, &
     965              :                                              ispin, ikp, cmos, real_wfn=use_real_wfn, &
     966        26740 :                                              local=.FALSE., gemm_ctx=workspace(1)%gemm_ctx)
     967              : 
     968              :                END DO !ispin
     969              :             END DO !ikp
     970              : 
     971              :          END IF
     972              : 
     973        82350 :          ALLOCATE (coeffs(nb))
     974              :          CALL qs_diis_b_step_kp(kpoints%scf_diis_buffer, coeffs, ib, nb, scf_env%iter_delta, diis_error, &
     975              :                                 cdiis_step, scf_control%eps_diis, nspin, nkp, kplocal, &
     976              :                                 MERGE(2, scf_control%nmixing, use_adiis), &
     977        54850 :                                 scf_section, kpoints%para_env_inter_kp)
     978              :          diis_weight = 1.0_dp
     979        27450 :          IF (use_adiis) THEN
     980           50 :             diis_weight = scf_env%scf_subspace_buffer%diis_weight
     981           50 :             IF (.NOT. ieee_is_finite(diis_error) .OR. diis_error >= scf_control%eps_diis) THEN
     982            6 :                cdiis_step = .FALSE.
     983            6 :                IF (cdiis_ncall < kpoints%scf_diis_buffer%nbuffer) THEN
     984              :                   ! The rejected state has not overwritten a full circular buffer.
     985            6 :                   kpoints%scf_diis_buffer%ncall = cdiis_ncall
     986              :                ELSE
     987            0 :                   CALL qs_diis_b_clear_kp(kpoints%scf_diis_buffer)
     988            0 :                   diis_weight = 0.0_dp
     989              :                END IF
     990              :             END IF
     991           50 :             IF (cdiis_step) THEN
     992              :                ! Use one half-weight handover step; MAX_DIIS only controls the buffer capacity.
     993           38 :                diis_weight = MIN(1.0_dp, diis_weight + 0.5_dp)
     994              :             ELSE
     995              :                ! A rejected or deferred CDIIS step must not leave a partial raw-Fock blend active.
     996           12 :                diis_weight = 0.0_dp
     997              :             END IF
     998           50 :             scf_env%scf_subspace_buffer%diis_weight = diis_weight
     999           50 :             diis_step = cdiis_step .AND. diis_weight >= 1.0_dp
    1000           50 :             IF (.NOT. diis_step) diis_error = scf_env%scf_subspace_buffer%last_old_fock_weight
    1001              :          ELSE
    1002        27400 :             diis_step = cdiis_step
    1003              :          END IF
    1004              : 
    1005              :          ! All first-pass instances have finished. Capture the selected
    1006              :          ! ADIIS operator once instead of retransferring it in every round.
    1007        54900 :          IF (use_adiis .AND. diis_weight < 1.0_dp) THEN
    1008           18 :             CALL kpoint_operator_prepare(op_ctx, adiis_ks, kpoint_slot_ks, prepared_part)
    1009              :             ! A collective prepare rejection must return all ranks to the transfer path.
    1010           18 :             use_local_kpoints = use_local_kpoints .AND. prepared_part
    1011              :          END IF
    1012              : 
    1013              :       ELSE
    1014         8830 :          IF (.NOT. update_p .OR. use_adiis) diis_step = .FALSE.
    1015              :       END IF
    1016              : 
    1017        36280 :       IF (use_local_kpoints) THEN
    1018              :          ! Unallocated arrays and disassociated pointers are absent at nonpointer optional dummies.
    1019        25292 :          IF (do_diis) effective_u => adiis_u
    1020              :          CALL kp_diag_local_phase(op_ctx, kpoints, workspace, scf_env, scf_control, nspin, &
    1021        25292 :                                   cache_smat, reuse_smat, use_adiis, ib, .FALSE., diis_weight, coeffs, effective_u)
    1022              :       ELSE
    1023        32656 :          DO ikp = 1, kpmax
    1024        58162 :             DO ispin = 1, nspin
    1025        25506 :                IF (do_diis) THEN
    1026        14942 :                   IF (use_adiis .AND. diis_weight < 1.0_dp) THEN
    1027              :                      CALL kpoint_operator_start(op_ctx, ikp, ispin, adiis_ks, kpoint_slot_ks, &
    1028            0 :                                                 use_grid=.FALSE., matrix_row=ispin)
    1029            0 :                      CALL kpoint_operator_finish(op_ctx, ikp, ispin, kpoint_slot_ks, cwork)
    1030            0 :                      IF (ikp <= kplocal .AND. ASSOCIATED(adiis_u)) THEN
    1031            0 :                         CALL lowdin_kp_apply(kpoints%kp_env(ikp)%kpoint_env, adiis_u(:, ispin), cmat=cwork)
    1032              :                      END IF
    1033              :                   END IF
    1034        14942 :                   IF (ikp > kplocal) CYCLE
    1035        14942 :                   CALL cp_cfm_to_cfm(kpoints%scf_diis_buffer%smat(ikp), csmat)
    1036        14942 :                   CALL kp_diis_candidate(kpoints, ikp, ispin, coeffs, diis_weight, cksmat, cwork)
    1037        14942 :                   IF (use_real_wfn) THEN
    1038            0 :                      CALL cp_cfm_to_fm(cksmat, rksmat, fmlocal)
    1039            0 :                      CALL cp_cfm_to_fm(csmat, rsmat, fmlocal)
    1040              :                   END IF
    1041              :                ELSE
    1042        10564 :                   CALL harvest_operators(ikp, ispin)
    1043        10564 :                   IF (ikp > kplocal) CYCLE
    1044              :                END IF
    1045        25506 :                kp => kpoints%kp_env(ikp)%kpoint_env
    1046        47174 :                IF (use_real_wfn) THEN
    1047          156 :                   CALL get_mo_set(kp%mos(ispin), mo_coeff=mo_coeff, eigenvalues=eigenvalues)
    1048          156 :                   IF (use_adiis) CALL shift_candidate_real(rksmat, rsmat, kp%mos(ispin), &
    1049            0 :                                                            adiis_candidate_shift(scf_env))
    1050          156 :                   IF (scf_env%cholesky_method == cholesky_off) THEN
    1051           40 :                      CALL cp_fm_geeig_canon(rksmat, rsmat, mo_coeff, eigenvalues, fmlocal, scf_control%eps_eigval)
    1052              :                   ELSE
    1053          116 :                      CALL cp_fm_geeig(rksmat, rsmat, mo_coeff, eigenvalues, fmlocal)
    1054              :                   END IF
    1055              :                ELSE
    1056        25350 :                   CALL kp_solve_complex(kp%mos(ispin), workspace(1), scf_env, scf_control, use_adiis, .FALSE.)
    1057              :                END IF
    1058              :             END DO
    1059              :          END DO
    1060              :       END IF
    1061        36280 :       IF (ALLOCATED(coeffs)) DEALLOCATE (coeffs)
    1062              : 
    1063        36280 :       CALL kpoint_operator_context_release(op_ctx)
    1064              : 
    1065        36280 :       IF (update_p) THEN
    1066              :          ! MO occupations
    1067        36088 :          IF (PRESENT(probe) .EQV. .TRUE.) THEN
    1068            0 :             scf_control%smear%do_smear = .FALSE.
    1069              :             CALL kpoint_set_mo_occupation(kpoints, scf_control%smear, &
    1070            0 :                                           probe=probe)
    1071              :          ELSE
    1072              :             CALL kpoint_set_mo_occupation(kpoints, scf_control%smear, &
    1073              :                                           added_mos_auto=scf_control%added_mos_auto, &
    1074        36088 :                                           added_mos_auto_grow=my_added_mos_auto_grow)
    1075              :          END IF
    1076        36088 :          IF (my_added_mos_auto_grow) THEN
    1077            0 :             IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
    1078              :          ELSE
    1079              :             ! density matrices
    1080        36088 :             CALL kpoint_density_matrices(kpoints)
    1081              :             ! density matrices in real space
    1082              :             CALL kpoint_density_transform(kpoints, scf_env%p_mix_new, .FALSE., &
    1083        36088 :                                           matrix_s(1, 1)%matrix, sab_nl, fmwork, overlap_rs=matrix_s)
    1084              :          END IF
    1085              :       END IF
    1086              : 
    1087        36280 :       IF (ASSOCIATED(rmatrix)) CALL dbcsr_deallocate_matrix(rmatrix)
    1088        36280 :       CALL rskp_transform_grid_release(s_grid)
    1089        74788 :       DO ispin = 1, nspin
    1090        74788 :          CALL rskp_transform_grid_release(ks_grid(ispin))
    1091              :       END DO
    1092        74788 :       DEALLOCATE (ks_grid)
    1093              : 
    1094        36280 :       IF (use_real_wfn) THEN
    1095          130 :          CALL cp_fm_release(rksmat)
    1096          130 :          CALL cp_fm_release(rsmat)
    1097              :       END IF
    1098        36280 :       IF (ALLOCATED(workspace)) CALL kp_diag_workspaces_release(workspace)
    1099        36280 :       CALL fm_pool_give_back_fm(ao_ao_fm_pool, fmlocal)
    1100              : 
    1101       108840 :       CALL timestop(handle)
    1102              : 
    1103              :    CONTAINS
    1104              : 
    1105              :       ! Serialized harvest only. Inactive tail rounds participate in every transfer,
    1106              :       ! then return before reading a local matrix or publishing the overlap cache.
    1107              : ! **************************************************************************************************
    1108              : !> \brief ...
    1109              : !> \param round ...
    1110              : !> \param spin ...
    1111              : ! **************************************************************************************************
    1112        25506 :       SUBROUTINE harvest_operators(round, spin)
    1113              :       INTEGER, INTENT(IN)                                :: round, spin
    1114              : 
    1115        25506 :          IF (use_real_wfn) THEN
    1116          156 :             CALL kpoint_operator_finish(op_ctx, round, spin, kpoint_slot_ks, fm_re=rksmat)
    1117          156 :             CALL kpoint_operator_finish(op_ctx, round, spin, kpoint_slot_s, fm_re=rsmat)
    1118          156 :             IF (round <= kplocal .AND. ASSOCIATED(effective_u)) THEN
    1119            0 :                CALL lowdin_kp_apply(kpoints%kp_env(round)%kpoint_env, effective_u(:, spin), rmat=rksmat)
    1120              :             END IF
    1121          156 :             IF (round <= kplocal .AND. do_diis) THEN
    1122            0 :                CALL cp_cfm_scale_and_add_fm(z_zero, cksmat, z_one, rksmat)
    1123            0 :                CALL cp_cfm_scale_and_add_fm(z_zero, csmat, z_one, rsmat)
    1124              :             END IF
    1125              :          ELSE
    1126        25350 :             CALL kpoint_operator_finish(op_ctx, round, spin, kpoint_slot_ks, cksmat)
    1127        25350 :             IF (round <= kplocal .AND. ASSOCIATED(effective_u)) THEN
    1128            0 :                CALL lowdin_kp_apply(kpoints%kp_env(round)%kpoint_env, effective_u(:, spin), cmat=cksmat)
    1129              :             END IF
    1130        25350 :             IF (.NOT. cache_smat .OR. (.NOT. reuse_smat .AND. spin == 1)) THEN
    1131         3492 :                CALL kpoint_operator_finish(op_ctx, round, spin, kpoint_slot_s, csmat)
    1132              :             END IF
    1133              :          END IF
    1134              : 
    1135        25506 :          IF (round > kplocal) RETURN
    1136        25506 :          kp => kpoints%kp_env(round)%kpoint_env
    1137        25506 :          IF (cache_smat) THEN
    1138        24352 :             IF (.NOT. reuse_smat .AND. spin == 1) THEN
    1139         2494 :                CALL cp_cfm_to_cfm(csmat, kpoints%scf_smat(round))
    1140              :             ELSE
    1141        21858 :                CALL cp_cfm_to_cfm(kpoints%scf_smat(round), csmat)
    1142              :             END IF
    1143              :          END IF
    1144              :       END SUBROUTINE harvest_operators
    1145              : 
    1146              :    END SUBROUTINE do_general_diag_kp
    1147              : 
    1148              : ! **************************************************************************************************
    1149              : !> \brief Execute a local numerical phase. All SCF decisions and collectives belong to the caller.
    1150              : !> \param ctx immutable prepared operators
    1151              : !> \param kpoints host environment
    1152              : !> \param workspace private dense/phase/LAPACK storage per worker
    1153              : !> \param scf_env SCF settings (read only during this phase)
    1154              : !> \param scf_control SCF control
    1155              : !> \param nspin spin count
    1156              : !> \param cache_smat retain the unmodified overlap
    1157              : !> \param reuse_smat overlap cache is already valid
    1158              : !> \param use_adiis shift an ADIIS candidate only
    1159              : !> \param ib DIIS insertion index
    1160              : !> \param store_error store raw F and its residual instead of solving
    1161              : !> \param diis_weight weight of the CDIIS candidate
    1162              : !> \param coeffs optional DIIS coefficients for the second phase
    1163              : !> \param potential optional Lowdin orbital potential paired with the prepared Hamiltonian
    1164              : ! **************************************************************************************************
    1165        45000 :    SUBROUTINE kp_diag_local_phase(ctx, kpoints, workspace, scf_env, scf_control, nspin, &
    1166        45000 :                                   cache_smat, reuse_smat, use_adiis, ib, store_error, diis_weight, coeffs, potential)
    1167              :       TYPE(kpoint_operator_context_type), INTENT(IN) :: ctx
    1168              :       TYPE(kpoint_type), POINTER :: kpoints
    1169              :       TYPE(kp_diag_workspace_type), TARGET, INTENT(INOUT) :: workspace(:)
    1170              :       TYPE(qs_scf_env_type), POINTER :: scf_env
    1171              :       TYPE(scf_control_type), POINTER :: scf_control
    1172              :       INTEGER, INTENT(IN) :: nspin, ib
    1173              :       LOGICAL, INTENT(IN) :: cache_smat, reuse_smat, use_adiis, store_error
    1174              :       REAL(KIND=dp), INTENT(IN) :: diis_weight
    1175              :       COMPLEX(KIND=dp), OPTIONAL, INTENT(IN) :: coeffs(:)
    1176              :       REAL(dp), OPTIONAL, INTENT(IN) :: potential(:, :)
    1177              : 
    1178        45000 :       COMPLEX(KIND=dp), ALLOCATABLE :: operators(:, :, :, :)
    1179        45000 :       REAL(KIND=dp), ALLOCATABLE :: block_work(:)
    1180              :       INTEGER :: first, ik, ikp, ispin, j, kplocal, nbatch, nmatrices, nworkers, thread, width
    1181              :       INTEGER(KIND=int_8) :: work_size
    1182              :       LOGICAL :: build_h, build_s
    1183              :       TYPE(kpoint_env_type), POINTER :: kp
    1184              :       TYPE(kp_diag_workspace_type), POINTER :: work
    1185              : 
    1186        45000 :       kplocal = kpoints%kp_range(2) - kpoints%kp_range(1) + 1
    1187        45000 :       IF (kplocal == 0) RETURN
    1188        45000 :       nworkers = SIZE(workspace)
    1189        45000 :       build_s = .NOT. PRESENT(coeffs) .AND. .NOT. reuse_smat
    1190        19708 :       build_h = .NOT. PRESENT(coeffs) .OR. diis_weight < 1.0_dp
    1191        45000 :       nmatrices = MERGE(1, 0, build_h) + MERGE(1, 0, build_s)
    1192        45000 :       width = 1
    1193        45000 :       work_size = 0_int_8
    1194        45000 :       IF (nmatrices > 0) CALL kpoint_operator_batch_size(ctx, nworkers, nmatrices, width, work_size)
    1195              :       ! Each worker assembles a bounded k tile, then consumes it using its private solver.
    1196              :       ! The second CDIIS phase combines history without allocating operator tiles.
    1197              : !$OMP PARALLEL DEFAULT(NONE) NUM_THREADS(nworkers) IF(nworkers > 1) &
    1198              : !$OMP SHARED(ctx,kpoints,workspace,scf_env,scf_control,nspin,cache_smat,reuse_smat,use_adiis,ib, &
    1199              : !$OMP        store_error,diis_weight,coeffs,potential,kplocal,nworkers,build_h,build_s,nmatrices,width,work_size) &
    1200        45000 : !$OMP PRIVATE(first,ik,ikp,ispin,j,nbatch,thread,kp,work,operators,block_work)
    1201              :       thread = 1
    1202              : !$    thread = omp_get_thread_num() + 1
    1203              :       work => workspace(thread)
    1204              :       ALLOCATE (operators(SIZE(work%cksmat%local_data, 1), SIZE(work%cksmat%local_data, 2), width, nmatrices), &
    1205              :                 block_work(work_size))
    1206              : !$OMP DO SCHEDULE(DYNAMIC, 1)
    1207              :       DO first = 1, kplocal, width
    1208              :          nbatch = MIN(width, kplocal - first + 1)
    1209              :          ik = kpoints%kp_range(1) + first - 1
    1210              :          IF (build_s) THEN
    1211              :             CALL kpoint_operator_evaluate_batch(ctx, 1, kpoint_slot_s, ik, operators(:, :, 1:nbatch, nmatrices), block_work)
    1212              :          END IF
    1213              :          DO ispin = 1, nspin
    1214              :             IF (build_h) THEN
    1215              :                CALL kpoint_operator_evaluate_batch(ctx, ispin, kpoint_slot_ks, ik, operators(:, :, 1:nbatch, 1), block_work)
    1216              :             END IF
    1217              :             DO j = 1, nbatch
    1218              :                ikp = first + j - 1
    1219              :                kp => kpoints%kp_env(ikp)%kpoint_env
    1220              :                IF (build_h) THEN
    1221              :                   IF (PRESENT(coeffs)) THEN
    1222              :                      work%csmat_base%local_data(:, :) = operators(:, :, j, 1)
    1223              :                      IF (PRESENT(potential)) CALL lowdin_kp_apply(kp, potential(:, ispin), cmat=work%csmat_base)
    1224              :                   ELSE
    1225              :                      work%cksmat%local_data(:, :) = operators(:, :, j, 1)
    1226              :                      IF (PRESENT(potential)) CALL lowdin_kp_apply(kp, potential(:, ispin), cmat=work%cksmat)
    1227              :                   END IF
    1228              :                END IF
    1229              :                IF (PRESENT(coeffs)) THEN
    1230              :                   CALL cp_cfm_to_cfm(kpoints%scf_diis_buffer%smat(ikp), work%csmat)
    1231              :                   CALL kp_diis_candidate(kpoints, ikp, ispin, coeffs, diis_weight, work%cksmat, work%csmat_base)
    1232              :                ELSE
    1233              :                   IF (reuse_smat) THEN
    1234              :                      CALL cp_cfm_to_cfm(kpoints%scf_smat(ikp), work%csmat)
    1235              :                   ELSE
    1236              :                      work%csmat%local_data(:, :) = operators(:, :, j, nmatrices)
    1237              :                   END IF
    1238              :                   IF (cache_smat .AND. .NOT. reuse_smat .AND. ispin == 1) THEN
    1239              :                      CALL cp_cfm_to_cfm(work%csmat, kpoints%scf_smat(ikp))
    1240              :                   END IF
    1241              :                END IF
    1242              :                IF (store_error) THEN
    1243              :                   CALL qs_diis_b_calc_err_kp(kpoints%scf_diis_buffer, ib, kp%mos, work%cksmat, work%csmat, &
    1244              :                                              ispin, ikp, work%cmos, local=.TRUE., gemm_ctx=work%gemm_ctx)
    1245              :                ELSE
    1246              :                   CALL kp_solve_complex(kp%mos(ispin), work, scf_env, scf_control, use_adiis, .TRUE.)
    1247              :                END IF
    1248              :             END DO
    1249              :          END DO
    1250              :       END DO
    1251              : !$OMP END DO
    1252        45000 :       DEALLOCATE (operators, block_work)
    1253              : !$OMP END PARALLEL
    1254              : 
    1255        45000 :    END SUBROUTINE kp_diag_local_phase
    1256              : 
    1257              : ! **************************************************************************************************
    1258              : !> \brief Form the same candidate on local and distributed layouts, preserving raw DIIS history.
    1259              : !> \param kpoints host DIIS buffer
    1260              : !> \param ikp local k-point index
    1261              : !> \param ispin spin index
    1262              : !> \param coeffs DIIS coefficients
    1263              : !> \param weight CDIIS blend weight
    1264              : !> \param fock output candidate
    1265              : !> \param adiis_fock ADIIS candidate, read only when weight is less than one
    1266              : ! **************************************************************************************************
    1267        48576 :    SUBROUTINE kp_diis_candidate(kpoints, ikp, ispin, coeffs, weight, fock, adiis_fock)
    1268              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1269              :       INTEGER, INTENT(IN)                                :: ikp, ispin
    1270              :       COMPLEX(KIND=dp), INTENT(IN)                       :: coeffs(:)
    1271              :       REAL(KIND=dp), INTENT(IN)                          :: weight
    1272              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: fock
    1273              :       TYPE(cp_cfm_type), INTENT(IN)                      :: adiis_fock
    1274              : 
    1275              :       INTEGER                                            :: jb
    1276              : 
    1277        48576 :       CALL cp_cfm_set_all(fock, z_zero)
    1278       211567 :       DO jb = 1, SIZE(coeffs)
    1279       211567 :          CALL cp_cfm_scale_and_add(z_one, fock, coeffs(jb), kpoints%scf_diis_buffer%param(jb, ispin, ikp))
    1280              :       END DO
    1281        48576 :       IF (weight < 1.0_dp) CALL cp_cfm_scale_and_add(CMPLX(weight, KIND=dp), fock, &
    1282           30 :                                                      CMPLX(1.0_dp - weight, KIND=dp), adiis_fock)
    1283        48576 :    END SUBROUTINE kp_diis_candidate
    1284              : 
    1285              : ! **************************************************************************************************
    1286              : !> \brief Shift, solve and publish a complex SCF candidate using private scratch.
    1287              : !> \param mos complex MO set
    1288              : !> \param work private workspace
    1289              : !> \param scf_env SCF settings
    1290              : !> \param scf_control SCF control
    1291              : !> \param use_adiis apply the candidate shift
    1292              : !> \param local select the one-rank local solver; otherwise honor the configured backend
    1293              : ! **************************************************************************************************
    1294        74197 :    SUBROUTINE kp_solve_complex(mos, work, scf_env, scf_control, use_adiis, local)
    1295              :       TYPE(mo_set_type), INTENT(INOUT)                   :: mos
    1296              :       TYPE(kp_diag_workspace_type), INTENT(INOUT)        :: work
    1297              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1298              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1299              :       LOGICAL, INTENT(IN)                                :: use_adiis, local
    1300              : 
    1301        74197 :       REAL(KIND=dp), POINTER                             :: eigenvalues(:)
    1302              : 
    1303        74197 :       CALL get_mo_set(mos, eigenvalues=eigenvalues)
    1304        74197 :       IF (use_adiis) CALL shift_candidate_complex(work%cksmat, work%csmat, mos, work%cmos, work%cwork, &
    1305          138 :                                                   adiis_candidate_shift(scf_env), local, work%gemm_ctx)
    1306        74197 :       IF (scf_env%cholesky_method == cholesky_off) THEN
    1307         4482 :          IF (local) THEN
    1308              :             CALL cp_cfm_geeig_canon_local(work%cksmat, work%csmat, mos%cmo_coeff, eigenvalues, work%cwork, &
    1309         1400 :                                           scf_control%eps_eigval, ws=work%solver)
    1310              :          ELSE
    1311              :             CALL cp_cfm_geeig_canon(work%cksmat, work%csmat, mos%cmo_coeff, eigenvalues, work%cwork, &
    1312         3082 :                                     scf_control%eps_eigval)
    1313              :          END IF
    1314              :       ELSE
    1315        69715 :          IF (local) THEN
    1316        47447 :             CALL cp_cfm_geeig_local(work%cksmat, work%csmat, mos%cmo_coeff, eigenvalues, ws=work%solver)
    1317              :          ELSE
    1318        22268 :             CALL cp_cfm_geeig(work%cksmat, work%csmat, mos%cmo_coeff, eigenvalues, work%cwork)
    1319              :          END IF
    1320              :       END IF
    1321        74197 :    END SUBROUTINE kp_solve_complex
    1322              : 
    1323              : ! **************************************************************************************************
    1324              : !> \brief Allocate all worker storage before launching numerical phases.
    1325              : !> \param workspace returned private workspaces
    1326              : !> \param nworkers number of workers
    1327              : !> \param matrix_struct AO layout of the k-point group
    1328              : !> \param mo_struct MO layout of the k-point group
    1329              : !> \param nentry number of phase-sum entries
    1330              : !> \param local allocate local phase and solver scratch
    1331              : !> \param canonical use the canonical solver
    1332              : !> \param lanczos allocate the block-Lanczos kernel scratch
    1333              : !> \param nkrylov number of block expansion steps, sizes the kernel scratch
    1334              : !> \param nblock number of columns refined jointly, sizes the kernel scratch
    1335              : ! **************************************************************************************************
    1336        36736 :    SUBROUTINE kp_diag_workspaces_create(workspace, nworkers, matrix_struct, mo_struct, nentry, local, canonical, &
    1337              :                                         lanczos, nkrylov, nblock)
    1338              :       TYPE(kp_diag_workspace_type), ALLOCATABLE, &
    1339              :          INTENT(OUT)                                     :: workspace(:)
    1340              :       INTEGER, INTENT(IN)                                :: nworkers
    1341              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct, mo_struct
    1342              :       INTEGER, INTENT(IN)                                :: nentry
    1343              :       LOGICAL, INTENT(IN)                                :: local, canonical
    1344              :       LOGICAL, INTENT(IN), OPTIONAL                      :: lanczos
    1345              :       INTEGER, INTENT(IN), OPTIONAL                      :: nkrylov, nblock
    1346              : 
    1347              :       INTEGER                                            :: i, n
    1348              :       LOGICAL                                            :: my_lanczos
    1349              : 
    1350        36736 :       my_lanczos = .FALSE.
    1351        36736 :       IF (PRESENT(lanczos)) my_lanczos = lanczos
    1352              : 
    1353       146944 :       ALLOCATE (workspace(nworkers))
    1354        73472 :       DO i = 1, nworkers
    1355        36736 :          CALL cp_cfm_create(workspace(i)%cksmat, matrix_struct)
    1356        36736 :          CALL cp_cfm_create(workspace(i)%csmat, matrix_struct)
    1357        36736 :          CALL cp_cfm_create(workspace(i)%cwork, matrix_struct)
    1358        36736 :          CALL cp_cfm_create(workspace(i)%cmos, mo_struct)
    1359              :          ! the transfer rounds of the Lanczos driver also need the stored
    1360              :          ! overlap copy, although they never run the local solvers
    1361        36736 :          IF (local .OR. my_lanczos) THEN
    1362        25878 :             CALL cp_cfm_create(workspace(i)%csmat_base, matrix_struct)
    1363              :          END IF
    1364        36736 :          IF (local) THEN
    1365        25748 :             CALL workspace(i)%gemm_ctx%create(LOCAL_GEMM_PU_GPU, timing=.FALSE.)
    1366        51952 :             ALLOCATE (workspace(i)%phase(1, nentry))
    1367        25748 :             n = matrix_struct%nrow_global
    1368        25748 :             IF (canonical) THEN
    1369          596 :                CALL cp_cfm_local_workspace_prepare(workspace(i)%solver, n, workspace(i)%cksmat%local_data)
    1370              :             ELSE
    1371              :                CALL cp_cfm_local_workspace_prepare(workspace(i)%solver, n, workspace(i)%cksmat%local_data, &
    1372        25152 :                                                    workspace(i)%csmat%local_data)
    1373              :             END IF
    1374              :          END IF
    1375        73472 :          IF (my_lanczos) THEN
    1376          586 :             CALL lanczos_workspace_create(workspace(i)%lan_ws, mo_struct, matrix_struct, nkrylov, nblock)
    1377              :          END IF
    1378              :       END DO
    1379        36736 :    END SUBROUTINE kp_diag_workspaces_create
    1380              : 
    1381              : ! **************************************************************************************************
    1382              : !> \brief Release dense matrices and automatic phase/LAPACK allocations after all workers finish.
    1383              : !> \param workspace private workspaces
    1384              : ! **************************************************************************************************
    1385        36736 :    SUBROUTINE kp_diag_workspaces_release(workspace)
    1386              :       TYPE(kp_diag_workspace_type), ALLOCATABLE, &
    1387              :          INTENT(INOUT)                                   :: workspace(:)
    1388              : 
    1389              :       INTEGER                                            :: i
    1390              : 
    1391        73472 :       DO i = 1, SIZE(workspace)
    1392        36736 :          CALL workspace(i)%gemm_ctx%destroy()
    1393        36736 :          CALL cp_cfm_release(workspace(i)%cksmat)
    1394        36736 :          CALL cp_cfm_release(workspace(i)%csmat)
    1395        36736 :          CALL cp_cfm_release(workspace(i)%csmat_base)
    1396        36736 :          CALL cp_cfm_release(workspace(i)%cwork)
    1397        36736 :          CALL cp_cfm_release(workspace(i)%cmos)
    1398        73472 :          CALL lanczos_workspace_release(workspace(i)%lan_ws)
    1399              :       END DO
    1400        73472 :       DEALLOCATE (workspace)
    1401        36736 :    END SUBROUTINE kp_diag_workspaces_release
    1402              : 
    1403              : ! **************************************************************************************************
    1404              : !> \brief Adaptive inner tolerance of an iterative solver from EPS_ADAPT:
    1405              : !>        loose while the density error sits far from self-consistency,
    1406              : !>        tracking that error at a fixed fraction and capped in the early
    1407              : !>        phase. A nonpositive factor or error disables the loosening and
    1408              : !>        returns the user threshold
    1409              : !> \param eps_iter user threshold
    1410              : !> \param eps_adapt loosening factor of the tracking
    1411              : !> \param iter_error outer error the threshold tracks
    1412              : !> \param noise_scale fraction of the outer error the solver noise keeps
    1413              : !> \param cap bound of the early loose phase
    1414              : !> \return ...
    1415              : ! **************************************************************************************************
    1416          700 :    PURE FUNCTION kp_adaptive_eps_iter(eps_iter, eps_adapt, iter_error, noise_scale, cap) RESULT(eps)
    1417              :       REAL(KIND=dp), INTENT(IN)                          :: eps_iter, eps_adapt, iter_error, &
    1418              :                                                             noise_scale, cap
    1419              :       REAL(KIND=dp)                                      :: eps
    1420              : 
    1421          700 :       IF (eps_adapt <= 0.0_dp .OR. iter_error <= 0.0_dp) THEN
    1422          612 :          eps = eps_iter
    1423              :       ELSE
    1424           88 :          eps = MAX(eps_iter, MIN(eps_adapt*iter_error/noise_scale, cap))
    1425              :       END IF
    1426          700 :    END FUNCTION kp_adaptive_eps_iter
    1427              : 
    1428              : ! **************************************************************************************************
    1429              : !> \brief Occupations, ADDED_MOS_AUTO growth check and the density exit
    1430              : !>        chain shared by the k-point diagonalization drivers. The
    1431              : !>        routine keeps its own bookkeeping: a growing step abandons the
    1432              : !>        density of the abandoned SCF step
    1433              : !> \param kpoints ...
    1434              : !> \param scf_env ...
    1435              : !> \param scf_control ...
    1436              : !> \param matrix_s_kp real-space overlap matrix, dbcsr image set
    1437              : !> \param sab_nl ...
    1438              : !> \param fmwork global scratch fms of the driver
    1439              : !> \param grow TRUE when the virtual-space buffer is too small for the
    1440              : !>        smearing tail: the outer loop grows the MOS and redoes this
    1441              : !>        SCF step
    1442              : ! **************************************************************************************************
    1443         1586 :    SUBROUTINE kp_diag_exit_chain(kpoints, scf_env, scf_control, matrix_s_kp, sab_nl, fmwork, grow)
    1444              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1445              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1446              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1447              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_s_kp
    1448              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1449              :          POINTER                                         :: sab_nl
    1450              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
    1451              :       LOGICAL, INTENT(OUT)                               :: grow
    1452              : 
    1453              :       CALL kpoint_set_mo_occupation(kpoints, scf_control%smear, &
    1454              :                                     added_mos_auto=scf_control%added_mos_auto, &
    1455         1586 :                                     added_mos_auto_grow=grow)
    1456         1586 :       IF (grow) RETURN
    1457         1578 :       CALL kpoint_density_matrices(kpoints)
    1458              :       CALL kpoint_density_transform(kpoints, scf_env%p_mix_new, .FALSE., &
    1459         1578 :                                     matrix_s_kp(1, 1)%matrix, sab_nl, fmwork, overlap_rs=matrix_s_kp)
    1460              :    END SUBROUTINE kp_diag_exit_chain
    1461              : 
    1462              : ! **************************************************************************************************
    1463              : !> \brief Per-column convergence thresholds of an iterative k-point
    1464              : !>        solver: the occupation decides which columns sit beyond the
    1465              : !>        thermal smearing tail and converge at the relaxed empty
    1466              : !>        threshold
    1467              : !> \param occupation occupation numbers of the channel
    1468              : !> \param eps_iter threshold of the occupied columns
    1469              : !> \param eps_iter_empty relaxed threshold of the unoccupied columns
    1470              : !> \param eps_col per-column thresholds, at least as long as the
    1471              : !>        occupation numbers
    1472              : ! **************************************************************************************************
    1473          764 :    SUBROUTINE kp_eps_col_by_occupation(occupation, eps_iter, eps_iter_empty, eps_col)
    1474              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), POINTER   :: occupation
    1475              :       REAL(KIND=dp), INTENT(IN)                          :: eps_iter, eps_iter_empty
    1476              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: eps_col
    1477              : 
    1478              :       INTEGER                                            :: imo
    1479              : 
    1480         7916 :       DO imo = 1, SIZE(occupation)
    1481         7916 :          IF (occupation(imo) < occ_tol) THEN
    1482         4229 :             eps_col(imo) = eps_iter_empty
    1483              :          ELSE
    1484         2923 :             eps_col(imo) = eps_iter
    1485              :          END IF
    1486              :       END DO
    1487          764 :    END SUBROUTINE kp_eps_col_by_occupation
    1488              : 
    1489              : ! **************************************************************************************************
    1490              : !> \brief Common setup of the iterative k-point drivers: the global
    1491              : !>        scratch fms, the operator context and the group matrix
    1492              : !>        structure
    1493              : !> \param qs_env ...
    1494              : !> \param kpoints ...
    1495              : !> \param nspin number of spin components
    1496              : !> \param matrix_ks_kp real-space Kohn-Sham matrices, dbcsr image set
    1497              : !> \param matrix_s_kp real-space overlap matrix, dbcsr image set
    1498              : !> \param fmwork returned global scratch fms
    1499              : !> \param op_ctx returned operator context
    1500              : !> \param matrix_struct returned AO layout of the k-point group
    1501              : !> \param prepare prepare the operator snapshot right away. The
    1502              : !>        transfer rounds of the Lanczos driver assemble lazily through
    1503              : !>        the get path and skip the snapshot
    1504              : !> \param prepared optional returned status of the snapshot preparation
    1505              : ! **************************************************************************************************
    1506         1492 :    SUBROUTINE kp_diag_setup(qs_env, kpoints, nspin, matrix_ks_kp, matrix_s_kp, fmwork, op_ctx, &
    1507              :                             matrix_struct, prepare, prepared)
    1508              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1509              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1510              :       INTEGER, INTENT(IN)                                :: nspin
    1511              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks_kp, matrix_s_kp
    1512              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
    1513              :       TYPE(kpoint_operator_context_type)                 :: op_ctx
    1514              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    1515              :       LOGICAL, INTENT(IN)                                :: prepare
    1516              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: prepared
    1517              : 
    1518              :       INTEGER                                            :: i
    1519              :       LOGICAL                                            :: ks_ready, s_ready
    1520              :       TYPE(cp_fm_pool_type), POINTER                     :: ao_ao_fm_pool, kp_ao_ao_fm_pool
    1521              :       TYPE(qs_matrix_pools_type), POINTER                :: kp_mpools, mpools
    1522              : 
    1523         1492 :       IF (PRESENT(prepared)) prepared = .FALSE.
    1524         1492 :       CALL get_qs_env(qs_env, mpools=mpools)
    1525         1492 :       CALL mpools_get(mpools, ao_ao_fm_pool=ao_ao_fm_pool)
    1526         7460 :       ALLOCATE (fmwork(4))
    1527         7460 :       DO i = 1, 4
    1528         7460 :          CALL fm_pool_create_fm(ao_ao_fm_pool, fmwork(i))
    1529              :       END DO
    1530         1492 :       CALL kpoint_operator_context_create(op_ctx, kpoints, fmwork(1), nspin)
    1531         1492 :       IF (prepare) THEN
    1532         1362 :          CALL kpoint_operator_prepare(op_ctx, matrix_ks_kp, kpoint_slot_ks, ks_ready)
    1533              :          CALL kpoint_operator_prepare(op_ctx, matrix_s_kp, kpoint_slot_s, s_ready, &
    1534         1362 :                                       matrix_row=kpoint_spin_free)
    1535         1362 :          IF (PRESENT(prepared)) prepared = ks_ready .AND. s_ready
    1536              :       END IF
    1537         1492 :       CALL get_kpoint_info(kpoints, mpools=kp_mpools)
    1538         1492 :       CALL mpools_get(kp_mpools, ao_ao_fm_pool=kp_ao_ao_fm_pool)
    1539         1492 :       matrix_struct => fm_pool_get_el_struct(kp_ao_ao_fm_pool)
    1540         1492 :    END SUBROUTINE kp_diag_setup
    1541              : 
    1542              : ! **************************************************************************************************
    1543              : !> \brief Common finalization of the iterative k-point drivers: release
    1544              : !>        the operator context and return the global scratch fms
    1545              : !> \param qs_env ...
    1546              : !> \param fmwork global scratch fms of the driver
    1547              : !> \param op_ctx operator context of the driver
    1548              : ! **************************************************************************************************
    1549         1492 :    SUBROUTINE kp_diag_finalize(qs_env, fmwork, op_ctx)
    1550              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1551              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
    1552              :       TYPE(kpoint_operator_context_type)                 :: op_ctx
    1553              : 
    1554              :       INTEGER                                            :: i
    1555              :       TYPE(cp_fm_pool_type), POINTER                     :: ao_ao_fm_pool
    1556              :       TYPE(qs_matrix_pools_type), POINTER                :: mpools
    1557              : 
    1558         1492 :       CALL kpoint_operator_context_release(op_ctx)
    1559         1492 :       CALL get_qs_env(qs_env, mpools=mpools)
    1560         1492 :       CALL mpools_get(mpools, ao_ao_fm_pool=ao_ao_fm_pool)
    1561         7460 :       DO i = 1, 4
    1562         7460 :          CALL fm_pool_give_back_fm(ao_ao_fm_pool, fmwork(i))
    1563              :       END DO
    1564         1492 :       DEALLOCATE (fmwork)
    1565         1492 :    END SUBROUTINE kp_diag_finalize
    1566              : 
    1567              : ! **************************************************************************************************
    1568              : !> \brief Kpoint diagonalization routine
    1569              : !>        Transforms matrices to kpoint, distributes kpoint groups, performs
    1570              : !>        general diagonalization (no storgae of overlap decomposition), stores
    1571              : !>        MOs, calculates occupation numbers, calculates density matrices
    1572              : !>        in kpoint representation, transforms density matrices to real space
    1573              : !> \param matrix_ks    Kohn-sham matrices (RS indices, global)
    1574              : !> \param matrix_s     Overlap matrices (RS indices, global)
    1575              : !> \param kpoints      Kpoint environment
    1576              : !> \param fmwork       global-layout FM template in the first array entry
    1577              : !> \par History
    1578              : !>      08.2014 created [JGH]
    1579              : ! **************************************************************************************************
    1580           22 :    SUBROUTINE diag_kp_basic(matrix_ks, matrix_s, kpoints, fmwork)
    1581              : 
    1582              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks, matrix_s
    1583              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1584              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
    1585              : 
    1586              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'diag_kp_basic'
    1587              : 
    1588              :       INTEGER                                            :: handle, ikp, ispin, kplocal, kpmax, nspin
    1589              :       INTEGER, DIMENSION(2)                              :: kp_range
    1590           22 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
    1591              :       LOGICAL                                            :: use_real_wfn
    1592           22 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues
    1593              :       TYPE(cp_cfm_type)                                  :: cksmat, cmos, csmat, cwork
    1594              :       TYPE(cp_fm_pool_type), POINTER                     :: ao_ao_fm_pool
    1595              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct, mo_struct
    1596              :       TYPE(cp_fm_type)                                   :: fmlocal, rksmat, rsmat
    1597              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1598              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1599           22 :       TYPE(kpoint_operator_context_type)                 :: op_ctx
    1600              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1601           22 :          POINTER                                         :: sab_nl
    1602              :       TYPE(qs_matrix_pools_type), POINTER                :: mpools
    1603              : 
    1604           22 :       CALL timeset(routineN, handle)
    1605              : 
    1606           22 :       NULLIFY (sab_nl)
    1607              :       CALL get_kpoint_info(kpoints, use_real_wfn=use_real_wfn, kp_range=kp_range, &
    1608           22 :                            kp_dist=kp_dist, sab_nl=sab_nl)
    1609           22 :       CPASSERT(ASSOCIATED(sab_nl))
    1610           22 :       kplocal = kp_range(2) - kp_range(1) + 1
    1611           46 :       kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
    1612              : 
    1613              :       ! fm pools to be used within a kpoint group
    1614           22 :       CALL get_kpoint_info(kpoints, mpools=mpools)
    1615           22 :       CALL mpools_get(mpools, ao_ao_fm_pool=ao_ao_fm_pool)
    1616              : 
    1617           22 :       CALL fm_pool_create_fm(ao_ao_fm_pool, fmlocal)
    1618           22 :       CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
    1619              : 
    1620           22 :       IF (use_real_wfn) THEN
    1621            0 :          CALL cp_fm_create(rksmat, matrix_struct)
    1622            0 :          CALL cp_fm_create(rsmat, matrix_struct)
    1623              :       ELSE
    1624           22 :          CALL cp_cfm_create(cksmat, matrix_struct)
    1625           22 :          CALL cp_cfm_create(csmat, matrix_struct)
    1626           22 :          CALL cp_cfm_create(cwork, matrix_struct)
    1627           22 :          kp => kpoints%kp_env(1)%kpoint_env
    1628           22 :          mo_struct => kp%mos(1)%cmo_coeff%matrix_struct
    1629           22 :          CALL cp_cfm_create(cmos, mo_struct)
    1630              :       END IF
    1631              : 
    1632           22 :       nspin = SIZE(matrix_ks, 1)
    1633           22 :       CALL kpoint_operator_context_create(op_ctx, kpoints, fmwork(1), nspin)
    1634           22 :       CALL kpoint_operator_prepare(op_ctx, matrix_ks, kpoint_slot_ks)
    1635           22 :       CALL kpoint_operator_prepare(op_ctx, matrix_s, kpoint_slot_s, matrix_row=kpoint_spin_free)
    1636           94 :       DO ikp = 1, kpmax
    1637          166 :          DO ispin = 1, nspin
    1638              :             CALL kpoint_operator_start(op_ctx, ikp, ispin, matrix_ks, kpoint_slot_ks, &
    1639           72 :                                        use_grid=.FALSE., matrix_row=ispin)
    1640              :             CALL kpoint_operator_start(op_ctx, ikp, ispin, matrix_s, kpoint_slot_s, &
    1641          144 :                                        use_grid=.FALSE., matrix_row=kpoint_spin_free)
    1642              :          END DO
    1643              :       END DO
    1644              : 
    1645              :       ! Finish communication then diagonalise in each group
    1646           94 :       DO ikp = 1, kpmax
    1647          166 :          DO ispin = 1, nspin
    1648           72 :             IF (use_real_wfn) THEN
    1649            0 :                CALL kpoint_operator_finish(op_ctx, ikp, ispin, kpoint_slot_ks, fm_re=rksmat)
    1650            0 :                CALL kpoint_operator_finish(op_ctx, ikp, ispin, kpoint_slot_s, fm_re=rsmat)
    1651              :             ELSE
    1652           72 :                CALL kpoint_operator_finish(op_ctx, ikp, ispin, kpoint_slot_ks, cksmat)
    1653           72 :                CALL kpoint_operator_finish(op_ctx, ikp, ispin, kpoint_slot_s, csmat)
    1654              :             END IF
    1655              : 
    1656              :             ! Each kpoint group has now information on a kpoint to be diagonalized
    1657              :             ! General eigensolver Hermite or Symmetric
    1658           72 :             IF (ikp > kplocal) CYCLE
    1659           72 :             kp => kpoints%kp_env(ikp)%kpoint_env
    1660          144 :             IF (use_real_wfn) THEN
    1661            0 :                CALL get_mo_set(kp%mos(ispin), mo_coeff=mo_coeff, eigenvalues=eigenvalues)
    1662            0 :                CALL cp_fm_geeig(rksmat, rsmat, mo_coeff, eigenvalues, fmlocal)
    1663              :             ELSE
    1664           72 :                CALL get_mo_set(kp%mos(ispin), eigenvalues=eigenvalues)
    1665           72 :                CALL cp_cfm_geeig(cksmat, csmat, cmos, eigenvalues, cwork)
    1666           72 :                CALL cp_cfm_to_cfm(cmos, kp%mos(ispin)%cmo_coeff)
    1667              :             END IF
    1668              :          END DO
    1669              :       END DO
    1670              : 
    1671           22 :       CALL kpoint_operator_context_release(op_ctx)
    1672              : 
    1673           22 :       IF (use_real_wfn) THEN
    1674            0 :          CALL cp_fm_release(rksmat)
    1675            0 :          CALL cp_fm_release(rsmat)
    1676              :       ELSE
    1677           22 :          CALL cp_cfm_release(cksmat)
    1678           22 :          CALL cp_cfm_release(csmat)
    1679           22 :          CALL cp_cfm_release(cwork)
    1680           22 :          CALL cp_cfm_release(cmos)
    1681              :       END IF
    1682           22 :       CALL fm_pool_give_back_fm(ao_ao_fm_pool, fmlocal)
    1683              : 
    1684           22 :       CALL timestop(handle)
    1685              : 
    1686           44 :    END SUBROUTINE diag_kp_basic
    1687              : 
    1688              : ! **************************************************************************************************
    1689              : !> \brief inner loop within MOS subspace, to refine occupation and density,
    1690              : !>        before next diagonalization of the Hamiltonian
    1691              : !> \param qs_env ...
    1692              : !> \param scf_env ...
    1693              : !> \param subspace_env ...
    1694              : !> \param mos ...
    1695              : !> \param rho ...
    1696              : !> \param ks_env ...
    1697              : !> \param scf_section ...
    1698              : !> \param scf_control ...
    1699              : !> \par History
    1700              : !>      09.2009 created [MI]
    1701              : !> \note  it is assumed that when diagonalization is used, also some mixing procedure is active
    1702              : ! **************************************************************************************************
    1703           10 :    SUBROUTINE do_scf_diag_subspace(qs_env, scf_env, subspace_env, mos, rho, &
    1704              :                                    ks_env, scf_section, scf_control)
    1705              : 
    1706              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1707              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1708              :       TYPE(subspace_env_type), POINTER                   :: subspace_env
    1709              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
    1710              :       TYPE(qs_rho_type), POINTER                         :: rho
    1711              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    1712              :       TYPE(section_vals_type), POINTER                   :: scf_section
    1713              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1714              : 
    1715              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'do_scf_diag_subspace'
    1716              :       REAL(KIND=dp), PARAMETER                           :: rone = 1.0_dp, rzero = 0.0_dp
    1717              : 
    1718              :       INTEGER                                            :: handle, i, iloop, ispin, nao, nmo, &
    1719              :                                                             nspin, output_unit
    1720              :       LOGICAL                                            :: converged
    1721              :       REAL(dp)                                           :: ene_diff, ene_old, iter_delta, max_val, &
    1722              :                                                             sum_band, sum_val, t1, t2
    1723           10 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues, mo_occupations
    1724           10 :       TYPE(cp_1d_r_p_type), ALLOCATABLE, DIMENSION(:)    :: eval_first, occ_first
    1725              :       TYPE(cp_fm_type)                                   :: work
    1726              :       TYPE(cp_fm_type), POINTER                          :: c0, chc, evec, mo_coeff
    1727              :       TYPE(cp_logger_type), POINTER                      :: logger
    1728           10 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s, rho_ao
    1729           10 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
    1730              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1731              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1732              :       TYPE(qs_energy_type), POINTER                      :: energy
    1733           10 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho_atom
    1734              : 
    1735           10 :       CALL timeset(routineN, handle)
    1736           10 :       NULLIFY (c0, chc, energy, evec, matrix_ks, mo_coeff, mo_eigenvalues, &
    1737           10 :                mo_occupations, dft_control, rho_ao, rho_ao_kp)
    1738              : 
    1739           10 :       logger => cp_get_default_logger()
    1740              :       output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DIAG_SUB_SCF", &
    1741           10 :                                          extension=".scfLog")
    1742              : 
    1743              :       !Extra loop keeping mos unchanged and refining the subspace occupation
    1744           10 :       nspin = SIZE(mos)
    1745           10 :       CALL qs_rho_get(rho, rho_ao=rho_ao, rho_ao_kp=rho_ao_kp)
    1746              : 
    1747           40 :       ALLOCATE (eval_first(nspin))
    1748           40 :       ALLOCATE (occ_first(nspin))
    1749           20 :       DO ispin = 1, nspin
    1750              :          CALL get_mo_set(mo_set=mos(ispin), &
    1751              :                          nmo=nmo, &
    1752              :                          eigenvalues=mo_eigenvalues, &
    1753           10 :                          occupation_numbers=mo_occupations)
    1754           30 :          ALLOCATE (eval_first(ispin)%array(nmo))
    1755           20 :          ALLOCATE (occ_first(ispin)%array(nmo))
    1756           50 :          eval_first(ispin)%array(1:nmo) = mo_eigenvalues(1:nmo)
    1757           70 :          occ_first(ispin)%array(1:nmo) = mo_occupations(1:nmo)
    1758              :       END DO
    1759              : 
    1760           20 :       DO ispin = 1, nspin
    1761              :          ! does not yet handle k-points
    1762           10 :          CALL dbcsr_copy(subspace_env%p_matrix_store(ispin)%matrix, rho_ao(ispin)%matrix)
    1763           20 :          CALL dbcsr_copy(rho_ao(ispin)%matrix, scf_env%p_mix_new(ispin, 1)%matrix)
    1764              :       END DO
    1765              : 
    1766           10 :       subspace_env%p_matrix_mix => scf_env%p_mix_new
    1767              : 
    1768           10 :       NULLIFY (matrix_ks, energy, para_env, matrix_s)
    1769              :       CALL get_qs_env(qs_env, &
    1770              :                       matrix_ks=matrix_ks, &
    1771              :                       energy=energy, &
    1772              :                       matrix_s=matrix_s, &
    1773              :                       para_env=para_env, &
    1774           10 :                       dft_control=dft_control)
    1775              : 
    1776              :       ! mixing storage allocation
    1777           10 :       IF (subspace_env%mixing_method >= gspace_mixing_nr) THEN
    1778              :          CALL mixing_allocate(qs_env, subspace_env%mixing_method, scf_env%p_mix_new, &
    1779            0 :                               scf_env%p_delta, nspin, subspace_env%mixing_store)
    1780            0 :          IF (dft_control%qs_control%gapw) THEN
    1781            0 :             CALL get_qs_env(qs_env=qs_env, rho_atom_set=rho_atom)
    1782              :             CALL mixing_init(subspace_env%mixing_method, rho, subspace_env%mixing_store, &
    1783            0 :                              para_env, rho_atom=rho_atom)
    1784            0 :          ELSE IF (dft_control%qs_control%dftb .OR. dft_control%qs_control%xtb) THEN
    1785            0 :             CALL charge_mixing_init(subspace_env%mixing_store)
    1786            0 :          ELSE IF (dft_control%qs_control%semi_empirical) THEN
    1787            0 :             CPABORT('SE Code not possible')
    1788              :          ELSE
    1789            0 :             CALL mixing_init(subspace_env%mixing_method, rho, subspace_env%mixing_store, para_env)
    1790              :          END IF
    1791              :       END IF
    1792              : 
    1793           10 :       ene_old = 0.0_dp
    1794              :       ene_diff = 0.0_dp
    1795           10 :       IF (output_unit > 0) THEN
    1796            0 :          WRITE (output_unit, "(/T19,A)") '<<<<<<<<<   SUBSPACE ROTATION    <<<<<<<<<<'
    1797              :          WRITE (output_unit, "(T4,A,T13,A,T21,A,T38,A,T51,A,T65,A/,T4,A)") &
    1798            0 :             "In-step", "Time", "Convergence", "Band ene.", "Total ene.", "Energy diff.", REPEAT("-", 74)
    1799              :       END IF
    1800              : 
    1801              :       ! recalculate density matrix here
    1802              : 
    1803              :       ! update of density
    1804           10 :       CALL qs_rho_update_rho(rho, qs_env=qs_env)
    1805              : 
    1806           22 :       DO iloop = 1, subspace_env%max_iter
    1807           20 :          t1 = m_walltime()
    1808           20 :          converged = .FALSE.
    1809           20 :          ene_old = energy%total
    1810              : 
    1811           20 :          CALL qs_ks_did_change(ks_env, rho_changed=.TRUE.)
    1812              :          CALL qs_ks_update_qs_env(qs_env, calculate_forces=.FALSE., &
    1813           20 :                                   just_energy=.FALSE., print_active=.FALSE.)
    1814              : 
    1815           20 :          max_val = 0.0_dp
    1816           20 :          sum_val = 0.0_dp
    1817           20 :          sum_band = 0.0_dp
    1818           40 :          DO ispin = 1, SIZE(matrix_ks)
    1819              :             CALL get_mo_set(mo_set=mos(ispin), &
    1820              :                             nao=nao, &
    1821              :                             nmo=nmo, &
    1822              :                             eigenvalues=mo_eigenvalues, &
    1823              :                             occupation_numbers=mo_occupations, &
    1824           20 :                             mo_coeff=mo_coeff)
    1825              : 
    1826              :             !compute C'HC
    1827           20 :             chc => subspace_env%chc_mat(ispin)
    1828           20 :             evec => subspace_env%c_vec(ispin)
    1829           20 :             c0 => subspace_env%c0(ispin)
    1830           20 :             CALL cp_fm_to_fm(mo_coeff, c0)
    1831           20 :             CALL cp_fm_create(work, c0%matrix_struct)
    1832           20 :             CALL cp_dbcsr_sm_fm_multiply(matrix_ks(ispin)%matrix, c0, work, nmo)
    1833           20 :             CALL parallel_gemm('T', 'N', nmo, nmo, nao, rone, c0, work, rzero, chc)
    1834           20 :             CALL cp_fm_release(work)
    1835              :             !diagonalize C'HC
    1836           20 :             CALL choose_eigv_solver(chc, evec, mo_eigenvalues)
    1837              : 
    1838              :             !rotate the mos by the eigenvectors of C'HC
    1839           20 :             CALL parallel_gemm('N', 'N', nao, nmo, nmo, rone, c0, evec, rzero, mo_coeff)
    1840              : 
    1841           20 :             IF (.NOT. scf_control%gce%do_gce) THEN
    1842              :                CALL set_mo_occupation(mo_set=mos(ispin), &
    1843           20 :                                       smear=scf_control%smear)
    1844              :             ELSE
    1845              :                CALL set_mo_occupation(mo_set=mos(ispin), &
    1846              :                                       smear=scf_control%smear, &
    1847            0 :                                       gce=scf_control%gce)
    1848              :             END IF
    1849              : 
    1850              :             ! does not yet handle k-points
    1851              :             CALL calculate_density_matrix(mos(ispin), &
    1852           20 :                                           subspace_env%p_matrix_mix(ispin, 1)%matrix)
    1853              : 
    1854          160 :             DO i = 1, nmo
    1855          100 :                sum_band = sum_band + mo_eigenvalues(i)*mo_occupations(i)
    1856              :             END DO
    1857              : 
    1858              :             !check for self consistency
    1859              :          END DO
    1860              : 
    1861           20 :          IF (subspace_env%mixing_method == direct_mixing_nr) THEN
    1862              :             CALL scf_env_density_mixing(subspace_env%p_matrix_mix, &
    1863           20 :                                         scf_env%mixing_store, rho_ao_kp, para_env, iter_delta, iloop)
    1864              :          ELSE
    1865              :             CALL self_consistency_check(rho_ao_kp, scf_env%p_delta, para_env, &
    1866            0 :                                         subspace_env%p_matrix_mix, delta=iter_delta)
    1867              :          END IF
    1868              : 
    1869           40 :          DO ispin = 1, nspin
    1870              :             ! does not yet handle k-points
    1871           40 :             CALL dbcsr_copy(rho_ao(ispin)%matrix, subspace_env%p_matrix_mix(ispin, 1)%matrix)
    1872              :          END DO
    1873              :          ! update of density
    1874           20 :          CALL qs_rho_update_rho(rho, qs_env=qs_env)
    1875              :          ! Mixing in reciprocal space
    1876           20 :          IF (subspace_env%mixing_method >= gspace_mixing_nr) THEN
    1877              :             CALL gspace_mixing(qs_env, scf_env%mixing_method, subspace_env%mixing_store, &
    1878            0 :                                rho, para_env, scf_env%iter_count)
    1879              :          END IF
    1880              : 
    1881           20 :          ene_diff = energy%total - ene_old
    1882              :          converged = (ABS(ene_diff) < subspace_env%eps_ene .AND. &
    1883           20 :                       iter_delta < subspace_env%eps_adapt*scf_env%iter_delta)
    1884           20 :          t2 = m_walltime()
    1885           20 :          IF (output_unit > 0) THEN
    1886              :             WRITE (output_unit, "(T4,I5,T11,F8.3,T18,E14.4,T34,F12.5,T46,F16.8,T62,E14.4)") &
    1887            0 :                iloop, t2 - t1, iter_delta, sum_band, energy%total, ene_diff
    1888            0 :             CALL m_flush(output_unit)
    1889              :          END IF
    1890           22 :          IF (converged) THEN
    1891            8 :             IF (output_unit > 0) WRITE (output_unit, "(T10,A,I6,A,/)") &
    1892            0 :                " Reached convergence in ", iloop, " iterations "
    1893              :             EXIT
    1894              :          END IF
    1895              : 
    1896              :       END DO ! iloop
    1897              : 
    1898           10 :       NULLIFY (subspace_env%p_matrix_mix)
    1899           20 :       DO ispin = 1, nspin
    1900              :          ! does not yet handle k-points
    1901           10 :          CALL dbcsr_copy(scf_env%p_mix_new(ispin, 1)%matrix, rho_ao(ispin)%matrix)
    1902           10 :          CALL dbcsr_copy(rho_ao(ispin)%matrix, subspace_env%p_matrix_store(ispin)%matrix)
    1903              : 
    1904           20 :          DEALLOCATE (eval_first(ispin)%array, occ_first(ispin)%array)
    1905              :       END DO
    1906           10 :       DEALLOCATE (eval_first, occ_first)
    1907              : 
    1908           10 :       CALL timestop(handle)
    1909              : 
    1910           10 :    END SUBROUTINE do_scf_diag_subspace
    1911              : 
    1912              : ! **************************************************************************************************
    1913              : !> \brief ...
    1914              : !> \param subspace_env ...
    1915              : !> \param qs_env ...
    1916              : !> \param mos ...
    1917              : ! **************************************************************************************************
    1918            2 :    SUBROUTINE diag_subspace_allocate(subspace_env, qs_env, mos)
    1919              : 
    1920              :       TYPE(subspace_env_type), POINTER                   :: subspace_env
    1921              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1922              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos
    1923              : 
    1924              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'diag_subspace_allocate'
    1925              : 
    1926              :       INTEGER                                            :: handle, i, ispin, nmo, nspin
    1927              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
    1928              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1929            2 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    1930              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1931            2 :          POINTER                                         :: sab_orb
    1932              : 
    1933            2 :       CALL timeset(routineN, handle)
    1934              : 
    1935            2 :       NULLIFY (sab_orb, matrix_s)
    1936              :       CALL get_qs_env(qs_env=qs_env, sab_orb=sab_orb, &
    1937            2 :                       matrix_s=matrix_s)
    1938              : 
    1939            2 :       nspin = SIZE(mos)
    1940              : !   *** allocate p_atrix_store ***
    1941            2 :       IF (.NOT. ASSOCIATED(subspace_env%p_matrix_store)) THEN
    1942            2 :          CALL dbcsr_allocate_matrix_set(subspace_env%p_matrix_store, nspin)
    1943              : 
    1944            4 :          DO i = 1, nspin
    1945            2 :             ALLOCATE (subspace_env%p_matrix_store(i)%matrix)
    1946              :             CALL dbcsr_create(matrix=subspace_env%p_matrix_store(i)%matrix, template=matrix_s(1)%matrix, &
    1947            2 :                               name="DENSITY_STORE", matrix_type=dbcsr_type_symmetric)
    1948              :             CALL cp_dbcsr_alloc_block_from_nbl(subspace_env%p_matrix_store(i)%matrix, &
    1949            2 :                                                sab_orb)
    1950            4 :             CALL dbcsr_set(subspace_env%p_matrix_store(i)%matrix, 0.0_dp)
    1951              :          END DO
    1952              : 
    1953              :       END IF
    1954              : 
    1955            8 :       ALLOCATE (subspace_env%chc_mat(nspin))
    1956            6 :       ALLOCATE (subspace_env%c_vec(nspin))
    1957            6 :       ALLOCATE (subspace_env%c0(nspin))
    1958              : 
    1959            4 :       DO ispin = 1, nspin
    1960            2 :          CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nmo=nmo)
    1961            2 :          CALL cp_fm_create(subspace_env%c0(ispin), mo_coeff%matrix_struct)
    1962            2 :          NULLIFY (fm_struct_tmp)
    1963              :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nmo, ncol_global=nmo, &
    1964              :                                   para_env=mo_coeff%matrix_struct%para_env, &
    1965            2 :                                   context=mo_coeff%matrix_struct%context)
    1966            2 :          CALL cp_fm_create(subspace_env%chc_mat(ispin), fm_struct_tmp, "chc")
    1967            2 :          CALL cp_fm_create(subspace_env%c_vec(ispin), fm_struct_tmp, "vec")
    1968            6 :          CALL cp_fm_struct_release(fm_struct_tmp)
    1969              :       END DO
    1970              : 
    1971            2 :       CALL timestop(handle)
    1972              : 
    1973            2 :    END SUBROUTINE diag_subspace_allocate
    1974              : 
    1975              : ! **************************************************************************************************
    1976              : !> \brief the inner loop of scf, specific to diagonalization without S matrix
    1977              : !>       basically, in goes the ks matrix out goes a new p matrix
    1978              : !> \param scf_env ...
    1979              : !> \param mos ...
    1980              : !> \param matrix_ks ...
    1981              : !> \param scf_control ...
    1982              : !> \param scf_section ...
    1983              : !> \param diis_step ...
    1984              : !> \par History
    1985              : !>      03.2006 created [Joost VandeVondele]
    1986              : ! **************************************************************************************************
    1987        17876 :    SUBROUTINE do_special_diag(scf_env, mos, matrix_ks, scf_control, &
    1988              :                               scf_section, diis_step)
    1989              : 
    1990              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1991              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
    1992              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks
    1993              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1994              :       TYPE(section_vals_type), POINTER                   :: scf_section
    1995              :       LOGICAL, INTENT(INOUT)                             :: diis_step
    1996              : 
    1997              :       INTEGER                                            :: ispin, nspin
    1998              :       LOGICAL                                            :: do_level_shift, use_jacobi
    1999              :       REAL(KIND=dp)                                      :: diis_error
    2000              : 
    2001        17876 :       nspin = SIZE(matrix_ks)
    2002              : 
    2003        36518 :       DO ispin = 1, nspin
    2004              :          CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, scf_env%scf_work1(ispin), &
    2005        36518 :                                scf_env%fm_copy_plan(ispin), check_plan=.TRUE.)
    2006              :       END DO
    2007        17876 :       IF (scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis) THEN
    2008              :          CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
    2009              :                              scf_env%scf_work2, scf_env%iter_delta, diis_error, diis_step, &
    2010              :                              scf_control%eps_diis, scf_control%nmixing, &
    2011        15282 :                              scf_section=scf_section)
    2012              :       ELSE
    2013         2594 :          diis_step = .FALSE.
    2014              :       END IF
    2015              : 
    2016        17876 :       IF ((scf_env%iter_count > 1) .AND. (scf_env%iter_delta < scf_control%diagonalization%eps_jacobi)) THEN
    2017           18 :          use_jacobi = .TRUE.
    2018              :       ELSE
    2019        17858 :          use_jacobi = .FALSE.
    2020              :       END IF
    2021              : 
    2022              :       do_level_shift = ((scf_control%level_shift /= 0.0_dp) .AND. &
    2023        17876 :                         ((scf_control%density_guess == core_guess) .OR. (scf_env%iter_count > 1)))
    2024        17876 :       IF (diis_step) THEN
    2025        11870 :          scf_env%iter_param = diis_error
    2026        11870 :          IF (use_jacobi) THEN
    2027           18 :             scf_env%iter_method = "DIIS/Jacobi"
    2028              :          ELSE
    2029        11852 :             scf_env%iter_method = "DIIS/Diag."
    2030              :          END IF
    2031              :       ELSE
    2032         6006 :          IF (scf_env%mixing_method == 1) THEN
    2033         6006 :             scf_env%iter_param = scf_env%p_mix_alpha
    2034         6006 :             IF (use_jacobi) THEN
    2035            0 :                scf_env%iter_method = "P_Mix/Jacobi"
    2036              :             ELSE
    2037         6006 :                scf_env%iter_method = "P_Mix/Diag."
    2038              :             END IF
    2039            0 :          ELSE IF (scf_env%mixing_method > 1) THEN
    2040            0 :             scf_env%iter_param = scf_env%mixing_store%alpha
    2041            0 :             IF (use_jacobi) THEN
    2042            0 :                scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Jacobi"
    2043              :             ELSE
    2044            0 :                scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
    2045              :             END IF
    2046              :          END IF
    2047              :       END IF
    2048        17876 :       scf_env%iter_delta = 0.0_dp
    2049              : 
    2050        36518 :       DO ispin = 1, nspin
    2051              :          CALL eigensolver_simple(matrix_ks=scf_env%scf_work1(ispin), &
    2052              :                                  mo_set=mos(ispin), &
    2053              :                                  work=scf_env%scf_work2, &
    2054              :                                  do_level_shift=do_level_shift, &
    2055              :                                  level_shift=scf_control%level_shift, &
    2056              :                                  use_jacobi=use_jacobi, &
    2057        36518 :                                  jacobi_threshold=scf_control%diagonalization%jacobi_threshold)
    2058              :       END DO
    2059              : 
    2060        17876 :       IF (.NOT. scf_control%gce%do_gce) THEN
    2061              :          CALL set_mo_occupation(mo_array=mos, &
    2062        17876 :                                 smear=scf_control%smear)
    2063              :       ELSE
    2064              :          CALL set_mo_occupation(mo_array=mos, &
    2065              :                                 smear=scf_control%smear, &
    2066            0 :                                 gce=scf_control%gce)
    2067              :       END IF
    2068              : 
    2069        36518 :       DO ispin = 1, nspin
    2070              :          ! does not yet handle k-points
    2071              :          CALL calculate_density_matrix(mos(ispin), &
    2072        36518 :                                        scf_env%p_mix_new(ispin, 1)%matrix)
    2073              :       END DO
    2074              : 
    2075        17876 :    END SUBROUTINE do_special_diag
    2076              : 
    2077              : ! **************************************************************************************************
    2078              : !> \brief the inner loop of scf, specific to iterative diagonalization using OT
    2079              : !>        with S matrix; basically, in goes the ks matrix out goes a new p matrix
    2080              : !> \param scf_env ...
    2081              : !> \param mos ...
    2082              : !> \param matrix_ks ...
    2083              : !> \param matrix_s ...
    2084              : !> \param scf_control ...
    2085              : !> \param scf_section ...
    2086              : !> \param diis_step ...
    2087              : !> \par History
    2088              : !>      10.2008 created [JGH]
    2089              : ! **************************************************************************************************
    2090          202 :    SUBROUTINE do_ot_diag(scf_env, mos, matrix_ks, matrix_s, &
    2091              :                          scf_control, scf_section, diis_step)
    2092              : 
    2093              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2094              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
    2095              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
    2096              :       TYPE(scf_control_type), POINTER                    :: scf_control
    2097              :       TYPE(section_vals_type), POINTER                   :: scf_section
    2098              :       LOGICAL, INTENT(INOUT)                             :: diis_step
    2099              : 
    2100              :       INTEGER                                            :: homo, ispin, nmo, nspin
    2101              :       REAL(KIND=dp)                                      :: diis_error, eps_iter
    2102          202 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues
    2103              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    2104              : 
    2105          202 :       NULLIFY (eigenvalues)
    2106              : 
    2107          202 :       nspin = SIZE(matrix_ks)
    2108              : 
    2109          448 :       DO ispin = 1, nspin
    2110              :          CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, &
    2111          448 :                                scf_env%scf_work1(ispin))
    2112              :       END DO
    2113              : 
    2114          202 :       IF ((scf_env%iter_count > 1) .AND. (.NOT. scf_env%skip_diis)) THEN
    2115              :          CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
    2116              :                              scf_env%scf_work2, scf_env%iter_delta, diis_error, diis_step, &
    2117              :                              scf_control%eps_diis, scf_control%nmixing, &
    2118              :                              s_matrix=matrix_s, &
    2119          180 :                              scf_section=scf_section)
    2120              :       ELSE
    2121           22 :          diis_step = .FALSE.
    2122              :       END IF
    2123              : 
    2124          202 :       eps_iter = scf_control%diagonalization%eps_iter
    2125          202 :       IF (diis_step) THEN
    2126          130 :          scf_env%iter_param = diis_error
    2127          130 :          scf_env%iter_method = "DIIS/OTdiag"
    2128          274 :          DO ispin = 1, nspin
    2129              :             CALL copy_fm_to_dbcsr(scf_env%scf_work1(ispin), &
    2130          274 :                                   matrix_ks(ispin)%matrix, keep_sparsity=.TRUE.)
    2131              :          END DO
    2132          130 :          eps_iter = MAX(eps_iter, scf_control%diagonalization%eps_adapt*diis_error)
    2133              :       ELSE
    2134           72 :          IF (scf_env%mixing_method == 1) THEN
    2135           72 :             scf_env%iter_param = scf_env%p_mix_alpha
    2136           72 :             scf_env%iter_method = "P_Mix/OTdiag."
    2137            0 :          ELSE IF (scf_env%mixing_method > 1) THEN
    2138            0 :             scf_env%iter_param = scf_env%mixing_store%alpha
    2139            0 :             scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/OTdiag."
    2140              :          END IF
    2141              :       END IF
    2142              : 
    2143          202 :       scf_env%iter_delta = 0.0_dp
    2144              : 
    2145          448 :       DO ispin = 1, nspin
    2146              :          CALL get_mo_set(mos(ispin), &
    2147              :                          mo_coeff=mo_coeff, &
    2148              :                          eigenvalues=eigenvalues, &
    2149              :                          nmo=nmo, &
    2150          246 :                          homo=homo)
    2151              :          CALL ot_eigensolver(matrix_h=matrix_ks(ispin)%matrix, &
    2152              :                              matrix_s=matrix_s(1)%matrix, &
    2153              :                              matrix_c_fm=mo_coeff, &
    2154              :                              preconditioner=scf_env%ot_preconditioner( &
    2155              :                              MIN(ispin, SIZE(scf_env%ot_preconditioner)))%preconditioner, &
    2156              :                              eps_gradient=eps_iter, &
    2157              :                              iter_max=scf_control%diagonalization%max_iter, &
    2158              :                              silent=.TRUE., &
    2159          246 :                              ot_settings=scf_control%diagonalization%ot_settings)
    2160              :          CALL calculate_subspace_eigenvalues(mo_coeff, matrix_ks(ispin)%matrix, &
    2161              :                                              evals_arg=eigenvalues, &
    2162          246 :                                              do_rotation=.TRUE.)
    2163              :          CALL copy_fm_to_dbcsr(mos(ispin)%mo_coeff, &
    2164          694 :                                mos(ispin)%mo_coeff_b)
    2165              :          !fm->dbcsr
    2166              :       END DO
    2167              : 
    2168              :       CALL set_mo_occupation(mo_array=mos, &
    2169          202 :                              smear=scf_control%smear)
    2170              : 
    2171          448 :       DO ispin = 1, nspin
    2172              :          ! does not yet handle k-points
    2173              :          CALL calculate_density_matrix(mos(ispin), &
    2174          448 :                                        scf_env%p_mix_new(ispin, 1)%matrix)
    2175              :       END DO
    2176              : 
    2177          202 :    END SUBROUTINE do_ot_diag
    2178              : 
    2179              : ! **************************************************************************************************
    2180              : !> \brief fixed-H OT diagonalization for real or complex K-point channels
    2181              : !> \param matrix_ks real-space Kohn-Sham matrices
    2182              : !> \param matrix_s real-space overlap matrices
    2183              : !> \param matrix_t ...
    2184              : !> \param kpoints K-point environment
    2185              : !> \param scf_env SCF environment
    2186              : !> \param scf_control SCF controls
    2187              : !> \param diis_step set false; density mixing remains the outer accelerator
    2188              : !> \param added_mos_auto_grow request a larger adaptive virtual-space buffer
    2189              : ! **************************************************************************************************
    2190           94 :    SUBROUTINE do_ot_diag_kp(matrix_ks, matrix_s, matrix_t, kpoints, scf_env, scf_control, &
    2191              :                             diis_step, added_mos_auto_grow)
    2192              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks, matrix_s, matrix_t
    2193              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2194              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2195              :       TYPE(scf_control_type), POINTER                    :: scf_control
    2196              :       LOGICAL, INTENT(INOUT)                             :: diis_step
    2197              :       LOGICAL, INTENT(OUT)                               :: added_mos_auto_grow
    2198              : 
    2199              :       INTEGER                                            :: ikp, ispin, ks_spin, nspin
    2200              :       LOGICAL                                            :: store_kinetic, use_real_wfn
    2201              :       REAL(KIND=dp)                                      :: eps_iter
    2202           94 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues
    2203              :       TYPE(cp_cfm_type)                                  :: cmo_work
    2204              :       TYPE(cp_fm_type)                                   :: coeff_im_work
    2205           94 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
    2206              :       TYPE(cp_fm_type), POINTER                          :: coeff_re
    2207              :       TYPE(dbcsr_type), POINTER                          :: matrix_h_im, matrix_h_re, matrix_s_im, &
    2208              :                                                             matrix_s_re, matrix_t_im, matrix_t_re
    2209              :       TYPE(kpoint_env_type), POINTER                     :: kp
    2210           94 :       TYPE(kpoint_operator_context_type)                 :: op_ctx
    2211              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2212           94 :          POINTER                                         :: sab_nl
    2213              : 
    2214           94 :       NULLIFY (coeff_re, eigenvalues, fmwork, kp, matrix_h_im, matrix_h_re, &
    2215           94 :                matrix_s_im, matrix_s_re, matrix_t_im, matrix_t_re, sab_nl)
    2216           94 :       added_mos_auto_grow = .FALSE.
    2217           94 :       diis_step = .FALSE.
    2218           94 :       eps_iter = scf_control%diagonalization%eps_iter
    2219           94 :       nspin = SIZE(matrix_ks, 1)
    2220              :       store_kinetic = scf_control%diagonalization%ot_settings%preconditioner_type == &
    2221           94 :          ot_precond_full_kinetic
    2222           94 :       IF (store_kinetic) THEN
    2223            0 :          CPASSERT(ASSOCIATED(matrix_t))
    2224              :       END IF
    2225           94 :       CALL get_kpoint_info(kpoints, use_real_wfn=use_real_wfn, sab_nl=sab_nl)
    2226           94 :       CPASSERT(ASSOCIATED(sab_nl))
    2227              : 
    2228              :       ! A full diagonalization supplies an orthonormal start after initialization or an
    2229              :       ! ADDED_MOS AUTO resize. Subsequent SCF steps only redistribute H(k) and S(k).
    2230           94 :       IF (scf_env%iter_count <= 1) THEN
    2231              :          CALL do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, &
    2232           10 :                                  .FALSE., diis_step)
    2233              :       END IF
    2234           94 :       CALL kpoint_operator_context_create(op_ctx, kpoints, scf_env%scf_work1(1), nspin)
    2235           94 :       IF (store_kinetic) THEN
    2236            0 :          CALL kpoint_operator_store(op_ctx, matrix_ks, matrix_s, matrix_t)
    2237              :       ELSE
    2238           94 :          CALL kpoint_operator_store(op_ctx, matrix_ks, matrix_s)
    2239              :       END IF
    2240           94 :       CALL kpoint_operator_context_release(op_ctx)
    2241              : 
    2242           94 :       scf_env%iter_delta = 0.0_dp
    2243          266 :       DO ikp = 1, SIZE(kpoints%kp_env)
    2244          172 :          kp => kpoints%kp_env(ikp)%kpoint_env
    2245          172 :          CPASSERT(ASSOCIATED(kp%ot_hmat) .AND. ASSOCIATED(kp%ot_smat))
    2246          172 :          IF (SIZE(kp%ot_smat) >= 2) THEN
    2247              :             CALL kpoint_operator_get_local(matrix_s, kpoints, kp, 1, &
    2248              :                                            kp%ot_smat(1), kp%ot_smat(2), &
    2249          172 :                                            matrix_s_re, matrix_s_im)
    2250              :          ELSE
    2251              :             CALL kpoint_operator_get_local(matrix_s, kpoints, kp, 1, &
    2252              :                                            kp%ot_smat(1), kp%ot_smat(1), &
    2253            0 :                                            matrix_s_re, matrix_s_im)
    2254            0 :             CALL dbcsr_set(matrix_s_im, 0.0_dp)
    2255              :          END IF
    2256          172 :          IF (store_kinetic) THEN
    2257            0 :             CPASSERT(ASSOCIATED(kp%ot_tmat))
    2258            0 :             IF (SIZE(kp%ot_tmat) >= 2) THEN
    2259              :                CALL kpoint_operator_get_local(matrix_t, kpoints, kp, 1, &
    2260              :                                               kp%ot_tmat(1), kp%ot_tmat(2), &
    2261            0 :                                               matrix_t_re, matrix_t_im)
    2262              :             ELSE
    2263              :                CALL kpoint_operator_get_local(matrix_t, kpoints, kp, 1, &
    2264              :                                               kp%ot_tmat(1), kp%ot_tmat(1), &
    2265            0 :                                               matrix_t_re, matrix_t_im)
    2266            0 :                CALL dbcsr_set(matrix_t_im, 0.0_dp)
    2267              :             END IF
    2268              :          END IF
    2269          344 :          DO ispin = 1, nspin
    2270          172 :             ks_spin = MIN(ispin, SIZE(kp%ot_hmat, 2))
    2271          172 :             IF (SIZE(kp%ot_hmat, 1) >= 2) THEN
    2272              :                CALL kpoint_operator_get_local(matrix_ks, kpoints, kp, ks_spin, &
    2273              :                                               kp%ot_hmat(1, ks_spin), kp%ot_hmat(2, ks_spin), &
    2274          172 :                                               matrix_h_re, matrix_h_im)
    2275              :             ELSE
    2276              :                CALL kpoint_operator_get_local(matrix_ks, kpoints, kp, ks_spin, &
    2277              :                                               kp%ot_hmat(1, ks_spin), kp%ot_hmat(1, ks_spin), &
    2278            0 :                                               matrix_h_re, matrix_h_im)
    2279            0 :                CALL dbcsr_set(matrix_h_im, 0.0_dp)
    2280              :             END IF
    2281          172 :             CALL get_mo_set(kp%mos(ispin), eigenvalues=eigenvalues)
    2282          172 :             IF (use_real_wfn) THEN
    2283            0 :                CALL get_mo_set(kp%mos(ispin), mo_coeff=coeff_re)
    2284              :                CALL cp_fm_create(coeff_im_work, coeff_re%matrix_struct, &
    2285            0 :                                  name='real k-point OT imaginary work')
    2286            0 :                CALL cp_cfm_create(cmo_work, coeff_re%matrix_struct)
    2287            0 :                CALL cp_cfm_scale_and_add_fm(z_zero, cmo_work, z_one, coeff_re)
    2288              :                CALL ot_eigensolver_complex(matrix_h=matrix_h_re, matrix_h_im=matrix_h_im, &
    2289              :                                            matrix_s=matrix_s_re, matrix_s_im=matrix_s_im, &
    2290              :                                            matrix_c_cfm=cmo_work, &
    2291              :                                            eps_gradient=eps_iter, &
    2292              :                                            iter_max=scf_control%diagonalization%max_iter, &
    2293              :                                            eigenvalues=eigenvalues, silent=.TRUE., &
    2294              :                                            ot_settings=scf_control%diagonalization%ot_settings, &
    2295              :                                            matrix_t=matrix_t_re, matrix_t_im=matrix_t_im, &
    2296            0 :                                            mo_set=kp%mos(ispin))
    2297            0 :                CALL cp_cfm_to_fm(cmo_work, coeff_re, coeff_im_work)
    2298            0 :                CALL cp_cfm_release(cmo_work)
    2299            0 :                CALL cp_fm_release(coeff_im_work)
    2300              :             ELSE
    2301              :                CALL ot_eigensolver_complex(matrix_h=matrix_h_re, matrix_h_im=matrix_h_im, &
    2302              :                                            matrix_s=matrix_s_re, matrix_s_im=matrix_s_im, &
    2303              :                                            matrix_c_cfm=kp%mos(ispin)%cmo_coeff, &
    2304              :                                            eps_gradient=eps_iter, &
    2305              :                                            iter_max=scf_control%diagonalization%max_iter, &
    2306              :                                            eigenvalues=eigenvalues, silent=.TRUE., &
    2307              :                                            ot_settings=scf_control%diagonalization%ot_settings, &
    2308              :                                            matrix_t=matrix_t_re, matrix_t_im=matrix_t_im, &
    2309          172 :                                            mo_set=kp%mos(ispin))
    2310              :             END IF
    2311          172 :             CALL dbcsr_release_p(matrix_h_re)
    2312          344 :             CALL dbcsr_release_p(matrix_h_im)
    2313              :          END DO
    2314          172 :          CALL dbcsr_release_p(matrix_s_re)
    2315          172 :          CALL dbcsr_release_p(matrix_s_im)
    2316          172 :          IF (ASSOCIATED(matrix_t_re)) CALL dbcsr_release_p(matrix_t_re)
    2317          266 :          IF (ASSOCIATED(matrix_t_im)) CALL dbcsr_release_p(matrix_t_im)
    2318              :       END DO
    2319              : 
    2320           94 :       fmwork => scf_env%scf_work1
    2321           94 :       CALL kp_diag_exit_chain(kpoints, scf_env, scf_control, matrix_s, sab_nl, fmwork, added_mos_auto_grow)
    2322           94 :       IF (added_mos_auto_grow) RETURN
    2323           94 :       IF (scf_env%mixing_method == 0) THEN
    2324            0 :          scf_env%iter_method = 'NoMix/OTdiag.'
    2325           94 :       ELSE IF (scf_env%mixing_method == 1) THEN
    2326           60 :          scf_env%iter_param = scf_env%p_mix_alpha
    2327           60 :          scf_env%iter_method = 'P_Mix/OTdiag.'
    2328              :       ELSE
    2329           34 :          scf_env%iter_param = scf_env%mixing_store%alpha
    2330           34 :          scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//'/OTdiag.'
    2331              :       END IF
    2332          188 :    END SUBROUTINE do_ot_diag_kp
    2333              : 
    2334              : ! **************************************************************************************************
    2335              : !> \brief Solve a set restricted open Kohn-Sham (ROKS) equations based on the
    2336              : !>         alpha and beta Kohn-Sham matrices from unrestricted Kohn-Sham.
    2337              : !> \param scf_env ...
    2338              : !> \param mos ...
    2339              : !> \param matrix_ks ...
    2340              : !> \param matrix_s ...
    2341              : !> \param scf_control ...
    2342              : !> \param scf_section ...
    2343              : !> \param diis_step ...
    2344              : !> \param orthogonal_basis ...
    2345              : !> \par History
    2346              : !>      04.2006 created [MK]
    2347              : !>      Revised (01.05.06,MK)
    2348              : !> \note
    2349              : !>         this is only a high-spin ROKS.
    2350              : ! **************************************************************************************************
    2351         1160 :    SUBROUTINE do_roks_diag(scf_env, mos, matrix_ks, matrix_s, &
    2352              :                            scf_control, scf_section, diis_step, &
    2353              :                            orthogonal_basis)
    2354              : 
    2355              :       ! Literature: - C. C. J. Roothaan, Rev. Mod. Phys. 32, 179 (1960)
    2356              :       !             - M. F. Guest and V. R. Saunders, Mol. Phys. 28(3), 819 (1974)
    2357              :       !             - M. Filatov and S. Shaik, Chem. Phys. Lett. 288, 689 (1998)
    2358              : 
    2359              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2360              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos
    2361              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
    2362              :       TYPE(scf_control_type), POINTER                    :: scf_control
    2363              :       TYPE(section_vals_type), POINTER                   :: scf_section
    2364              :       LOGICAL, INTENT(INOUT)                             :: diis_step
    2365              :       LOGICAL, INTENT(IN)                                :: orthogonal_basis
    2366              : 
    2367              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'do_roks_diag'
    2368              : 
    2369              :       INTEGER                                            :: handle, homoa, homob, imo, nalpha, nao, &
    2370              :                                                             nbeta, nmo
    2371              :       REAL(KIND=dp)                                      :: diis_error, level_shift_loc
    2372         1160 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eiga, eigb, occa, occb
    2373              :       TYPE(cp_fm_type), POINTER                          :: ksa, ksb, mo2ao, moa, mob, ortho, work
    2374              : 
    2375              : ! -------------------------------------------------------------------------
    2376              : 
    2377         1160 :       CALL timeset(routineN, handle)
    2378              : 
    2379         1160 :       IF (scf_env%cholesky_method == cholesky_inverse) THEN
    2380            0 :          ortho => scf_env%ortho_m1
    2381              :       ELSE
    2382         1160 :          ortho => scf_env%ortho
    2383              :       END IF
    2384         1160 :       work => scf_env%scf_work2
    2385              : 
    2386         1160 :       ksa => scf_env%scf_work1(1)
    2387         1160 :       ksb => scf_env%scf_work1(2)
    2388              : 
    2389         1160 :       CALL copy_dbcsr_to_fm(matrix_ks(1)%matrix, ksa, scf_env%fm_copy_plan(1), check_plan=.TRUE.)
    2390         1160 :       CALL copy_dbcsr_to_fm(matrix_ks(2)%matrix, ksb, scf_env%fm_copy_plan(2), check_plan=.TRUE.)
    2391              : 
    2392              :       ! Get MO information
    2393              : 
    2394              :       CALL get_mo_set(mo_set=mos(1), &
    2395              :                       nao=nao, &
    2396              :                       nmo=nmo, &
    2397              :                       nelectron=nalpha, &
    2398              :                       homo=homoa, &
    2399              :                       eigenvalues=eiga, &
    2400              :                       occupation_numbers=occa, &
    2401         1160 :                       mo_coeff=moa)
    2402              : 
    2403              :       CALL get_mo_set(mo_set=mos(2), &
    2404              :                       nelectron=nbeta, &
    2405              :                       homo=homob, &
    2406              :                       eigenvalues=eigb, &
    2407              :                       occupation_numbers=occb, &
    2408         1160 :                       mo_coeff=mob)
    2409              : 
    2410              :       ! Define the amount of level-shifting
    2411              : 
    2412         1160 :       IF ((scf_control%level_shift /= 0.0_dp) .AND. &
    2413              :           ((scf_control%density_guess == core_guess) .OR. &
    2414              :            (scf_control%density_guess == restart_guess) .OR. &
    2415              :            (scf_env%iter_count > 1))) THEN
    2416           20 :          level_shift_loc = scf_control%level_shift
    2417              :       ELSE
    2418         1140 :          level_shift_loc = 0.0_dp
    2419              :       END IF
    2420              : 
    2421              :       IF ((scf_env%iter_count > 1) .OR. &
    2422         1160 :           (scf_control%density_guess == core_guess) .OR. &
    2423              :           (scf_control%density_guess == restart_guess)) THEN
    2424              : 
    2425              :          ! Transform the spin unrestricted alpha and beta Kohn-Sham matrices
    2426              :          ! from AO basis to MO basis: K(MO) = C(T)*K(AO)*C
    2427              : 
    2428         1052 :          CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksa, moa, 0.0_dp, work)
    2429         1052 :          CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, moa, work, 0.0_dp, ksa)
    2430              : 
    2431         1052 :          CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksb, moa, 0.0_dp, work)
    2432         1052 :          CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, moa, work, 0.0_dp, ksb)
    2433              : 
    2434              :          ! Combine the spin unrestricted alpha and beta Kohn-Sham matrices
    2435              :          ! in the MO basis
    2436              : 
    2437         1052 :          IF (scf_control%roks_scheme == general_roks) THEN
    2438              :             CALL combine_ks_matrices(ksa, ksb, occa, occb, scf_control%roks_f, &
    2439            0 :                                      nalpha, nbeta)
    2440         1052 :          ELSE IF (scf_control%roks_scheme == high_spin_roks) THEN
    2441         1052 :             CALL combine_ks_matrices(ksa, ksb, occa, occb, scf_control%roks_parameter)
    2442              :          ELSE
    2443            0 :             CPABORT("Unknown ROKS scheme requested")
    2444              :          END IF
    2445              : 
    2446              :          ! Back-transform the restricted open Kohn-Sham matrix from MO basis
    2447              :          ! to AO basis
    2448              : 
    2449         1052 :          IF (orthogonal_basis) THEN
    2450              :             ! Q = C
    2451          464 :             mo2ao => moa
    2452              :          ELSE
    2453              :             ! Q = S*C
    2454          588 :             mo2ao => mob
    2455              : !MK     CALL copy_sm_to_fm(matrix_s(1)%matrix,work)
    2456              : !MK     CALL cp_fm_symm("L", "U",nao, nao, 1.0_dp, work, moa, 0.0_dp, mo2ao)
    2457          588 :             CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, moa, mo2ao, nao)
    2458              :          END IF
    2459              : 
    2460              :          ! K(AO) = Q*K(MO)*Q(T)
    2461              : 
    2462         1052 :          CALL parallel_gemm("N", "T", nao, nao, nao, 1.0_dp, ksa, mo2ao, 0.0_dp, work)
    2463         1052 :          CALL parallel_gemm("N", "N", nao, nao, nao, 1.0_dp, mo2ao, work, 0.0_dp, ksa)
    2464              : 
    2465              :       ELSE
    2466              : 
    2467              :          ! No transformation matrix available, yet. The closed shell part,
    2468              :          ! i.e. the beta Kohn-Sham matrix in AO basis, is taken.
    2469              :          ! There might be better choices, anyhow.
    2470              : 
    2471          108 :          CALL cp_fm_to_fm(ksb, ksa)
    2472              : 
    2473              :       END IF
    2474              : 
    2475              :       ! Update DIIS buffer and possibly perform DIIS extrapolation step
    2476              : 
    2477         1160 :       IF (scf_env%iter_count > 1) THEN
    2478         1046 :          IF (orthogonal_basis) THEN
    2479              :             CALL qs_diis_b_step(diis_buffer=scf_env%scf_diis_buffer, &
    2480              :                                 mo_array=mos, &
    2481              :                                 kc=scf_env%scf_work1, &
    2482              :                                 sc=work, &
    2483              :                                 delta=scf_env%iter_delta, &
    2484              :                                 error_max=diis_error, &
    2485              :                                 diis_step=diis_step, &
    2486              :                                 eps_diis=scf_control%eps_diis, &
    2487              :                                 scf_section=scf_section, &
    2488          460 :                                 roks=.TRUE.)
    2489          460 :             CPASSERT(scf_env%iter_delta == scf_env%iter_delta)
    2490              :          ELSE
    2491              :             CALL qs_diis_b_step(diis_buffer=scf_env%scf_diis_buffer, &
    2492              :                                 mo_array=mos, &
    2493              :                                 kc=scf_env%scf_work1, &
    2494              :                                 sc=work, &
    2495              :                                 delta=scf_env%iter_delta, &
    2496              :                                 error_max=diis_error, &
    2497              :                                 diis_step=diis_step, &
    2498              :                                 eps_diis=scf_control%eps_diis, &
    2499              :                                 scf_section=scf_section, &
    2500              :                                 s_matrix=matrix_s, &
    2501          586 :                                 roks=.TRUE.)
    2502              :          END IF
    2503              :       END IF
    2504              : 
    2505         1160 :       IF (diis_step) THEN
    2506          802 :          scf_env%iter_param = diis_error
    2507          802 :          scf_env%iter_method = "DIIS/Diag."
    2508              :       ELSE
    2509          358 :          IF (scf_env%mixing_method == 1) THEN
    2510          358 :             scf_env%iter_param = scf_env%p_mix_alpha
    2511          358 :             scf_env%iter_method = "P_Mix/Diag."
    2512            0 :          ELSE IF (scf_env%mixing_method > 1) THEN
    2513            0 :             scf_env%iter_param = scf_env%mixing_store%alpha
    2514            0 :             scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
    2515              :          END IF
    2516              :       END IF
    2517              : 
    2518         1160 :       scf_env%iter_delta = 0.0_dp
    2519              : 
    2520         1160 :       IF (level_shift_loc /= 0.0_dp) THEN
    2521              : 
    2522              :          ! Transform the current Kohn-Sham matrix from AO to MO basis
    2523              :          ! for level-shifting using the current MO set
    2524              : 
    2525           20 :          CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksa, moa, 0.0_dp, work)
    2526           20 :          CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, moa, work, 0.0_dp, ksa)
    2527              : 
    2528              :          ! Apply level-shifting using 50:50 split of the shift (could be relaxed)
    2529              : 
    2530           60 :          DO imo = homob + 1, homoa
    2531           60 :             CALL cp_fm_add_to_element(ksa, imo, imo, 0.5_dp*level_shift_loc)
    2532              :          END DO
    2533          220 :          DO imo = homoa + 1, nmo
    2534          220 :             CALL cp_fm_add_to_element(ksa, imo, imo, level_shift_loc)
    2535              :          END DO
    2536              : 
    2537         1140 :       ELSE IF (.NOT. orthogonal_basis) THEN
    2538              : 
    2539              :          ! Transform the current Kohn-Sham matrix to an orthogonal basis
    2540          618 :          SELECT CASE (scf_env%cholesky_method)
    2541              :          CASE (cholesky_reduce)
    2542            0 :             CALL cp_fm_cholesky_reduce(ksa, ortho)
    2543              :          CASE (cholesky_restore)
    2544          554 :             CALL cp_fm_uplo_to_full(ksa, work)
    2545              :             CALL cp_fm_cholesky_restore(ksa, nao, ortho, work, &
    2546          554 :                                         "SOLVE", pos="RIGHT")
    2547              :             CALL cp_fm_cholesky_restore(work, nao, ortho, ksa, &
    2548          554 :                                         "SOLVE", pos="LEFT", transa="T")
    2549              :          CASE (cholesky_inverse)
    2550            0 :             CALL cp_fm_uplo_to_full(ksa, work)
    2551              :             CALL cp_fm_cholesky_restore(ksa, nao, ortho, work, &
    2552            0 :                                         "MULTIPLY", pos="RIGHT")
    2553              :             CALL cp_fm_cholesky_restore(work, nao, ortho, ksa, &
    2554            0 :                                         "MULTIPLY", pos="LEFT", transa="T")
    2555              :          CASE (cholesky_off)
    2556           64 :             CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksa, ortho, 0.0_dp, work)
    2557          682 :             CALL parallel_gemm("N", "N", nao, nao, nao, 1.0_dp, ortho, work, 0.0_dp, ksa)
    2558              :          END SELECT
    2559              : 
    2560              :       END IF
    2561              : 
    2562              :       ! Diagonalization of the ROKS operator matrix
    2563              : 
    2564         1160 :       CALL choose_eigv_solver(ksa, work, eiga)
    2565              : 
    2566              :       ! Back-transformation of the orthonormal eigenvectors if needed
    2567              : 
    2568         1160 :       IF (level_shift_loc /= 0.0_dp) THEN
    2569              :          ! Use old MO set for back-transformation if level-shifting was applied
    2570           20 :          CALL cp_fm_to_fm(moa, ortho)
    2571           20 :          CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, ortho, work, 0.0_dp, moa)
    2572              :       ELSE
    2573         1140 :          IF (orthogonal_basis) THEN
    2574          522 :             CALL cp_fm_to_fm(work, moa)
    2575              :          ELSE
    2576         1172 :             SELECT CASE (scf_env%cholesky_method)
    2577              :             CASE (cholesky_reduce, cholesky_restore)
    2578          554 :                CALL cp_fm_cholesky_restore(work, nmo, ortho, moa, "SOLVE")
    2579              :             CASE (cholesky_inverse)
    2580            0 :                CALL cp_fm_cholesky_restore(work, nmo, ortho, moa, "MULTIPLY")
    2581              :             CASE (cholesky_off)
    2582          618 :                CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, ortho, work, 0.0_dp, moa)
    2583              :             END SELECT
    2584              :          END IF
    2585              :       END IF
    2586              : 
    2587              :       ! Correct MO eigenvalues, if level-shifting was applied
    2588              : 
    2589         1160 :       IF (level_shift_loc /= 0.0_dp) THEN
    2590           60 :          DO imo = homob + 1, homoa
    2591           60 :             eiga(imo) = eiga(imo) - 0.5_dp*level_shift_loc
    2592              :          END DO
    2593          220 :          DO imo = homoa + 1, nmo
    2594          220 :             eiga(imo) = eiga(imo) - level_shift_loc
    2595              :          END DO
    2596              :       END IF
    2597              : 
    2598              :       ! Update also the beta MO set
    2599              : 
    2600        34460 :       eigb(:) = eiga(:)
    2601         1160 :       CALL cp_fm_to_fm(moa, mob)
    2602              : 
    2603              :       ! Calculate the new alpha and beta density matrix
    2604              : 
    2605              :       ! does not yet handle k-points
    2606         1160 :       CALL calculate_density_matrix(mos(1), scf_env%p_mix_new(1, 1)%matrix)
    2607         1160 :       CALL calculate_density_matrix(mos(2), scf_env%p_mix_new(2, 1)%matrix)
    2608              : 
    2609         1160 :       CALL timestop(handle)
    2610              : 
    2611         1160 :    END SUBROUTINE do_roks_diag
    2612              : 
    2613              : ! **************************************************************************************************
    2614              : !> \brief iterative diagonalization using the block Krylov-space approach
    2615              : !> \param scf_env ...
    2616              : !> \param mos ...
    2617              : !> \param matrix_ks ...
    2618              : !> \param scf_control ...
    2619              : !> \param scf_section ...
    2620              : !> \param check_moconv_only ...
    2621              : !> \param
    2622              : !> \par History
    2623              : !>      05.2009 created [MI]
    2624              : ! **************************************************************************************************
    2625              : 
    2626          114 :    SUBROUTINE do_block_krylov_diag(scf_env, mos, matrix_ks, &
    2627              :                                    scf_control, scf_section, check_moconv_only)
    2628              : 
    2629              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2630              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
    2631              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks
    2632              :       TYPE(scf_control_type), POINTER                    :: scf_control
    2633              :       TYPE(section_vals_type), POINTER                   :: scf_section
    2634              :       LOGICAL, INTENT(IN), OPTIONAL                      :: check_moconv_only
    2635              : 
    2636              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'do_block_krylov_diag'
    2637              :       REAL(KIND=dp), PARAMETER                           :: rone = 1.0_dp, rzero = 0.0_dp
    2638              : 
    2639              :       INTEGER                                            :: handle, homo, ispin, iter, nao, nmo, &
    2640              :                                                             output_unit
    2641              :       LOGICAL                                            :: converged, my_check_moconv_only
    2642              :       REAL(dp)                                           :: eps_iter, t1, t2
    2643          114 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues
    2644              :       TYPE(cp_fm_type), POINTER                          :: c0, c1, chc, evec, ks, mo_coeff, ortho, &
    2645              :                                                             work
    2646              :       TYPE(cp_logger_type), POINTER                      :: logger
    2647              : 
    2648          228 :       logger => cp_get_default_logger()
    2649          114 :       CALL timeset(routineN, handle)
    2650              : 
    2651              :       output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%LANCZOS", &
    2652          114 :                                          extension=".scfLog")
    2653              : 
    2654          114 :       my_check_moconv_only = .FALSE.
    2655          114 :       IF (PRESENT(check_moconv_only)) my_check_moconv_only = check_moconv_only
    2656              : 
    2657          114 :       NULLIFY (mo_coeff, ortho, work, ks)
    2658          114 :       NULLIFY (mo_eigenvalues)
    2659          114 :       NULLIFY (c0, c1)
    2660              : 
    2661          114 :       IF (scf_env%cholesky_method == cholesky_inverse) THEN
    2662           38 :          ortho => scf_env%ortho_m1
    2663              :       ELSE
    2664           76 :          ortho => scf_env%ortho
    2665              :       END IF
    2666          114 :       work => scf_env%scf_work2
    2667              : 
    2668          228 :       DO ispin = 1, SIZE(matrix_ks)
    2669              :          CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, &
    2670          228 :                                scf_env%scf_work1(ispin), scf_env%fm_copy_plan(ispin), check_plan=.TRUE.)
    2671              :       END DO
    2672              : 
    2673          114 :       IF (scf_env%mixing_method == 1) THEN
    2674            0 :          scf_env%iter_param = scf_env%p_mix_alpha
    2675            0 :          scf_env%iter_method = "P_Mix/Lanczos"
    2676              :       ELSE
    2677          114 :          scf_env%iter_param = scf_env%mixing_store%alpha
    2678          114 :          scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Lanc."
    2679              :       END IF
    2680              : 
    2681          228 :       DO ispin = 1, SIZE(matrix_ks)
    2682              : 
    2683          114 :          ks => scf_env%scf_work1(ispin)
    2684          114 :          CALL cp_fm_uplo_to_full(ks, work)
    2685              : 
    2686              :          CALL get_mo_set(mo_set=mos(ispin), &
    2687              :                          nao=nao, &
    2688              :                          nmo=nmo, &
    2689              :                          homo=homo, &
    2690              :                          eigenvalues=mo_eigenvalues, &
    2691          114 :                          mo_coeff=mo_coeff)
    2692              : 
    2693          114 :          NULLIFY (c0, c1)
    2694          114 :          c0 => scf_env%krylov_space%mo_conv(ispin)
    2695          114 :          c1 => scf_env%krylov_space%mo_refine(ispin)
    2696          114 :          SELECT CASE (scf_env%cholesky_method)
    2697              :          CASE (cholesky_reduce)
    2698            0 :             CALL cp_fm_cholesky_reduce(ks, ortho)
    2699            0 :             CALL cp_fm_uplo_to_full(ks, work)
    2700            0 :             CALL cp_fm_cholesky_restore(mo_coeff, nmo, ortho, c0, "MULTIPLY")
    2701              :          CASE (cholesky_restore)
    2702              :             CALL cp_fm_cholesky_restore(ks, nao, ortho, work, &
    2703           76 :                                         "SOLVE", pos="RIGHT")
    2704              :             CALL cp_fm_cholesky_restore(work, nao, ortho, ks, &
    2705           76 :                                         "SOLVE", pos="LEFT", transa="T")
    2706           76 :             CALL cp_fm_cholesky_restore(mo_coeff, nmo, ortho, c0, "MULTIPLY")
    2707              :          CASE (cholesky_inverse)
    2708              :             CALL cp_fm_cholesky_restore(ks, nao, ortho, work, &
    2709           38 :                                         "MULTIPLY", pos="RIGHT")
    2710              :             CALL cp_fm_cholesky_restore(work, nao, ortho, ks, &
    2711           38 :                                         "MULTIPLY", pos="LEFT", transa="T")
    2712          152 :             CALL cp_fm_cholesky_restore(mo_coeff, nmo, ortho, c0, "SOLVE")
    2713              :          END SELECT
    2714              : 
    2715          114 :          scf_env%krylov_space%nmo_nc = nmo
    2716          114 :          scf_env%krylov_space%nmo_conv = 0
    2717              : 
    2718          114 :          t1 = m_walltime()
    2719          114 :          IF (output_unit > 0) THEN
    2720            0 :             WRITE (output_unit, "(/T15,A)") '<<<<<<<<<   LANCZOS REFINEMENT    <<<<<<<<<<'
    2721              :             WRITE (output_unit, "(T8,A,T15,A,T23,A,T36,A,T49,A,T60,A,/,T8,A)") &
    2722            0 :                " Spin ", " Cycle ", &
    2723            0 :                " conv. MOS ", " B2MAX ", " B2MIN ", " Time", REPEAT("-", 60)
    2724              :          END IF
    2725              :          eps_iter = kp_adaptive_eps_iter(scf_env%krylov_settings%eps_conv, scf_env%krylov_settings%eps_adapt, &
    2726          114 :                                          scf_env%iter_delta, 1.0_dp, HUGE(1.0_dp))
    2727          114 :          iter = 0
    2728          114 :          converged = .FALSE.
    2729              :          !Check convergence of MOS
    2730          342 :          IF (my_check_moconv_only) THEN
    2731              : 
    2732              :             CALL lanczos_refinement(scf_env%krylov_space, ks, c0, c1, mo_eigenvalues, &
    2733            0 :                                     nao, eps_iter, ispin, check_moconv_only=my_check_moconv_only)
    2734            0 :             t2 = m_walltime()
    2735            0 :             IF (output_unit > 0) THEN
    2736              :                WRITE (output_unit, '(T8,I3,T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
    2737            0 :                   ispin, iter, scf_env%krylov_space%nmo_conv, &
    2738            0 :                   scf_env%krylov_space%max_res_norm, scf_env%krylov_space%min_res_norm, t2 - t1
    2739              :             END IF
    2740              : 
    2741              :             CYCLE
    2742              :          ELSE
    2743              :             !Block Lanczos refinement
    2744          848 :             DO iter = 1, scf_env%krylov_settings%max_iter
    2745              :                CALL lanczos_refinement_2v(scf_env%krylov_space, ks, c0, c1, mo_eigenvalues, &
    2746          744 :                                           nao, eps_iter, ispin)
    2747          744 :                t2 = m_walltime()
    2748          744 :                IF (output_unit > 0) THEN
    2749              :                   WRITE (output_unit, '(T8,I3,T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
    2750            0 :                      ispin, iter, scf_env%krylov_space%nmo_conv, &
    2751            0 :                      scf_env%krylov_space%max_res_norm, scf_env%krylov_space%min_res_norm, t2 - t1
    2752              :                END IF
    2753          744 :                t1 = m_walltime()
    2754          848 :                IF (scf_env%krylov_space%max_res_norm < eps_iter) THEN
    2755           10 :                   converged = .TRUE.
    2756           10 :                   IF (output_unit > 0) WRITE (output_unit, *) &
    2757            0 :                      " Reached convergence in ", iter, " iterations "
    2758              :                   EXIT
    2759              :                END IF
    2760              :             END DO
    2761              : 
    2762          114 :             IF (.NOT. converged .AND. output_unit > 0) THEN
    2763              :                WRITE (output_unit, "(T4, A)") " WARNING Lanczos refinement could "// &
    2764            0 :                   "not converge all the mos:"
    2765            0 :                WRITE (output_unit, "(T40,A,T70,I10)") " number of not converged mos ", &
    2766            0 :                   scf_env%krylov_space%nmo_nc
    2767            0 :                WRITE (output_unit, "(T40,A,T70,E10.2)") " max norm of the residual ", &
    2768            0 :                   scf_env%krylov_space%max_res_norm
    2769              : 
    2770              :             END IF
    2771              : 
    2772              :             ! For the moment skip the re-orthogonalization
    2773              :             IF (.FALSE.) THEN
    2774              :                !Re-orthogonalization
    2775              :                NULLIFY (chc, evec)
    2776              :                chc => scf_env%krylov_space%chc_mat(ispin)
    2777              :                evec => scf_env%krylov_space%c_vec(ispin)
    2778              :                CALL parallel_gemm('N', 'N', nao, nmo, nao, rone, ks, c0, rzero, work)
    2779              :                CALL parallel_gemm('T', 'N', nmo, nmo, nao, rone, c0, work, rzero, chc)
    2780              :                !Diagonalize  (C^t)HC
    2781              :                CALL choose_eigv_solver(chc, evec, mo_eigenvalues)
    2782              :                !Rotate the C vectors
    2783              :                CALL parallel_gemm('N', 'N', nao, nmo, nmo, rone, c0, evec, rzero, c1)
    2784              :                c0 => scf_env%krylov_space%mo_refine(ispin)
    2785              :             END IF
    2786              : 
    2787          114 :             IF (scf_env%cholesky_method == cholesky_inverse) THEN
    2788           38 :                CALL cp_fm_cholesky_restore(c0, nmo, ortho, mo_coeff, "MULTIPLY")
    2789              :             ELSE
    2790           76 :                CALL cp_fm_cholesky_restore(c0, nmo, ortho, mo_coeff, "SOLVE")
    2791              :             END IF
    2792              : 
    2793          114 :             IF (.NOT. scf_control%gce%do_gce) THEN
    2794              :                CALL set_mo_occupation(mo_set=mos(ispin), &
    2795          114 :                                       smear=scf_control%smear)
    2796              :             ELSE
    2797              :                CALL set_mo_occupation(mo_set=mos(ispin), &
    2798              :                                       smear=scf_control%smear, &
    2799            0 :                                       gce=scf_control%gce)
    2800              :             END IF
    2801              : 
    2802              :             ! does not yet handle k-points
    2803              :             CALL calculate_density_matrix(mos(ispin), &
    2804          114 :                                           scf_env%p_mix_new(ispin, 1)%matrix)
    2805              :          END IF
    2806              :       END DO ! ispin
    2807              : 
    2808          114 :       IF (output_unit > 0) THEN
    2809            0 :          WRITE (output_unit, "(T15,A/)") '<<<<<<<<< END LANCZOS REFINEMENT  <<<<<<<<<<'
    2810              :       END IF
    2811              : 
    2812              :       CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
    2813          114 :                                         "PRINT%LANCZOS")
    2814              : 
    2815          114 :       CALL timestop(handle)
    2816              : 
    2817          114 :    END SUBROUTINE do_block_krylov_diag
    2818              : 
    2819              : ! **************************************************************************************************
    2820              : !> \brief iterative diagonalization using the block davidson space approach
    2821              : !> \param qs_env ...
    2822              : !> \param scf_env ...
    2823              : !> \param mos ...
    2824              : !> \param matrix_ks ...
    2825              : !> \param matrix_s ...
    2826              : !> \param scf_control ...
    2827              : !> \param scf_section ...
    2828              : !> \param check_moconv_only ...
    2829              : !> \param
    2830              : !> \par History
    2831              : !>      05.2011 created [MI]
    2832              : ! **************************************************************************************************
    2833              : 
    2834           94 :    SUBROUTINE do_block_davidson_diag(qs_env, scf_env, mos, matrix_ks, matrix_s, &
    2835              :                                      scf_control, scf_section, check_moconv_only)
    2836              : 
    2837              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2838              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2839              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
    2840              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
    2841              :       TYPE(scf_control_type), POINTER                    :: scf_control
    2842              :       TYPE(section_vals_type), POINTER                   :: scf_section
    2843              :       LOGICAL, INTENT(IN), OPTIONAL                      :: check_moconv_only
    2844              : 
    2845              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'do_block_davidson_diag'
    2846              : 
    2847              :       INTEGER                                            :: handle, ispin, nspins, output_unit
    2848              :       LOGICAL                                            :: do_prec, my_check_moconv_only
    2849              :       TYPE(cp_logger_type), POINTER                      :: logger
    2850              : 
    2851           94 :       logger => cp_get_default_logger()
    2852           94 :       CALL timeset(routineN, handle)
    2853              : 
    2854              :       output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DAVIDSON", &
    2855           94 :                                          extension=".scfLog")
    2856              : 
    2857           94 :       IF (output_unit > 0) THEN
    2858            0 :          WRITE (output_unit, "(/T15,A)") '<<<<<<<<<  DAVIDSON ITERATIONS   <<<<<<<<<<'
    2859              :       END IF
    2860              : 
    2861           94 :       IF (scf_env%mixing_method == 1) THEN
    2862            0 :          scf_env%iter_param = scf_env%p_mix_alpha
    2863            0 :          scf_env%iter_method = "P_Mix/Dav."
    2864              :       ELSE
    2865           94 :          scf_env%iter_param = scf_env%mixing_store%alpha
    2866           94 :          scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Dav."
    2867              :       END IF
    2868              : 
    2869           94 :       my_check_moconv_only = .FALSE.
    2870           94 :       IF (PRESENT(check_moconv_only)) my_check_moconv_only = check_moconv_only
    2871           94 :       do_prec = .FALSE.
    2872           94 :       IF (scf_env%block_davidson_env(1)%prec_type /= 0 .AND. &
    2873              :           scf_env%iter_count >= scf_env%block_davidson_env(1)%first_prec) THEN
    2874           84 :          do_prec = .TRUE.
    2875              :       END IF
    2876              : 
    2877           94 :       nspins = SIZE(matrix_ks)
    2878              : 
    2879           94 :       IF (do_prec .AND. (scf_env%iter_count == scf_env%block_davidson_env(1)%first_prec .OR. &
    2880              :                          MODULO(scf_env%iter_count, scf_env%block_davidson_env(1)%niter_new_prec) == 0)) THEN
    2881              :          CALL restart_preconditioner(qs_env, scf_env%ot_preconditioner, &
    2882           18 :                                      prec_type=scf_env%block_davidson_env(1)%prec_type, nspins=nspins)
    2883              :          CALL prepare_preconditioner(qs_env, mos, matrix_ks, matrix_s, scf_env%ot_preconditioner, &
    2884              :                                      scf_env%block_davidson_env(1)%prec_type, &
    2885              :                                      scf_env%block_davidson_env(1)%solver_type, &
    2886              :                                      scf_env%block_davidson_env(1)%energy_gap, nspins, &
    2887              :                                      convert_to_dbcsr=scf_env%block_davidson_env(1)%use_sparse_mos, &
    2888           18 :                                      full_mo_set=.TRUE.)
    2889              :       END IF
    2890              : 
    2891          198 :       DO ispin = 1, nspins
    2892          198 :          IF (scf_env%block_davidson_env(ispin)%use_sparse_mos) THEN
    2893           64 :             IF (.NOT. do_prec) THEN
    2894              :                CALL generate_extended_space_sparse(scf_env%block_davidson_env(ispin), mos(ispin), &
    2895            8 :                                                    matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit)
    2896              :             ELSE
    2897              :                CALL generate_extended_space_sparse(scf_env%block_davidson_env(ispin), mos(ispin), &
    2898              :                                                    matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit, &
    2899           56 :                                                    scf_env%ot_preconditioner(ispin)%preconditioner)
    2900              :             END IF
    2901              : 
    2902              :          ELSE
    2903           40 :             IF (.NOT. do_prec) THEN
    2904              :                CALL generate_extended_space(scf_env%block_davidson_env(ispin), mos(ispin), &
    2905            4 :                                             matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit)
    2906              :             ELSE
    2907              :                CALL generate_extended_space(scf_env%block_davidson_env(ispin), mos(ispin), &
    2908              :                                             matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit, &
    2909           36 :                                             scf_env%ot_preconditioner(ispin)%preconditioner)
    2910              :             END IF
    2911              :          END IF
    2912              :       END DO !ispin
    2913              : 
    2914           94 :       IF (.NOT. scf_control%gce%do_gce) THEN
    2915              :          CALL set_mo_occupation(mo_array=mos, &
    2916           94 :                                 smear=scf_control%smear)
    2917              :       ELSE
    2918              :          CALL set_mo_occupation(mo_array=mos, &
    2919              :                                 smear=scf_control%smear, &
    2920            0 :                                 gce=scf_control%gce)
    2921              :       END IF
    2922              : 
    2923          198 :       DO ispin = 1, nspins
    2924              :          ! does not yet handle k-points
    2925              :          CALL calculate_density_matrix(mos(ispin), &
    2926          198 :                                        scf_env%p_mix_new(ispin, 1)%matrix)
    2927              :       END DO
    2928              : 
    2929           94 :       IF (output_unit > 0) THEN
    2930            0 :          WRITE (output_unit, "(T15,A/)") '<<<<<<<<< END DAVIDSON ITERATION  <<<<<<<<<<'
    2931              :       END IF
    2932              : 
    2933              :       CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
    2934           94 :                                         "PRINT%DAVIDSON")
    2935              : 
    2936           94 :       CALL timestop(handle)
    2937              : 
    2938           94 :    END SUBROUTINE do_block_davidson_diag
    2939              : 
    2940              : ! **************************************************************************************************
    2941              : !> \brief block-Davidson SCF step for complex K points, one channel per
    2942              : !>        (local kpoint, spin); mirrors do_block_davidson_diag for the
    2943              : !>        preconditioner scheduling and do_general_diag_kp for the H(k)/S(k)
    2944              : !>        assembly and the density exit chain
    2945              : !> \param qs_env ...
    2946              : !> \param scf_env ...
    2947              : !> \param matrix_ks_kp real-space Kohn-Sham matrices, dbcsr image set
    2948              : !> \param matrix_s_kp real-space overlap matrix, dbcsr image set
    2949              : !> \param kpoints ...
    2950              : !> \param scf_control ...
    2951              : !> \param added_mos_auto_grow ...
    2952              : ! **************************************************************************************************
    2953          906 :    SUBROUTINE do_block_davidson_diag_kp(qs_env, scf_env, matrix_ks_kp, matrix_s_kp, kpoints, &
    2954              :                                         scf_control, added_mos_auto_grow)
    2955              : 
    2956              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2957              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2958              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks_kp, matrix_s_kp
    2959              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2960              :       TYPE(scf_control_type), POINTER                    :: scf_control
    2961              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: added_mos_auto_grow
    2962              : 
    2963              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'do_block_davidson_diag_kp'
    2964              :       REAL(KIND=dp), PARAMETER                           :: empty_factor = 5.0_dp, &
    2965              :                                                             eps_iter_cap = 1.0E-4_dp
    2966              : 
    2967              :       INTEGER                                            :: channel, first_prec, handle, ispin, iw, &
    2968              :                                                             kplocal, kpmax, local_kpoint, &
    2969              :                                                             nchannels, nspin, output_unit
    2970              :       INTEGER, DIMENSION(2)                              :: kp_range
    2971          906 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
    2972          906 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    2973              :       LOGICAL                                            :: do_prec, my_grow, use_real_wfn
    2974              :       REAL(KIND=dp)                                      :: eps_iter, eps_iter_empty
    2975          906 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    2976              :       TYPE(cp_cfm_type)                                  :: cksmat, csmat, csmat_base
    2977              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    2978          906 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
    2979              :       TYPE(cp_logger_type), POINTER                      :: logger
    2980              :       TYPE(kpoint_env_type), POINTER                     :: kp
    2981          906 :       TYPE(kpoint_operator_context_type)                 :: op_ctx
    2982              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2983              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2984          906 :          POINTER                                         :: sab_nl
    2985              :       TYPE(section_vals_type), POINTER                   :: scf_section
    2986              : 
    2987              : ! bounds of the adaptive inner tolerance. The loose phase is capped for
    2988              : ! the residual-norm semantics of EPS_ITER. A residual of order 1/k would
    2989              : ! leave an eigenvector error of order 10 percent at a typical metallic
    2990              : ! gap. Unoccupied MOS converge empty_factor times looser. The tracking
    2991              : ! divides the mixing delta by noise_scale: the SCF convergence measure
    2992              : ! is the LARGEST ELEMENT of the density residual, in which the
    2993              : ! per-column residuals of a whole block accumulate. The measured
    2994              : ! amplification is ~20 on a smeared Bi2S3/MoS2 slab, so tracking at
    2995              : ! delta/100 keeps the injected noise below the outer convergence level.
    2996              : 
    2997         1812 :       logger => cp_get_default_logger()
    2998          906 :       CALL timeset(routineN, handle)
    2999              : 
    3000          906 :       scf_section => section_vals_get_subs_vals(qs_env%input, "DFT%SCF")
    3001              :       output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DAVIDSON", &
    3002          906 :                                          extension=".scfLog")
    3003          906 :       IF (output_unit > 0) THEN
    3004            0 :          WRITE (output_unit, "(/T15,A)") '<<<<<<<<<  DAVIDSON ITERATIONS   <<<<<<<<<<'
    3005              :       END IF
    3006              : 
    3007              :       CALL get_kpoint_info(kpoints, kp_range=kp_range, kp_dist=kp_dist, xkp=xkp, &
    3008              :                            use_real_wfn=use_real_wfn, sab_nl=sab_nl, &
    3009          906 :                            cell_to_index=cell_to_index)
    3010          906 :       IF (use_real_wfn) THEN
    3011            0 :          CPABORT('Davidson Kp requires complex K-point MOS')
    3012              :       END IF
    3013          906 :       para_env => kpoints%blacs_env_all%para_env
    3014          906 :       kplocal = kp_range(2) - kp_range(1) + 1
    3015         2384 :       kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
    3016          906 :       nspin = SIZE(matrix_ks_kp, 1)
    3017          906 :       nchannels = kplocal*nspin
    3018              : 
    3019          906 :       IF (scf_env%mixing_method == 1) THEN
    3020          684 :          scf_env%iter_param = scf_env%p_mix_alpha
    3021          684 :          scf_env%iter_method = "P_Mix/Dav."
    3022          222 :       ELSE IF (scf_env%mixing_method > 1) THEN
    3023          222 :          scf_env%iter_param = scf_env%mixing_store%alpha
    3024          222 :          scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Dav."
    3025              :       END IF
    3026              : 
    3027              :       ! preconditioner scheduling, mirrors do_block_davidson_diag. The first
    3028              :       ! K-point SCF step cold-starts unless extrapolation prefilled the MOS
    3029              :       ! (mos_prefilled). The FULL_ALL maker consumes the MO coefficients and
    3030              :       ! eigenvalues, so building before the first solve completed would feed it
    3031              :       ! uninitialized data and stall the Davidson convergence. Keep first_prec
    3032              :       ! clamped past that step in both cases. Warming it up under prefilled MOS
    3033              :       ! would mix two variables at once.
    3034          906 :       first_prec = MAX(scf_env%block_davidson_env(1)%first_prec, 2)
    3035          906 :       do_prec = .FALSE.
    3036          906 :       IF (scf_env%block_davidson_env(1)%prec_type /= ot_precond_none .AND. &
    3037              :           scf_env%iter_count >= first_prec) THEN
    3038          806 :          do_prec = .TRUE.
    3039              :       END IF
    3040              :       ! adaptive inner tolerance from EPS_ADAPT: loose while the density is
    3041              :       ! still far from self-consistency, tightening with the outer error
    3042              :       ! scaled by noise_scale (mirrors the block Krylov scheduling in
    3043              :       ! do_block_krylov_diag). The
    3044              :       ! ratchet is monotone across SCF steps: the threshold may tighten but
    3045              :       ! never relax again. A rebounding outer error would otherwise re-loosen
    3046              :       ! the solver, and the run could stop on a near-zero mixing delta of a
    3047              :       ! pair of identical, sloppily converged densities. The cap bounds the
    3048              :       ! early loose phase. Unoccupied MOS converge empty_factor times
    3049              :       ! looser (the occupancy decides which columns qualify, see
    3050              :       ! generate_extended_space_c). There is no restoration of the
    3051              :       ! user threshold at the end. The tolerance stays a margin below the
    3052              :       ! outer error. The MOS the run exits with satisfy that same margin
    3053              :       ! rather than the nominal EPS_ITER.
    3054          906 :       eps_iter = scf_env%block_davidson_env(1)%eps_iter
    3055          906 :       eps_iter_empty = eps_iter
    3056          906 :       IF (scf_control%diagonalization%eps_adapt > 0.0_dp .AND. scf_env%iter_delta > 0.0_dp) THEN
    3057              :          ! stall escape: when the mixing delta sank below the tolerance the
    3058              :          ! last solve used, that solve's own sloppiness may be the noise floor
    3059              :          ! pinning the delta. Tighten one decade below what that solve used.
    3060              :          ! Tightening relative to the OPERATING tolerance instead of the
    3061              :          ! dipped delta bounds the reaction to transient mixing dips (a
    3062              :          ! momentary overshoot must not collapse the threshold by orders of
    3063              :          ! magnitude and destabilise the mixer), while a genuine stall moves
    3064              :          ! the threshold down decade by decade. Checking on the stall alone
    3065              :          ! keeps the loose phase as loose as EPS_ADAPT allows
    3066           76 :          IF (scf_env%iter_delta < scf_env%block_davidson_env(1)%eps_iter_used) THEN
    3067              :             scf_env%block_davidson_env(1)%eps_iter_prev = &
    3068              :                MIN(scf_env%block_davidson_env(1)%eps_iter_prev, &
    3069              :                    MAX(scf_env%block_davidson_env(1)%eps_iter, &
    3070           12 :                        0.1_dp*scf_env%block_davidson_env(1)%eps_iter_used))
    3071              :          END IF
    3072              :          ! candidate: looser than the user value, capped; ratchet: only
    3073              :          ! tighter than the previous adaptive value, which lives in the
    3074              :          ! persistent channel settings (a local variable would reset on
    3075              :          ! every call into this driver)
    3076              :          eps_iter = MIN(MAX(eps_iter, MIN(scf_control%diagonalization%eps_adapt*scf_env%iter_delta/ &
    3077              :                                           scf_env%block_davidson_env(1)%noise_scale, &
    3078           76 :                                           eps_iter_cap)), scf_env%block_davidson_env(1)%eps_iter_prev)
    3079           76 :          eps_iter_empty = empty_factor*eps_iter
    3080              :          ! record what this solve uses, after every override above: the outer
    3081              :          ! loop compares the mixing delta against it (qs_scf_check_inner_exit)
    3082           76 :          scf_env%block_davidson_env(1)%eps_iter_prev = eps_iter
    3083           76 :          scf_env%block_davidson_env(1)%eps_iter_used = eps_iter
    3084              :       END IF
    3085              :       ! schedule trace of the adaptive tolerance, one line per SCF step at
    3086              :       ! DEBUG print level
    3087          906 :       IF (scf_control%diagonalization%eps_adapt > 0.0_dp .AND. para_env%is_source() .AND. &
    3088              :           logger%iter_info%print_level >= debug_print_level) THEN
    3089            0 :          iw = cp_logger_get_default_unit_nr()
    3090            0 :          IF (iw > 0) THEN
    3091              :             WRITE (UNIT=iw, FMT="(T3,'EPS_ADAPT step',I5,' delta=',ES9.2,' eps_occ=',ES9.2,' eps_empty=',ES9.2)") &
    3092            0 :                scf_env%iter_count, scf_env%iter_delta, eps_iter, eps_iter_empty
    3093              :          END IF
    3094              :       END IF
    3095              : 
    3096              :       ! work matrices: global scratch fms (also the operator-context
    3097              :       ! template) and the complex H(k)/S(k)
    3098              :       CALL kp_diag_setup(qs_env, kpoints, nspin, matrix_ks_kp, matrix_s_kp, fmwork, op_ctx, &
    3099          906 :                          matrix_struct, .TRUE.)
    3100          906 :       CALL cp_cfm_create(cksmat, matrix_struct, name="dav_hk")
    3101          906 :       CALL cp_cfm_create(csmat, matrix_struct, name="dav_sk")
    3102          906 :       CALL cp_cfm_create(csmat_base, matrix_struct, name="dav_sk_base")
    3103              : 
    3104          906 :       IF (do_prec .AND. (scf_env%iter_count == first_prec .OR. &
    3105              :                          MODULO(scf_env%iter_count, &
    3106              :                                 scf_env%block_davidson_env(1)%niter_new_prec) == 0)) THEN
    3107              :          CALL davidson_kp_prepare_preconditioners( &
    3108           56 :             qs_env, scf_env, matrix_ks_kp, matrix_s_kp, kpoints, op_ctx)
    3109              :       END IF
    3110              : 
    3111         2786 :       DO local_kpoint = 1, kpmax
    3112              :          ! Every k-point group executes the same sequence of global transforms.
    3113              :          ! Groups without a k point in the last round still participate
    3114              :          ! in the service calls, but skip their local solver work.
    3115              :          CALL kpoint_operator_get(op_ctx, local_kpoint, kpoint_spin_free, matrix_s_kp, &
    3116         1880 :                                   cmat=csmat_base, matrix_row=kpoint_spin_free, slot=kpoint_slot_s)
    3117              : 
    3118         4742 :          DO ispin = 1, nspin
    3119              :             CALL kpoint_operator_get(op_ctx, local_kpoint, ispin, matrix_ks_kp, &
    3120         1956 :                                      cmat=cksmat, matrix_row=ispin, slot=kpoint_slot_ks)
    3121         1956 :             IF (local_kpoint > kplocal) CYCLE
    3122         1956 :             kp => kpoints%kp_env(local_kpoint)%kpoint_env
    3123         1956 :             CALL cp_cfm_to_cfm(csmat_base, csmat)
    3124              : 
    3125         3836 :             IF (scf_env%iter_count == 1 .AND. .NOT. kp%mos_prefilled) THEN
    3126              :                ! K-point MOS enter the first SCF step allocated but uninitialized.
    3127              :                ! The stored S(k) copy is restored for every spin because
    3128              :                ! cp_cfm_geeig overwrites its matrix arguments.
    3129           74 :                CALL cold_start_mo_init(kp, ispin, cksmat, csmat)
    3130              :             ELSE
    3131         1882 :                channel = (local_kpoint - 1)*nspin + ispin
    3132         1882 :                IF (do_prec) THEN
    3133              :                   CALL generate_extended_space_c(scf_env%block_davidson_env(channel), &
    3134              :                                                  kp%mos(ispin), cksmat, csmat, output_unit, &
    3135              :                                                  eps_iter, eps_iter_empty, &
    3136         1754 :                                                  scf_env%ot_preconditioner(channel)%preconditioner)
    3137              :                ELSE
    3138              :                   CALL generate_extended_space_c(scf_env%block_davidson_env(channel), &
    3139              :                                                  kp%mos(ispin), cksmat, csmat, output_unit, &
    3140          128 :                                                  eps_iter, eps_iter_empty)
    3141              :                END IF
    3142              :             END IF
    3143              :          END DO
    3144              :       END DO
    3145              : 
    3146              :       ! occupations and density: the shared exit chain, same as every
    3147              :       ! other k-point diagonalization driver
    3148          906 :       CALL kp_diag_exit_chain(kpoints, scf_env, scf_control, matrix_s_kp, sab_nl, fmwork, my_grow)
    3149          906 :       IF (my_grow .AND. PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
    3150              : 
    3151          906 :       CALL cp_cfm_release(cksmat)
    3152          906 :       CALL cp_cfm_release(csmat)
    3153          906 :       CALL cp_cfm_release(csmat_base)
    3154          906 :       CALL kp_diag_finalize(qs_env, fmwork, op_ctx)
    3155              : 
    3156          906 :       IF (output_unit > 0) THEN
    3157            0 :          WRITE (output_unit, "(T15,A/)") '<<<<<<<<< END DAVIDSON ITERATION  <<<<<<<<<<'
    3158              :       END IF
    3159              :       CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
    3160          906 :                                         "PRINT%DAVIDSON")
    3161              : 
    3162          906 :       CALL timestop(handle)
    3163              : 
    3164         1812 :    END SUBROUTINE do_block_davidson_diag_kp
    3165              : 
    3166              : ! **************************************************************************************************
    3167              : !> \brief Block Krylov (Lanczos) refinement of the k-point MOS, the complex
    3168              : !>        counterpart of do_block_krylov_diag: every channel (local kpoint,
    3169              : !>        spin) is standardized with the Cholesky factor of S(k), refined by
    3170              : !>        the complex block-Krylov kernel, and rotated back into the
    3171              : !>        generalized problem
    3172              : !> \param qs_env ...
    3173              : !> \param scf_env ...
    3174              : !> \param matrix_ks_kp real-space Kohn-Sham matrix, dbcsr image set
    3175              : !> \param matrix_s_kp real-space overlap matrix, dbcsr image set
    3176              : !> \param kpoints ...
    3177              : !> \param scf_control ...
    3178              : !> \param check_moconv_only only report the convergence statistics
    3179              : !> \param added_mos_auto_grow signals the outer loop that the virtual-space
    3180              : !>        buffer must grow before this SCF step is redone
    3181              : ! **************************************************************************************************
    3182          586 :    SUBROUTINE do_block_krylov_diag_kp(qs_env, scf_env, matrix_ks_kp, matrix_s_kp, kpoints, &
    3183              :                                       scf_control, check_moconv_only, added_mos_auto_grow)
    3184              : 
    3185              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3186              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    3187              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks_kp, matrix_s_kp
    3188              :       TYPE(kpoint_type), POINTER                         :: kpoints
    3189              :       TYPE(scf_control_type), POINTER                    :: scf_control
    3190              :       LOGICAL, INTENT(IN), OPTIONAL                      :: check_moconv_only
    3191              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: added_mos_auto_grow
    3192              : 
    3193              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'do_block_krylov_diag_kp'
    3194              :       REAL(KIND=dp), PARAMETER                           :: empty_factor = 5.0_dp, &
    3195              :                                                             eps_iter_cap = 1.0E-4_dp, &
    3196              :                                                             noise_scale = 100.0_dp
    3197              : 
    3198              :       INTEGER                                            :: handle, ik, ikp, ispin, kplocal, kpmax, &
    3199              :                                                             local_kpoint, max_iter, nentry, nspin, &
    3200              :                                                             output_unit
    3201              :       INTEGER, DIMENSION(2)                              :: kp_range
    3202          586 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
    3203              :       LOGICAL                                            :: my_check_moconv_only, my_grow, &
    3204              :                                                             prepared_ops, use_local_kpoints, &
    3205              :                                                             use_real_wfn
    3206              :       REAL(KIND=dp)                                      :: eps_iter, eps_iter_empty
    3207              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct, mo_struct
    3208          586 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
    3209              :       TYPE(cp_logger_type), POINTER                      :: logger
    3210          586 :       TYPE(kp_diag_workspace_type), ALLOCATABLE, TARGET  :: workspace(:)
    3211              :       TYPE(kpoint_env_type), POINTER                     :: kp
    3212          586 :       TYPE(kpoint_operator_context_type)                 :: op_ctx
    3213              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    3214          586 :          POINTER                                         :: sab_nl
    3215              :       TYPE(section_vals_type), POINTER                   :: scf_section
    3216              : 
    3217              : ! empty_factor and noise_scale mirror the defaults of the
    3218              : ! Davidson k-point driver. eps_iter_cap bounds the adaptive tolerance
    3219              : 
    3220         1172 :       logger => cp_get_default_logger()
    3221          586 :       CALL timeset(routineN, handle)
    3222              : 
    3223          586 :       my_check_moconv_only = .FALSE.
    3224          586 :       IF (PRESENT(check_moconv_only)) my_check_moconv_only = check_moconv_only
    3225              : 
    3226          586 :       scf_section => section_vals_get_subs_vals(qs_env%input, "DFT%SCF")
    3227              :       output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%LANCZOS", &
    3228          586 :                                          extension=".scfLog")
    3229              : 
    3230              :       CALL get_kpoint_info(kpoints, kp_range=kp_range, kp_dist=kp_dist, &
    3231          586 :                            use_real_wfn=use_real_wfn, sab_nl=sab_nl)
    3232          586 :       IF (use_real_wfn) THEN
    3233            0 :          CPABORT('k-point Lanczos refinement requires complex k-point MOS')
    3234              :       END IF
    3235          586 :       kplocal = kp_range(2) - kp_range(1) + 1
    3236              :       ! the largest local k-point count across the groups: kp_dist can be
    3237              :       ! uneven, and every group must join the service calls for every round
    3238         1634 :       kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
    3239          586 :       nspin = SIZE(matrix_ks_kp, 1)
    3240              : 
    3241          586 :       IF (scf_env%mixing_method == 1) THEN
    3242          264 :          scf_env%iter_param = scf_env%p_mix_alpha
    3243          264 :          scf_env%iter_method = "P_Mix/Lanczos"
    3244              :       ELSE
    3245          322 :          scf_env%iter_param = scf_env%mixing_store%alpha
    3246          322 :          scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Lanc."
    3247              :       END IF
    3248              : 
    3249              :       ! work matrices: the driver workspace below holds the complex
    3250              :       ! H(k)/S(k) of the channels
    3251              : 
    3252              :       ! adaptive inner tolerance, mirrors do_block_krylov_diag; it carries
    3253              :       ! no ratchet state, the threshold follows the sinking mixing delta
    3254              :       eps_iter = kp_adaptive_eps_iter(scf_env%krylov_settings%eps_conv, scf_env%krylov_settings%eps_adapt, &
    3255          586 :                                       scf_env%iter_delta, noise_scale, eps_iter_cap)
    3256              :       ! unoccupied MOS relax like the Davidson k-point driver: the
    3257              :       ! occupation decides which columns use the relaxed empty threshold,
    3258              :       ! not the HOMO index (see generate_extended_space_c)
    3259          586 :       eps_iter_empty = eps_iter
    3260          586 :       IF (scf_env%krylov_settings%eps_adapt > 0.0_dp) eps_iter_empty = empty_factor*eps_iter
    3261          586 :       max_iter = scf_env%krylov_settings%max_iter
    3262              : 
    3263              :       ! one-rank k-point groups refine their k points locally, without a
    3264              :       ! transfer round; a diag check, a convergence-only probe and an
    3265              :       ! explicitly selected diagonalization library keep the rounds
    3266          586 :       use_local_kpoints = kpoints%para_env_kp%num_pe == 1
    3267          586 :       IF (diag_check_requested()) use_local_kpoints = .FALSE.
    3268          586 :       IF (my_check_moconv_only) use_local_kpoints = .FALSE.
    3269          586 :       IF (diag_lib_explicit) use_local_kpoints = .FALSE.
    3270              :       ! the transfer rounds assemble their operators lazily through the
    3271              :       ! get path and skip the snapshot
    3272              :       CALL kp_diag_setup(qs_env, kpoints, nspin, matrix_ks_kp, matrix_s_kp, fmwork, op_ctx, &
    3273          586 :                          matrix_struct, use_local_kpoints, prepared_ops)
    3274          586 :       use_local_kpoints = use_local_kpoints .AND. prepared_ops
    3275              : 
    3276          586 :       nentry = 0
    3277          586 :       IF (use_local_kpoints) CALL kpoint_operator_work_size(op_ctx, nentry)
    3278          586 :       kp => kpoints%kp_env(1)%kpoint_env
    3279          586 :       mo_struct => kp%mos(1)%cmo_coeff%matrix_struct
    3280              :       CALL kp_diag_workspaces_create(workspace, 1, matrix_struct, mo_struct, nentry, &
    3281              :                                      use_local_kpoints, scf_env%cholesky_method == cholesky_off, &
    3282              :                                      lanczos=.TRUE., nkrylov=scf_env%krylov_settings%nkrylov, &
    3283          586 :                                      nblock=scf_env%krylov_settings%nblock)
    3284              : 
    3285          586 :       IF (output_unit > 0 .AND. .NOT. my_check_moconv_only) THEN
    3286           28 :          WRITE (output_unit, "(/T15,A)") '<<<<<<<<<   LANCZOS REFINEMENT    <<<<<<<<<<'
    3287              :          WRITE (output_unit, "(T8,A,T15,A,T23,A,T36,A,T49,A,T60,A,/,T8,A)") &
    3288           28 :             " Spin ", " Cycle ", &
    3289           56 :             " conv. MOS ", " B2MAX ", " B2MIN ", " Time", REPEAT("-", 60)
    3290              :       END IF
    3291              : 
    3292          586 :       IF (use_local_kpoints) THEN
    3293              :          ! serial pass over the locally owned k points. The first SCF step
    3294              :          ! cold-starts every unprefilled channel in place, like the rounds
    3295              :          ! path below. Later steps refine
    3296         1059 :          DO ikp = 1, kplocal
    3297          603 :             kp => kpoints%kp_env(ikp)%kpoint_env
    3298          603 :             ik = kp_range(1) + ikp - 1
    3299              :             CALL kpoint_operator_evaluate(op_ctx, 1, kpoint_slot_s, ik, workspace(1)%phase, &
    3300          603 :                                           workspace(1)%csmat_base)
    3301         1662 :             DO ispin = 1, nspin
    3302              :                CALL kpoint_operator_evaluate(op_ctx, ispin, kpoint_slot_ks, ik, workspace(1)%phase, &
    3303          603 :                                              workspace(1)%cksmat)
    3304          603 :                IF (scf_env%iter_count == 1 .AND. .NOT. kp%mos_prefilled) THEN
    3305              :                   ! the K-point MOS enter the first SCF step allocated but
    3306              :                   ! uninitialized
    3307           25 :                   CALL cold_start_mo_init(kp, ispin, workspace(1)%cksmat, workspace(1)%csmat_base)
    3308           25 :                   CYCLE
    3309              :                END IF
    3310              :                CALL lanczos_refine_channel(kp, ispin, scf_env, my_check_moconv_only, eps_iter, &
    3311         1181 :                                            eps_iter_empty, max_iter, workspace(1), output_unit, .TRUE.)
    3312              :             END DO
    3313              :          END DO
    3314              :       ELSE
    3315              : 
    3316          318 :          DO local_kpoint = 1, kpmax
    3317              :             ! Every k-point group executes the same sequence of global transforms
    3318              :             ! up to the largest local k-point count (kp_dist can be uneven after
    3319              :             ! #5993). Only the group owning this local_kpoint receives the
    3320              :             ! redistributed matrix. The others participate through the dummy
    3321              :             ! destination. Groups without a k point in the last rounds still
    3322              :             ! join the service calls and skip their local solver work.
    3323              :             CALL kpoint_operator_get(op_ctx, local_kpoint, kpoint_spin_free, matrix_s_kp, &
    3324          188 :                                      cmat=workspace(1)%csmat_base, matrix_row=kpoint_spin_free)
    3325              : 
    3326          518 :             DO ispin = 1, nspin
    3327              :                CALL kpoint_operator_get(op_ctx, local_kpoint, ispin, matrix_ks_kp, &
    3328          200 :                                         cmat=workspace(1)%cksmat, matrix_row=ispin)
    3329          200 :                IF (local_kpoint > kplocal) CYCLE
    3330          200 :                kp => kpoints%kp_env(local_kpoint)%kpoint_env
    3331              : 
    3332          200 :                IF (scf_env%iter_count == 1 .AND. .NOT. kp%mos_prefilled) THEN
    3333              :                   ! first SCF step cold-starts by a direct diagonalization,
    3334              :                   ! same entry as the Davidson k-point path
    3335           14 :                   CALL cold_start_mo_init(kp, ispin, workspace(1)%cksmat, workspace(1)%csmat_base)
    3336           14 :                   CYCLE
    3337              :                END IF
    3338              : 
    3339              :                CALL lanczos_refine_channel(kp, ispin, scf_env, my_check_moconv_only, eps_iter, &
    3340          374 :                                            eps_iter_empty, max_iter, workspace(1), output_unit, .TRUE.)
    3341              :             END DO
    3342              :          END DO
    3343              :       END IF
    3344              : 
    3345              :       ! occupations and density: the shared exit chain. With
    3346              :       ! check_moconv_only the caller falls back to the standard k-point
    3347              :       ! diagonalization. That path supplies MOS and density, and the
    3348              :       ! statistics above are printed for information only
    3349          586 :       IF (.NOT. my_check_moconv_only) THEN
    3350          586 :          CALL kp_diag_exit_chain(kpoints, scf_env, scf_control, matrix_s_kp, sab_nl, fmwork, my_grow)
    3351          586 :          IF (my_grow .AND. PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
    3352              :       END IF
    3353              : 
    3354          586 :       CALL kp_diag_workspaces_release(workspace)
    3355          586 :       CALL kp_diag_finalize(qs_env, fmwork, op_ctx)
    3356              : 
    3357          586 :       IF (output_unit > 0 .AND. .NOT. my_check_moconv_only) THEN
    3358           28 :          WRITE (output_unit, "(T15,A/)") '<<<<<<<<< END LANCZOS REFINEMENT  <<<<<<<<<<'
    3359              :       END IF
    3360              :       CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
    3361          586 :                                         "PRINT%LANCZOS")
    3362              : 
    3363          586 :       CALL timestop(handle)
    3364              : 
    3365         1172 :    END SUBROUTINE do_block_krylov_diag_kp
    3366              : 
    3367              : ! **************************************************************************************************
    3368              : !> \brief Refine the MOS of one (k point, spin) channel. The routine
    3369              : !>        projects H(k) onto its Hermitian part, standardizes the channel
    3370              : !>        by the Cholesky factor of S(k), sweeps the single-pass kernel,
    3371              : !>        and writes the MOS back to the MO sets. The caller owns every
    3372              : !>        matrix. The routine allocates no CP2K matrix.
    3373              : !> \param kp k-point environment holding the MOS pair of the channel
    3374              : !> \param ispin spin component
    3375              : !> \param scf_env SCF environment holding the Krylov settings
    3376              : !> \param check_moconv_only only run the entry Rayleigh-Ritz of the kernel
    3377              : !>        and report the convergence count
    3378              : !> \param eps_iter convergence threshold of the occupied columns
    3379              : !> \param eps_iter_empty relaxed threshold of the unoccupied columns
    3380              : !> \param max_iter sweeps allowed per channel
    3381              : !> \param work driver workspace of the channel. cksmat holds the
    3382              : !>        complex H(k), standardized in place. csmat_base holds the
    3383              : !>        untouched S(k). csmat holds its work copy and the Cholesky
    3384              : !>        factor after the standardization. cwork holds the
    3385              : !>        Hermitian-projection scratch. cmos holds the MOS in the
    3386              : !>        standardized basis. lan_ws holds the kernel scratch
    3387              : !> \param output_unit unit of the refinement table. A nonpositive unit
    3388              : !>        disables every report
    3389              : !> \param print_row report this channel in the refinement table and in
    3390              : !>        the not-converged warnings. The local-kpoint path passes
    3391              : !>        .FALSE. and reports nothing, like the local phase of the
    3392              : !>        general k-point diagonalization
    3393              : ! **************************************************************************************************
    3394          764 :    SUBROUTINE lanczos_refine_channel(kp, ispin, scf_env, check_moconv_only, eps_iter, eps_iter_empty, &
    3395              :                                      max_iter, work, output_unit, print_row)
    3396              :       TYPE(kpoint_env_type), POINTER                     :: kp
    3397              :       INTEGER, INTENT(IN)                                :: ispin
    3398              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    3399              :       LOGICAL, INTENT(IN)                                :: check_moconv_only
    3400              :       REAL(KIND=dp), INTENT(IN)                          :: eps_iter, eps_iter_empty
    3401              :       INTEGER, INTENT(IN)                                :: max_iter
    3402              :       TYPE(kp_diag_workspace_type), INTENT(INOUT)        :: work
    3403              :       INTEGER, INTENT(IN)                                :: output_unit
    3404              :       LOGICAL, INTENT(IN)                                :: print_row
    3405              : 
    3406              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'lanczos_refine_channel'
    3407              : 
    3408              :       INTEGER                                            :: handle, iter, nmo, nmo_conv, nmo_nc
    3409              :       LOGICAL                                            :: any_refined, converged, need_suffix_rr, &
    3410              :                                                             next_need_suffix_rr, step_refined
    3411              :       REAL(KIND=dp)                                      :: max_res, min_res, t1, t2
    3412              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eps_col
    3413          764 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues, occupation
    3414              :       TYPE(cp_cfm_type), POINTER                         :: cmo_coeff
    3415              : 
    3416          764 :       CALL timeset(routineN, handle)
    3417              : 
    3418              :       CALL get_mo_set(mo_set=kp%mos(ispin), nmo=nmo, &
    3419              :                       eigenvalues=mo_eigenvalues, occupation_numbers=occupation, &
    3420          764 :                       cmo_coeff=cmo_coeff)
    3421              : 
    3422          764 :       CALL cp_cfm_to_cfm(work%csmat_base, work%csmat)
    3423              : 
    3424              :       ! H(k) is Hermitian only to grid accuracy and the kernel forms its
    3425              :       ! residuals with the full matrix: project onto the Hermitian part
    3426              :       ! once per channel
    3427          764 :       CALL cp_cfm_transpose(work%cksmat, "C", work%cwork)
    3428              :       CALL cp_cfm_scale_and_add(CMPLX(0.5_dp, 0.0_dp, KIND=dp), work%cksmat, &
    3429          764 :                                 CMPLX(0.5_dp, 0.0_dp, KIND=dp), work%cwork)
    3430              : 
    3431              :       ! complex MOS of the channel
    3432          764 :       CALL cp_cfm_to_cfm(cmo_coeff, work%cmos)
    3433              : 
    3434              :       ! standardization S(k) = U^dag U: operator and MOS are pulled
    3435              :       ! through the same transform, X = U C and A = U^-dag H U^-1, so
    3436              :       ! the kernel faces a standard eigenproblem. CHOLESKY OFF is not
    3437              :       ! supported on this path
    3438          764 :       CALL cp_cfm_cholesky_decompose(work%csmat)
    3439          764 :       CALL cp_cfm_triangular_multiply(work%csmat, work%cksmat, side="R", invert_tr=.TRUE.)
    3440          764 :       CALL cp_cfm_triangular_multiply(work%csmat, work%cksmat, side="L", transa_tr="C", invert_tr=.TRUE.)
    3441          764 :       CALL cp_cfm_triangular_multiply(work%csmat, work%cmos, side="L", invert_tr=.FALSE.)
    3442              : 
    3443              :       ! per-column thresholds: the occupation decides which columns
    3444              :       ! qualify for the relaxed empty threshold
    3445         2292 :       ALLOCATE (eps_col(nmo))
    3446          764 :       CALL kp_eps_col_by_occupation(occupation, eps_iter, eps_iter_empty, eps_col)
    3447              : 
    3448          764 :       converged = .FALSE.
    3449          764 :       any_refined = .FALSE.
    3450          764 :       need_suffix_rr = .FALSE.
    3451              : 
    3452          764 :       t1 = m_walltime()
    3453              :       CALL lanczos_channel_begin(work%cksmat, work%cmos, mo_eigenvalues, eps_col, &
    3454              :                                  work%lan_ws, max_res, min_res, nmo_conv, nmo_nc, &
    3455          764 :                                  check_moconv_only=check_moconv_only)
    3456          764 :       IF (check_moconv_only) THEN
    3457            0 :          DEALLOCATE (eps_col)
    3458            0 :          IF (print_row .AND. output_unit > 0) THEN
    3459              :             WRITE (output_unit, '(T8,I3,T16,I5,T24,I6,T33,E12.4,2x,E12.4)') &
    3460            0 :                ispin, 0, nmo_conv, max_res, min_res
    3461              :          END IF
    3462            0 :          CALL timestop(handle)
    3463              :          RETURN
    3464              :       END IF
    3465              : 
    3466          764 :       IF (nmo_nc == 0) THEN
    3467          170 :          t2 = m_walltime()
    3468          170 :          IF (print_row .AND. output_unit > 0 .AND. max_iter >= 1) THEN
    3469              :             WRITE (output_unit, '(T8,I3,T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
    3470            1 :                ispin, 1, nmo_conv, max_res, min_res, t2 - t1
    3471              :          END IF
    3472              :          converged = .TRUE.
    3473              :       ELSE
    3474         1044 :          DO iter = 1, max_iter
    3475          839 :             IF (iter > 1) t1 = m_walltime()
    3476              :             CALL lanczos_sweep_suffix(work%cksmat, work%cmos, mo_eigenvalues, eps_col, &
    3477              :                                       scf_env%krylov_settings%nkrylov, scf_env%krylov_settings%nblock, &
    3478              :                                       iter == 1, need_suffix_rr, work%lan_ws, &
    3479              :                                       max_res, min_res, nmo_conv, nmo_nc, step_refined, &
    3480          839 :                                       next_need_suffix_rr)
    3481          839 :             need_suffix_rr = next_need_suffix_rr
    3482          839 :             any_refined = any_refined .OR. step_refined
    3483          839 :             t2 = m_walltime()
    3484          839 :             IF (print_row .AND. output_unit > 0) THEN
    3485              :                WRITE (output_unit, '(T8,I3,T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
    3486           48 :                   ispin, iter, nmo_conv, max_res, min_res, t2 - t1
    3487              :             END IF
    3488         1044 :             IF (nmo_nc == 0) THEN
    3489              :                converged = .TRUE.
    3490              :                EXIT
    3491              :             END IF
    3492              :          END DO
    3493              :       END IF
    3494          764 :       DEALLOCATE (eps_col)
    3495              : 
    3496          764 :       IF (any_refined) THEN
    3497          594 :          CALL lanczos_channel_end(work%cmos, work%lan_ws)
    3498              :       END IF
    3499          764 :       IF (.NOT. converged .AND. print_row .AND. output_unit > 0) THEN
    3500              :          WRITE (output_unit, "(T4, A)") " WARNING Lanczos refinement could "// &
    3501           20 :             "not converge all the mos:"
    3502           20 :          WRITE (output_unit, "(T40,A,T70,I10)") " number of not converged mos ", nmo_nc
    3503           20 :          WRITE (output_unit, "(T40,A,T70,E10.2)") " max norm of the residual ", max_res
    3504              :       END IF
    3505              : 
    3506              :       ! rotate the refined MOS back into the generalized problem, C = U^-1 X
    3507          764 :       CALL cp_cfm_triangular_multiply(work%csmat, work%cmos, side="L", invert_tr=.TRUE.)
    3508          764 :       CALL cp_cfm_to_cfm(work%cmos, cmo_coeff)
    3509              : 
    3510          764 :       CALL timestop(handle)
    3511         1528 :    END SUBROUTINE lanczos_refine_channel
    3512              : 
    3513              : ! **************************************************************************************************
    3514              : !> \brief first-SCF-step initialization of the K-point MOS of one spin by one
    3515              : !>        direct diagonalization of H(k); both arguments are assembled by the
    3516              : !>        caller because cp_cfm_geeig overwrites them
    3517              : !> \param kp kpoint environment holding the complex MO set
    3518              : !> \param ispin ...
    3519              : !> \param cksmat complex H(k), assembled by the caller
    3520              : !> \param csmat complex S(k), assembled by the caller
    3521              : ! **************************************************************************************************
    3522          452 :    SUBROUTINE cold_start_mo_init(kp, ispin, cksmat, csmat)
    3523              : 
    3524              :       TYPE(kpoint_env_type), POINTER                     :: kp
    3525              :       INTEGER, INTENT(IN)                                :: ispin
    3526              :       TYPE(cp_cfm_type)                                  :: cksmat, csmat
    3527              : 
    3528              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'cold_start_mo_init'
    3529              : 
    3530              :       INTEGER                                            :: handle
    3531          113 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues
    3532              :       TYPE(cp_cfm_type)                                  :: chwork, cswork, cwork
    3533              : 
    3534          113 :       CALL timeset(routineN, handle)
    3535              : 
    3536          113 :       CALL get_mo_set(kp%mos(ispin), eigenvalues=eigenvalues)
    3537              :       ! cp_cfm_geeig overwrites its matrix arguments: solve on scratch
    3538              :       ! copies so the caller H(k)/S(k) stay valid
    3539          113 :       CALL cp_cfm_create(chwork, cksmat%matrix_struct, name="kp_cold_h")
    3540          113 :       CALL cp_cfm_create(cswork, csmat%matrix_struct, name="kp_cold_s")
    3541          113 :       CALL cp_cfm_to_cfm(cksmat, chwork)
    3542          113 :       CALL cp_cfm_to_cfm(csmat, cswork)
    3543          113 :       CALL cp_cfm_create(cwork, cksmat%matrix_struct, name="kp_cold_work")
    3544          113 :       CALL cp_cfm_geeig(chwork, cswork, kp%mos(ispin)%cmo_coeff, eigenvalues, cwork)
    3545          113 :       CALL cp_cfm_release(chwork)
    3546          113 :       CALL cp_cfm_release(cswork)
    3547          113 :       CALL cp_cfm_release(cwork)
    3548              : 
    3549          113 :       CALL timestop(handle)
    3550              : 
    3551          113 :    END SUBROUTINE cold_start_mo_init
    3552              : 
    3553              : ! **************************************************************************************************
    3554              : !> \brief builds one complex K-point preconditioner per (local kpoint, spin)
    3555              : !>        channel; mirrors prepare_qs_ot_kpoint_preconditioners
    3556              : !> \param qs_env ...
    3557              : !> \param scf_env ...
    3558              : !> \param matrix_ks_kp ...
    3559              : !> \param matrix_s_kp ...
    3560              : !> \param kpoints ...
    3561              : !> \param op_ctx ...
    3562              : ! **************************************************************************************************
    3563           56 :    SUBROUTINE davidson_kp_prepare_preconditioners( &
    3564              :       qs_env, scf_env, matrix_ks_kp, matrix_s_kp, kpoints, op_ctx)
    3565              : 
    3566              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3567              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    3568              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks_kp, matrix_s_kp
    3569              :       TYPE(kpoint_type), POINTER                         :: kpoints
    3570              :       TYPE(kpoint_operator_context_type)                 :: op_ctx
    3571              : 
    3572              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'davidson_kp_prepare_preconditioners'
    3573              : 
    3574              :       INTEGER                                            :: channel, handle, ispin, kplocal, kpmax, &
    3575              :                                                             local_kpoint, nchannels, nmo, nspin, &
    3576              :                                                             prec_type, solver_type
    3577              :       INTEGER, DIMENSION(2)                              :: kp_range
    3578           56 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
    3579           56 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    3580              :       REAL(KIND=dp)                                      :: energy_gap
    3581           56 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues
    3582           56 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    3583              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    3584              :       TYPE(cp_cfm_type)                                  :: matrix_c, matrix_h, matrix_s
    3585           56 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_t_kp
    3586              :       TYPE(dbcsr_type), POINTER                          :: matrix_h_im, matrix_h_re, matrix_s_im, &
    3587              :                                                             matrix_s_re, matrix_t_im, matrix_t_re
    3588              :       TYPE(kpoint_env_type), POINTER                     :: kp
    3589              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    3590              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    3591           56 :          POINTER                                         :: sab_nl
    3592              : 
    3593           56 :       CALL timeset(routineN, handle)
    3594              : 
    3595              :       CALL get_kpoint_info(kpoints, kp_range=kp_range, kp_dist=kp_dist, xkp=xkp, sab_nl=sab_nl, &
    3596           56 :                            cell_to_index=cell_to_index)
    3597           56 :       CALL get_qs_env(qs_env, kinetic_kp=matrix_t_kp)
    3598              :       ! the preconditioner fms must live on the kpoint-group BLACS context,
    3599              :       ! the context of the MOS they are applied with
    3600           56 :       blacs_env => kpoints%blacs_env
    3601           56 :       para_env => kpoints%para_env_kp
    3602           56 :       kplocal = kp_range(2) - kp_range(1) + 1
    3603          148 :       kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
    3604           56 :       nspin = SIZE(matrix_ks_kp, 1)
    3605           56 :       nchannels = kplocal*nspin
    3606           56 :       prec_type = scf_env%block_davidson_env(1)%prec_type
    3607           56 :       solver_type = scf_env%block_davidson_env(1)%solver_type
    3608           56 :       energy_gap = scf_env%block_davidson_env(1)%energy_gap
    3609              : 
    3610              :       ! channel storage: every (kpoint, spin) channel carries its own
    3611              :       ! preconditioner, because S(k) and H(k) differ per kpoint. The Gamma
    3612              :       ! reuse pattern of restart_preconditioner (a single entry for the
    3613              :       ! spin-independent types) must not be used here.
    3614           56 :       IF (ASSOCIATED(scf_env%ot_preconditioner)) THEN
    3615          114 :          DO channel = 1, SIZE(scf_env%ot_preconditioner)
    3616          114 :             IF (ASSOCIATED(scf_env%ot_preconditioner(channel)%preconditioner)) THEN
    3617           78 :                CALL destroy_preconditioner(scf_env%ot_preconditioner(channel)%preconditioner)
    3618           78 :                DEALLOCATE (scf_env%ot_preconditioner(channel)%preconditioner)
    3619              :             END IF
    3620              :          END DO
    3621           36 :          DEALLOCATE (scf_env%ot_preconditioner)
    3622           36 :          NULLIFY (scf_env%ot_preconditioner)
    3623              :       END IF
    3624          292 :       ALLOCATE (scf_env%ot_preconditioner(nchannels))
    3625          180 :       DO channel = 1, nchannels
    3626          620 :          ALLOCATE (scf_env%ot_preconditioner(channel)%preconditioner)
    3627              :          CALL init_preconditioner(scf_env%ot_preconditioner(channel)%preconditioner, &
    3628          180 :                                   para_env, blacs_env)
    3629              :       END DO
    3630              : 
    3631           56 :       NULLIFY (eigenvalues, matrix_h_im, matrix_h_re, matrix_s_im, matrix_s_re, &
    3632           56 :                matrix_t_im, matrix_t_re)
    3633           56 :       IF (prec_type == ot_precond_full_kinetic) THEN
    3634           28 :          CPASSERT(ASSOCIATED(matrix_t_kp))
    3635           28 :          CALL kpoint_operator_prepare(op_ctx, matrix_t_kp, kpoint_slot_t, matrix_row=kpoint_spin_free)
    3636              :       END IF
    3637              : 
    3638          176 :       DO local_kpoint = 1, kpmax
    3639              :          ! S(k) is spin independent. Build it with the same global-group
    3640              :          ! redistribution protocol as the Davidson operator itself, directly
    3641              :          ! as the group-local block-cyclic DBCSR pair of the preconditioner
    3642              :          ! makers.
    3643          120 :          CALL dbcsr_init_p(matrix_s_re)
    3644          120 :          CALL dbcsr_init_p(matrix_s_im)
    3645              :          CALL kpoint_operator_get(op_ctx, local_kpoint, kpoint_spin_free, matrix_s_kp, &
    3646              :                                   mat_re=matrix_s_re, mat_im=matrix_s_im, &
    3647          120 :                                   matrix_row=kpoint_spin_free, slot=kpoint_slot_s)
    3648              : 
    3649          120 :          IF (prec_type == ot_precond_full_kinetic) THEN
    3650           56 :             CALL dbcsr_init_p(matrix_t_re)
    3651           56 :             CALL dbcsr_init_p(matrix_t_im)
    3652              :             CALL kpoint_operator_get(op_ctx, local_kpoint, kpoint_spin_free, matrix_t_kp, &
    3653              :                                      mat_re=matrix_t_re, mat_im=matrix_t_im, &
    3654           56 :                                      matrix_row=kpoint_spin_free, slot=kpoint_slot_t)
    3655              :          END IF
    3656              : 
    3657          244 :          DO ispin = 1, nspin
    3658          124 :             IF (prec_type == ot_precond_full_all .OR. prec_type == ot_precond_full_single_inverse) THEN
    3659           52 :                CALL dbcsr_init_p(matrix_h_re)
    3660           52 :                CALL dbcsr_init_p(matrix_h_im)
    3661              :                CALL kpoint_operator_get(op_ctx, local_kpoint, ispin, matrix_ks_kp, &
    3662           52 :                                         mat_re=matrix_h_re, mat_im=matrix_h_im, matrix_row=ispin, slot=kpoint_slot_ks)
    3663              :             END IF
    3664          124 :             IF (local_kpoint <= kplocal) THEN
    3665          124 :                kp => kpoints%kp_env(local_kpoint)%kpoint_env
    3666          124 :                channel = (local_kpoint - 1)*nspin + ispin
    3667          124 :                IF (prec_type == ot_precond_full_all .OR. prec_type == ot_precond_full_single_inverse) THEN
    3668              :                   ! Davidson iterates the full MO set, so its active space is all nmo
    3669              :                   ! MOs of the channel: assemble the complex channel matrices on the
    3670              :                   ! kpoint-group context and call the complex H-based cores directly
    3671              :                   ! (mirrors the complex preconditioners of the K-point OT case; the
    3672              :                   ! FULL_SINGLE_INVERSE variant trades the state selectivity of
    3673              :                   ! FULL_ALL for one shifted factorization and a gemm application)
    3674              :                   CALL get_mo_set(kp%mos(ispin), eigenvalues=eigenvalues, &
    3675           52 :                                   nmo=nmo)
    3676           52 :                   CALL cp_cfm_create(matrix_c, kp%mos(ispin)%cmo_coeff%matrix_struct, name="dav pc C")
    3677           52 :                   CALL cp_cfm_to_cfm(kp%mos(ispin)%cmo_coeff, matrix_c)
    3678              :                   CALL dbcsr_pair_to_cfm(matrix_h_re, matrix_h_im, &
    3679              :                                          scf_env%ot_preconditioner(channel)%preconditioner, &
    3680           52 :                                          'dav pc H', matrix_h)
    3681              :                   CALL dbcsr_pair_to_cfm(matrix_s_re, matrix_s_im, &
    3682              :                                          scf_env%ot_preconditioner(channel)%preconditioner, &
    3683           52 :                                          'dav pc S', matrix_s)
    3684           52 :                   IF (prec_type == ot_precond_full_all) THEN
    3685              :                      CALL make_complex_full_all(scf_env%ot_preconditioner(channel)%preconditioner, &
    3686              :                                                 matrix_c, matrix_h, matrix_s, eigenvalues(1:nmo), &
    3687           36 :                                                 energy_gap)
    3688              :                   ELSE
    3689              :                      CALL make_complex_full_single_inverse( &
    3690              :                         scf_env%ot_preconditioner(channel)%preconditioner, &
    3691           16 :                         matrix_c, matrix_h, matrix_s, energy_gap)
    3692              :                   END IF
    3693           52 :                   CALL cp_cfm_release(matrix_c)
    3694           52 :                   CALL cp_cfm_release(matrix_h)
    3695           52 :                   CALL cp_cfm_release(matrix_s)
    3696           72 :                ELSE IF (prec_type == ot_precond_full_kinetic) THEN
    3697              :                   CALL make_preconditioner_complex_full_kinetic( &
    3698              :                      scf_env%ot_preconditioner(channel)%preconditioner, &
    3699           56 :                      matrix_t_re, matrix_t_im, matrix_s_re, matrix_s_im, energy_gap, solver_type)
    3700           16 :                ELSE IF (prec_type == ot_precond_s_inverse) THEN
    3701              :                   CALL make_preconditioner_complex_full_s_inverse( &
    3702              :                      scf_env%ot_preconditioner(channel)%preconditioner, &
    3703           16 :                      matrix_s_re, matrix_s_im, solver_type)
    3704              :                END IF
    3705              :             END IF
    3706          244 :             IF (prec_type == ot_precond_full_all .OR. prec_type == ot_precond_full_single_inverse) THEN
    3707           52 :                CALL dbcsr_release_p(matrix_h_re)
    3708           52 :                CALL dbcsr_release_p(matrix_h_im)
    3709              :             END IF
    3710              :          END DO
    3711              : 
    3712          120 :          CALL dbcsr_release_p(matrix_s_re)
    3713          120 :          CALL dbcsr_release_p(matrix_s_im)
    3714          176 :          IF (prec_type == ot_precond_full_kinetic) THEN
    3715           56 :             CALL dbcsr_release_p(matrix_t_re)
    3716           56 :             CALL dbcsr_release_p(matrix_t_im)
    3717              :          END IF
    3718              :       END DO
    3719              : 
    3720           56 :       CALL timestop(handle)
    3721              : 
    3722           56 :    END SUBROUTINE davidson_kp_prepare_preconditioners
    3723              : 
    3724              : ! **************************************************************************************************
    3725              : !> \brief Kpoint diagonalization routine
    3726              : !>        Transforms matrices to kpoint, distributes kpoint groups, performs diagonalization
    3727              : !> \param matrix_s     Overlap matrices (RS indices, global)
    3728              : !> \param kpoints      Kpoint environment
    3729              : !> \param fmwork       full matrices distributed over all groups
    3730              : !> \param lowdin_forces retain the overlap spectrum for Lowdin force/stress derivatives
    3731              : !> \par History
    3732              : !>      02.2026 created [JGH]
    3733              : ! **************************************************************************************************
    3734          134 :    SUBROUTINE diag_kp_smat(matrix_s, kpoints, fmwork, lowdin_forces)
    3735              : 
    3736              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_s
    3737              :       TYPE(kpoint_type), POINTER                         :: kpoints
    3738              :       TYPE(cp_fm_type), DIMENSION(:)                     :: fmwork
    3739              :       LOGICAL, INTENT(IN), OPTIONAL                      :: lowdin_forces
    3740              : 
    3741              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'diag_kp_smat'
    3742              :       COMPLEX(KIND=dp), PARAMETER                        :: cone = (1.0_dp, 0.0_dp), &
    3743              :                                                             czero = (0.0_dp, 0.0_dp)
    3744              : 
    3745              :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: ceig
    3746              :       INTEGER                                            :: handle, ikp, kplocal, kpmax, nao
    3747              :       INTEGER, DIMENSION(2)                              :: kp_range
    3748          134 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
    3749              :       LOGICAL                                            :: save_spectrum, use_real_wfn
    3750              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenvalues
    3751              :       TYPE(cp_cfm_type)                                  :: csmat, cwork
    3752              :       TYPE(cp_fm_pool_type), POINTER                     :: ao_ao_fm_pool
    3753              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    3754              :       TYPE(cp_fm_type)                                   :: fmlocal, rsmat
    3755              :       TYPE(kpoint_env_type), POINTER                     :: kp
    3756          134 :       TYPE(kpoint_operator_context_type)                 :: op_ctx
    3757              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    3758          134 :          POINTER                                         :: sab_nl
    3759              :       TYPE(qs_matrix_pools_type), POINTER                :: mpools
    3760              : 
    3761          134 :       CALL timeset(routineN, handle)
    3762              : 
    3763          134 :       NULLIFY (sab_nl)
    3764              :       CALL get_kpoint_info(kpoints, use_real_wfn=use_real_wfn, kp_range=kp_range, &
    3765          134 :                            kp_dist=kp_dist, sab_nl=sab_nl)
    3766          134 :       CPASSERT(ASSOCIATED(sab_nl))
    3767          134 :       kplocal = kp_range(2) - kp_range(1) + 1
    3768          390 :       kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
    3769              : 
    3770              :       ! fm pools to be used within a kpoint group
    3771          134 :       CALL get_kpoint_info(kpoints, mpools=mpools)
    3772          134 :       CALL mpools_get(mpools, ao_ao_fm_pool=ao_ao_fm_pool)
    3773              : 
    3774          134 :       CALL fm_pool_create_fm(ao_ao_fm_pool, fmlocal)
    3775          134 :       CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
    3776              : 
    3777          134 :       IF (use_real_wfn) THEN
    3778            0 :          CALL cp_fm_create(rsmat, matrix_struct)
    3779              :       ELSE
    3780          134 :          CALL cp_cfm_create(csmat, matrix_struct)
    3781          134 :          CALL cp_cfm_create(cwork, matrix_struct)
    3782              :       END IF
    3783              : 
    3784          134 :       CALL cp_fm_get_info(fmwork(1), nrow_global=nao)
    3785          670 :       ALLOCATE (eigenvalues(nao), ceig(nao))
    3786              : 
    3787              :       ! The overlap is spin free: the routine drives every instance under the
    3788              :       ! single spin-free key.
    3789          134 :       CALL kpoint_operator_context_create(op_ctx, kpoints, fmwork(1), 1)
    3790          134 :       CALL kpoint_operator_prepare(op_ctx, matrix_s, kpoint_slot_s, matrix_row=kpoint_spin_free)
    3791          634 :       DO ikp = 1, kpmax
    3792              :          CALL kpoint_operator_start(op_ctx, ikp, kpoint_spin_free, matrix_s, kpoint_slot_s, &
    3793          634 :                                     use_grid=.FALSE., matrix_row=kpoint_spin_free)
    3794              :       END DO
    3795              : 
    3796              :       ! Finish communication then diagonalise in each group
    3797          634 :       DO ikp = 1, kpmax
    3798          500 :          IF (use_real_wfn) THEN
    3799            0 :             CALL kpoint_operator_finish(op_ctx, ikp, kpoint_spin_free, kpoint_slot_s, fm_re=rsmat)
    3800              :          ELSE
    3801          500 :             CALL kpoint_operator_finish(op_ctx, ikp, kpoint_spin_free, kpoint_slot_s, csmat)
    3802              :          END IF
    3803              : 
    3804              :          ! Each kpoint group has now information on a kpoint to be diagonalized
    3805              :          ! Eigensolver Hermite or Symmetric
    3806          500 :          IF (ikp > kplocal) CYCLE
    3807          500 :          kp => kpoints%kp_env(ikp)%kpoint_env
    3808          500 :          save_spectrum = ALLOCATED(kp%lowdin_sqrt)
    3809          500 :          IF (PRESENT(lowdin_forces)) save_spectrum = lowdin_forces
    3810          500 :          CALL cp_cfm_release(kp%lowdin_evec)
    3811          500 :          IF (ALLOCATED(kp%lowdin_sqrt)) DEALLOCATE (kp%lowdin_sqrt)
    3812          500 :          IF (use_real_wfn) THEN
    3813            0 :             CALL choose_eigv_solver(rsmat, fmlocal, eigenvalues)
    3814              :          ELSE
    3815          500 :             CALL cp_cfm_heevd(csmat, cwork, eigenvalues)
    3816              :          END IF
    3817         8600 :          CPASSERT(ALL(eigenvalues(1:nao) >= 0.0_dp))
    3818          500 :          IF (save_spectrum) THEN
    3819          384 :             IF (ANY(eigenvalues <= 0.0_dp)) THEN
    3820            0 :                CPABORT("Lowdin forces require a positive definite overlap")
    3821              :             END IF
    3822           32 :             ALLOCATE (kp%lowdin_sqrt(nao))
    3823          384 :             kp%lowdin_sqrt(:) = SQRT(eigenvalues)
    3824           16 :             CALL cp_cfm_create(kp%lowdin_evec, matrix_struct)
    3825           16 :             IF (use_real_wfn) THEN
    3826            0 :                CALL cp_fm_to_cfm(fmlocal, mtarget=kp%lowdin_evec)
    3827              :             ELSE
    3828           16 :                CALL cp_cfm_to_cfm(cwork, kp%lowdin_evec)
    3829              :             END IF
    3830              :          END IF
    3831          634 :          IF (use_real_wfn) THEN
    3832            0 :             CALL cp_fm_release(kp%shalf)
    3833            0 :             CALL cp_fm_create(kp%shalf, matrix_struct)
    3834            0 :             eigenvalues(1:nao) = SQRT(eigenvalues(1:nao))
    3835            0 :             CALL cp_fm_to_fm(fmlocal, rsmat)
    3836            0 :             CALL cp_fm_column_scale(rsmat, eigenvalues)
    3837              :             CALL parallel_gemm("N", "T", nao, nao, nao, 1.0_dp, rsmat, fmlocal, &
    3838            0 :                                0.0_dp, kp%shalf)
    3839              :          ELSE
    3840          500 :             CALL cp_cfm_release(kp%cshalf)
    3841          500 :             CALL cp_cfm_create(kp%cshalf, matrix_struct)
    3842         8600 :             ceig(1:nao) = SQRT(eigenvalues(1:nao))
    3843          500 :             CALL cp_cfm_to_cfm(cwork, csmat)
    3844          500 :             CALL cp_cfm_column_scale(csmat, ceig)
    3845              :             CALL parallel_gemm("N", "C", nao, nao, nao, cone, csmat, cwork, &
    3846          500 :                                czero, kp%cshalf)
    3847              :          END IF
    3848              :       END DO
    3849              : 
    3850          134 :       CALL kpoint_operator_context_release(op_ctx)
    3851              : 
    3852              :       ! All done
    3853          134 :       DEALLOCATE (eigenvalues, ceig)
    3854              : 
    3855          134 :       IF (use_real_wfn) THEN
    3856            0 :          CALL cp_fm_release(rsmat)
    3857              :       ELSE
    3858          134 :          CALL cp_cfm_release(csmat)
    3859          134 :          CALL cp_cfm_release(cwork)
    3860              :       END IF
    3861          134 :       CALL fm_pool_give_back_fm(ao_ao_fm_pool, fmlocal)
    3862              : 
    3863          134 :       CALL timestop(handle)
    3864              : 
    3865          536 :    END SUBROUTINE diag_kp_smat
    3866              : 
    3867              : END MODULE qs_scf_diagonalization
        

Generated by: LCOV version 2.0-1