LCOV - code coverage report
Current view: top level - src - qs_scf_diagonalization.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:ba1d7ca) Lines: 73.9 % 1473 1088
Test Date: 2026-09-09 06:35:33 Functions: 68.0 % 25 17

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

Generated by: LCOV version 2.0-1