LCOV - code coverage report
Current view: top level - src - qs_scf_diagonalization.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:5064cfc) Lines: 74.9 % 768 575
Test Date: 2026-03-04 06:45:10 Functions: 90.9 % 11 10

            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_cfm_basic_linalg,             ONLY: cp_cfm_column_scale,&
      18              :                                               cp_cfm_scale_and_add,&
      19              :                                               cp_cfm_scale_and_add_fm
      20              :    USE cp_cfm_diag,                     ONLY: cp_cfm_geeig,&
      21              :                                               cp_cfm_geeig_canon,&
      22              :                                               cp_cfm_heevd
      23              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      24              :                                               cp_cfm_release,&
      25              :                                               cp_cfm_set_all,&
      26              :                                               cp_cfm_to_cfm,&
      27              :                                               cp_cfm_to_fm,&
      28              :                                               cp_cfm_type
      29              :    USE cp_control_types,                ONLY: dft_control_type,&
      30              :                                               hairy_probes_type
      31              :    USE cp_dbcsr_api,                    ONLY: &
      32              :         dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_desymmetrize, dbcsr_p_type, &
      33              :         dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, &
      34              :         dbcsr_type_symmetric
      35              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      36              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      37              :                                               copy_fm_to_dbcsr,&
      38              :                                               cp_dbcsr_sm_fm_multiply,&
      39              :                                               dbcsr_allocate_matrix_set
      40              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      41              :                                               cp_fm_symm,&
      42              :                                               cp_fm_uplo_to_full
      43              :    USE cp_fm_cholesky,                  ONLY: cp_fm_cholesky_reduce,&
      44              :                                               cp_fm_cholesky_restore
      45              :    USE cp_fm_diag,                      ONLY: FM_DIAG_TYPE_CUSOLVER,&
      46              :                                               choose_eigv_solver,&
      47              :                                               cp_fm_geeig,&
      48              :                                               cp_fm_geeig_canon,&
      49              :                                               cusolver_generalized,&
      50              :                                               diag_type
      51              :    USE cp_fm_pool_types,                ONLY: cp_fm_pool_p_type,&
      52              :                                               fm_pool_create_fm,&
      53              :                                               fm_pool_give_back_fm
      54              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      55              :                                               cp_fm_struct_release,&
      56              :                                               cp_fm_struct_type
      57              :    USE cp_fm_types,                     ONLY: &
      58              :         copy_info_type, cp_fm_add_to_element, cp_fm_cleanup_copy_general, cp_fm_create, &
      59              :         cp_fm_finish_copy_general, cp_fm_get_info, cp_fm_release, cp_fm_start_copy_general, &
      60              :         cp_fm_to_fm, cp_fm_type
      61              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      62              :                                               cp_logger_type
      63              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      64              :                                               cp_print_key_unit_nr
      65              :    USE input_constants,                 ONLY: &
      66              :         cholesky_dbcsr, cholesky_inverse, cholesky_off, cholesky_reduce, cholesky_restore, &
      67              :         core_guess, general_roks, high_spin_roks, restart_guess
      68              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      69              :                                               section_vals_type
      70              :    USE kinds,                           ONLY: dp
      71              :    USE kpoint_methods,                  ONLY: kpoint_density_matrices,&
      72              :                                               kpoint_density_transform,&
      73              :                                               kpoint_set_mo_occupation,&
      74              :                                               rskp_transform
      75              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      76              :                                               kpoint_env_type,&
      77              :                                               kpoint_type
      78              :    USE machine,                         ONLY: m_flush,&
      79              :                                               m_walltime
      80              :    USE mathconstants,                   ONLY: gaussi,&
      81              :                                               z_one,&
      82              :                                               z_zero
      83              :    USE message_passing,                 ONLY: mp_para_env_type
      84              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      85              :    USE preconditioner,                  ONLY: prepare_preconditioner,&
      86              :                                               restart_preconditioner
      87              :    USE qs_density_matrices,             ONLY: calculate_density_matrix
      88              :    USE qs_density_mixing_types,         ONLY: direct_mixing_nr,&
      89              :                                               gspace_mixing_nr
      90              :    USE qs_diis,                         ONLY: qs_diis_b_calc_err_kp,&
      91              :                                               qs_diis_b_info_kp,&
      92              :                                               qs_diis_b_step,&
      93              :                                               qs_diis_b_step_kp
      94              :    USE qs_energy_types,                 ONLY: qs_energy_type
      95              :    USE qs_environment_types,            ONLY: get_qs_env,&
      96              :                                               qs_environment_type
      97              :    USE qs_gspace_mixing,                ONLY: gspace_mixing
      98              :    USE qs_ks_methods,                   ONLY: qs_ks_update_qs_env
      99              :    USE qs_ks_types,                     ONLY: qs_ks_did_change,&
     100              :                                               qs_ks_env_type
     101              :    USE qs_matrix_pools,                 ONLY: mpools_get,&
     102              :                                               qs_matrix_pools_type
     103              :    USE qs_mixing_utils,                 ONLY: charge_mixing_init,&
     104              :                                               mixing_allocate,&
     105              :                                               mixing_init,&
     106              :                                               self_consistency_check
     107              :    USE qs_mo_methods,                   ONLY: calculate_subspace_eigenvalues
     108              :    USE qs_mo_occupation,                ONLY: set_mo_occupation
     109              :    USE qs_mo_types,                     ONLY: get_mo_set,&
     110              :                                               mo_set_type
     111              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
     112              :    USE qs_ot_eigensolver,               ONLY: ot_eigensolver
     113              :    USE qs_rho_atom_types,               ONLY: rho_atom_type
     114              :    USE qs_rho_methods,                  ONLY: qs_rho_update_rho
     115              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
     116              :                                               qs_rho_type
     117              :    USE qs_scf_block_davidson,           ONLY: generate_extended_space,&
     118              :                                               generate_extended_space_sparse
     119              :    USE qs_scf_lanczos,                  ONLY: lanczos_refinement,&
     120              :                                               lanczos_refinement_2v
     121              :    USE qs_scf_methods,                  ONLY: combine_ks_matrices,&
     122              :                                               eigensolver,&
     123              :                                               eigensolver_dbcsr,&
     124              :                                               eigensolver_generalized,&
     125              :                                               eigensolver_simple,&
     126              :                                               eigensolver_symm,&
     127              :                                               scf_env_density_mixing
     128              :    USE qs_scf_types,                    ONLY: qs_scf_env_type,&
     129              :                                               subspace_env_type
     130              :    USE scf_control_types,               ONLY: scf_control_type
     131              : #include "./base/base_uses.f90"
     132              : 
     133              :    IMPLICIT NONE
     134              : 
     135              :    PRIVATE
     136              : 
     137              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_diagonalization'
     138              : 
     139              :    PUBLIC :: do_general_diag, do_general_diag_kp, do_roks_diag, &
     140              :              do_special_diag, do_ot_diag, do_block_davidson_diag, &
     141              :              do_block_krylov_diag, do_scf_diag_subspace, diag_subspace_allocate, &
     142              :              general_eigenproblem, diag_kp_smat
     143              : 
     144              : CONTAINS
     145              : 
     146              : ! **************************************************************************************************
     147              : !> \brief the inner loop of scf, specific to diagonalization with S matrix
     148              : !>       basically, in goes the ks matrix out goes a new p matrix
     149              : !> \param scf_env ...
     150              : !> \param mos ...
     151              : !> \param matrix_ks ...
     152              : !> \param matrix_s ...
     153              : !> \param scf_control ...
     154              : !> \param scf_section ...
     155              : !> \param diis_step ...
     156              : !> \par History
     157              : !>      03.2006 created [Joost VandeVondele]
     158              : ! **************************************************************************************************
     159              : 
     160        77173 :    SUBROUTINE general_eigenproblem(scf_env, mos, matrix_ks, &
     161              :                                    matrix_s, scf_control, scf_section, &
     162              :                                    diis_step)
     163              : 
     164              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     165              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos
     166              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     167              :       TYPE(scf_control_type), POINTER                    :: scf_control
     168              :       TYPE(section_vals_type), POINTER                   :: scf_section
     169              :       LOGICAL, INTENT(INOUT)                             :: diis_step
     170              : 
     171              :       INTEGER                                            :: ispin, nspin
     172              :       LOGICAL                                            :: do_level_shift, owns_ortho, use_jacobi
     173              :       REAL(KIND=dp)                                      :: diis_error, eps_diis
     174              :       TYPE(cp_fm_type), POINTER                          :: ortho
     175              :       TYPE(dbcsr_type), POINTER                          :: ortho_dbcsr
     176              : 
     177        77173 :       nspin = SIZE(matrix_ks)
     178        77173 :       NULLIFY (ortho, ortho_dbcsr)
     179              : 
     180       164266 :       DO ispin = 1, nspin
     181              :          CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, &
     182       164266 :                                scf_env%scf_work1(ispin))
     183              :       END DO
     184              : 
     185        77173 :       eps_diis = scf_control%eps_diis
     186              : 
     187        77173 :       IF (scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis) THEN
     188              :          CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
     189              :                              scf_env%scf_work2, scf_env%iter_delta, diis_error, diis_step, &
     190              :                              eps_diis, scf_control%nmixing, &
     191              :                              s_matrix=matrix_s, &
     192        64397 :                              scf_section=scf_section)
     193              :       ELSE
     194        12776 :          diis_step = .FALSE.
     195              :       END IF
     196              : 
     197              :       do_level_shift = ((scf_control%level_shift /= 0.0_dp) .AND. &
     198              :                         ((scf_control%density_guess == core_guess) .OR. &
     199        77173 :                          (scf_env%iter_count > 1)))
     200              : 
     201        77173 :       IF ((scf_env%iter_count > 1) .AND. &
     202              :           (scf_env%iter_delta < scf_control%diagonalization%eps_jacobi)) THEN
     203            0 :          use_jacobi = .TRUE.
     204              :       ELSE
     205        77173 :          use_jacobi = .FALSE.
     206              :       END IF
     207              : 
     208        77173 :       IF (diis_step) THEN
     209        45595 :          scf_env%iter_param = diis_error
     210        45595 :          IF (use_jacobi) THEN
     211            0 :             scf_env%iter_method = "DIIS/Jacobi"
     212              :          ELSE
     213        45595 :             scf_env%iter_method = "DIIS/Diag."
     214              :          END IF
     215              :       ELSE
     216        31578 :          IF (scf_env%mixing_method == 0) THEN
     217            0 :             scf_env%iter_method = "NoMix/Diag."
     218        31578 :          ELSE IF (scf_env%mixing_method == 1) THEN
     219        30164 :             scf_env%iter_param = scf_env%p_mix_alpha
     220        30164 :             IF (use_jacobi) THEN
     221            0 :                scf_env%iter_method = "P_Mix/Jacobi"
     222              :             ELSE
     223        30164 :                scf_env%iter_method = "P_Mix/Diag."
     224              :             END IF
     225         1414 :          ELSEIF (scf_env%mixing_method > 1) THEN
     226         1414 :             scf_env%iter_param = scf_env%mixing_store%alpha
     227         1414 :             IF (use_jacobi) THEN
     228            0 :                scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Jacobi"
     229              :             ELSE
     230         1414 :                scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
     231              :             END IF
     232              :          END IF
     233              :       END IF
     234              : 
     235        77173 :       IF (scf_env%cholesky_method == cholesky_dbcsr) THEN
     236         1064 :          ortho_dbcsr => scf_env%ortho_dbcsr
     237         3182 :          DO ispin = 1, nspin
     238              :             CALL eigensolver_dbcsr(matrix_ks=matrix_ks(ispin)%matrix, matrix_ks_fm=scf_env%scf_work1(ispin), &
     239              :                                    mo_set=mos(ispin), &
     240              :                                    ortho_dbcsr=ortho_dbcsr, &
     241         3182 :                                    ksbuf1=scf_env%buf1_dbcsr, ksbuf2=scf_env%buf2_dbcsr)
     242              :          END DO
     243              : 
     244        76109 :       ELSE IF (scf_env%cholesky_method > cholesky_off) THEN
     245        75683 :          IF (scf_env%cholesky_method == cholesky_inverse) THEN
     246          144 :             ortho => scf_env%ortho_m1
     247              :          ELSE
     248        75539 :             ortho => scf_env%ortho
     249              :          END IF
     250              : 
     251        75683 :          owns_ortho = .FALSE.
     252        75683 :          IF (.NOT. ASSOCIATED(ortho)) THEN
     253            0 :             ALLOCATE (ortho)
     254            0 :             owns_ortho = .TRUE.
     255              :          END IF
     256              : 
     257       160150 :          DO ispin = 1, nspin
     258       160150 :             IF (diag_type == FM_DIAG_TYPE_CUSOLVER .AND. cusolver_generalized .AND. .NOT. do_level_shift) THEN
     259              :                CALL eigensolver_generalized(matrix_ks_fm=scf_env%scf_work1(ispin), &
     260              :                                             matrix_s=matrix_s(ispin)%matrix, &
     261              :                                             mo_set=mos(ispin), &
     262            0 :                                             work=scf_env%scf_work2)
     263              :             ELSE
     264        84467 :                IF (do_level_shift) THEN
     265              :                   CALL eigensolver(matrix_ks_fm=scf_env%scf_work1(ispin), &
     266              :                                    mo_set=mos(ispin), &
     267              :                                    ortho=ortho, &
     268              :                                    work=scf_env%scf_work2, &
     269              :                                    cholesky_method=scf_env%cholesky_method, &
     270              :                                    do_level_shift=do_level_shift, &
     271              :                                    level_shift=scf_control%level_shift, &
     272              :                                    matrix_u_fm=scf_env%ortho, &
     273          124 :                                    use_jacobi=use_jacobi)
     274              :                ELSE
     275              :                   CALL eigensolver(matrix_ks_fm=scf_env%scf_work1(ispin), &
     276              :                                    mo_set=mos(ispin), &
     277              :                                    ortho=ortho, &
     278              :                                    work=scf_env%scf_work2, &
     279              :                                    cholesky_method=scf_env%cholesky_method, &
     280              :                                    do_level_shift=do_level_shift, &
     281              :                                    level_shift=scf_control%level_shift, &
     282        84343 :                                    use_jacobi=use_jacobi)
     283              :                END IF
     284              :             END IF
     285              :          END DO
     286              : 
     287        75683 :          IF (owns_ortho) DEALLOCATE (ortho)
     288              :       ELSE
     289          426 :          ortho => scf_env%ortho
     290              : 
     291          426 :          owns_ortho = .FALSE.
     292          426 :          IF (.NOT. ASSOCIATED(ortho)) THEN
     293            0 :             ALLOCATE (ortho)
     294            0 :             owns_ortho = .TRUE.
     295              :          END IF
     296              : 
     297          426 :          IF (do_level_shift) THEN
     298          172 :          DO ispin = 1, nspin
     299              :          IF (ASSOCIATED(scf_env%scf_work1_red) .AND. ASSOCIATED(scf_env%scf_work2_red) &
     300          172 :              .AND. ASSOCIATED(scf_env%ortho_red) .AND. ASSOCIATED(scf_env%ortho_m1_red)) THEN
     301              :             CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
     302              :                                   mo_set=mos(ispin), &
     303              :                                   ortho=ortho, &
     304              :                                   work=scf_env%scf_work2, &
     305              :                                   do_level_shift=do_level_shift, &
     306              :                                   level_shift=scf_control%level_shift, &
     307              :                                   matrix_u_fm=scf_env%ortho_m1, &
     308              :                                   use_jacobi=use_jacobi, &
     309              :                                   jacobi_threshold=scf_control%diagonalization%jacobi_threshold, &
     310              :                                   matrix_ks_fm_red=scf_env%scf_work1_red(ispin), &
     311              :                                   ortho_red=scf_env%ortho_red, &
     312              :                                   work_red=scf_env%scf_work2_red, &
     313           86 :                                   matrix_u_fm_red=scf_env%ortho_m1_red)
     314              :          ELSE
     315              :             CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
     316              :                                   mo_set=mos(ispin), &
     317              :                                   ortho=ortho, &
     318              :                                   work=scf_env%scf_work2, &
     319              :                                   do_level_shift=do_level_shift, &
     320              :                                   level_shift=scf_control%level_shift, &
     321              :                                   matrix_u_fm=scf_env%ortho_m1, &
     322              :                                   use_jacobi=use_jacobi, &
     323            0 :                                   jacobi_threshold=scf_control%diagonalization%jacobi_threshold)
     324              :          END IF
     325              :          END DO
     326              :          ELSE
     327          762 :          DO ispin = 1, nspin
     328              :          IF (ASSOCIATED(scf_env%scf_work1_red) .AND. ASSOCIATED(scf_env%scf_work2_red) &
     329          762 :              .AND. ASSOCIATED(scf_env%ortho_red)) THEN
     330              :             CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
     331              :                                   mo_set=mos(ispin), &
     332              :                                   ortho=ortho, &
     333              :                                   work=scf_env%scf_work2, &
     334              :                                   do_level_shift=do_level_shift, &
     335              :                                   level_shift=scf_control%level_shift, &
     336              :                                   use_jacobi=use_jacobi, &
     337              :                                   jacobi_threshold=scf_control%diagonalization%jacobi_threshold, &
     338              :                                   matrix_ks_fm_red=scf_env%scf_work1_red(ispin), &
     339              :                                   ortho_red=scf_env%ortho_red, &
     340          422 :                                   work_red=scf_env%scf_work2_red)
     341              :          ELSE
     342              :             CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
     343              :                                   mo_set=mos(ispin), &
     344              :                                   ortho=ortho, &
     345              :                                   work=scf_env%scf_work2, &
     346              :                                   do_level_shift=do_level_shift, &
     347              :                                   level_shift=scf_control%level_shift, &
     348              :                                   use_jacobi=use_jacobi, &
     349            0 :                                   jacobi_threshold=scf_control%diagonalization%jacobi_threshold)
     350              :          END IF
     351              :          END DO
     352              :          END IF
     353              : 
     354          426 :          IF (owns_ortho) DEALLOCATE (ortho)
     355              :       END IF
     356              : 
     357        77173 :    END SUBROUTINE general_eigenproblem
     358              : 
     359              : ! **************************************************************************************************
     360              : !> \brief ...
     361              : !> \param scf_env ...
     362              : !> \param mos ...
     363              : !> \param matrix_ks ...
     364              : !> \param matrix_s ...
     365              : !> \param scf_control ...
     366              : !> \param scf_section ...
     367              : !> \param diis_step ...
     368              : !> \param probe ...
     369              : ! **************************************************************************************************
     370        76145 :    SUBROUTINE do_general_diag(scf_env, mos, matrix_ks, &
     371              :                               matrix_s, scf_control, scf_section, &
     372              :                               diis_step, probe)
     373              : 
     374              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     375              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
     376              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     377              :       TYPE(scf_control_type), POINTER                    :: scf_control
     378              :       TYPE(section_vals_type), POINTER                   :: scf_section
     379              :       LOGICAL, INTENT(INOUT)                             :: diis_step
     380              :       TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
     381              :          POINTER                                         :: probe
     382              : 
     383              :       INTEGER                                            :: ispin, nspin
     384              :       REAL(KIND=dp)                                      :: total_zeff_corr
     385              : 
     386        76145 :       nspin = SIZE(matrix_ks)
     387              : 
     388              :       CALL general_eigenproblem(scf_env, mos, matrix_ks, &
     389        76145 :                                 matrix_s, scf_control, scf_section, diis_step)
     390              : 
     391              :       total_zeff_corr = 0.0_dp
     392        76145 :       total_zeff_corr = scf_env%sum_zeff_corr
     393              : 
     394        76145 :       IF (ABS(total_zeff_corr) > 0.0_dp) THEN
     395              :          CALL set_mo_occupation(mo_array=mos, &
     396           40 :                                 smear=scf_control%smear, tot_zeff_corr=total_zeff_corr)
     397              :       ELSE
     398        76105 :          IF (PRESENT(probe) .EQV. .TRUE.) THEN
     399           14 :             scf_control%smear%do_smear = .FALSE.
     400              :             CALL set_mo_occupation(mo_array=mos, &
     401              :                                    smear=scf_control%smear, &
     402           14 :                                    probe=probe)
     403              :          ELSE
     404              :             CALL set_mo_occupation(mo_array=mos, &
     405        76091 :                                    smear=scf_control%smear)
     406              :          END IF
     407              :       END IF
     408              : 
     409       161182 :       DO ispin = 1, nspin
     410              :          CALL calculate_density_matrix(mos(ispin), &
     411       161182 :                                        scf_env%p_mix_new(ispin, 1)%matrix)
     412              :       END DO
     413              : 
     414        76145 :    END SUBROUTINE do_general_diag
     415              : 
     416              : ! **************************************************************************************************
     417              : !> \brief Kpoint diagonalization routine
     418              : !>        Transforms matrices to kpoint, distributes kpoint groups, performs
     419              : !>        general diagonalization (no storgae of overlap decomposition), stores
     420              : !>        MOs, calculates occupation numbers, calculates density matrices
     421              : !>        in kpoint representation, transforms density matrices to real space
     422              : !> \param matrix_ks    Kohn-sham matrices (RS indices, global)
     423              : !> \param matrix_s     Overlap matrices (RS indices, global)
     424              : !> \param kpoints      Kpoint environment
     425              : !> \param scf_env      SCF environment
     426              : !> \param scf_control  SCF control variables
     427              : !> \param update_p ...
     428              : !> \param diis_step ...
     429              : !> \param diis_error ...
     430              : !> \param qs_env ...
     431              : !> \param probe ...
     432              : !> \par History
     433              : !>      08.2014 created [JGH]
     434              : ! **************************************************************************************************
     435         5676 :    SUBROUTINE do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, update_p, &
     436              :                                  diis_step, diis_error, qs_env, probe)
     437              : 
     438              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks, matrix_s
     439              :       TYPE(kpoint_type), POINTER                         :: kpoints
     440              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     441              :       TYPE(scf_control_type), POINTER                    :: scf_control
     442              :       LOGICAL, INTENT(IN)                                :: update_p
     443              :       LOGICAL, INTENT(INOUT)                             :: diis_step
     444              :       REAL(dp), INTENT(INOUT), OPTIONAL                  :: diis_error
     445              :       TYPE(qs_environment_type), OPTIONAL, POINTER       :: qs_env
     446              :       TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
     447              :          POINTER                                         :: probe
     448              : 
     449              :       CHARACTER(len=*), PARAMETER :: routineN = 'do_general_diag_kp'
     450              : 
     451         5676 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: coeffs
     452              :       INTEGER                                            :: handle, ib, igroup, ik, ikp, indx, &
     453              :                                                             ispin, jb, kplocal, nb, nkp, &
     454              :                                                             nkp_groups, nspin
     455              :       INTEGER, DIMENSION(2)                              :: kp_range
     456         5676 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
     457         5676 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     458              :       LOGICAL                                            :: do_diis, my_kpgrp, use_real_wfn
     459         5676 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues
     460         5676 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
     461         5676 :       TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:, :) :: info
     462              :       TYPE(cp_cfm_type)                                  :: cksmat, cmos, csmat, cwork
     463         5676 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_ao_fm_pools
     464              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct, mo_struct
     465              :       TYPE(cp_fm_type)                                   :: fmdummy, fmlocal, rksmat, rsmat
     466         5676 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
     467              :       TYPE(cp_fm_type), POINTER                          :: imos, mo_coeff, rmos
     468              :       TYPE(dbcsr_type), POINTER                          :: cmatrix, rmatrix, tmpmat
     469              :       TYPE(kpoint_env_type), POINTER                     :: kp
     470              :       TYPE(mp_para_env_type), POINTER                    :: para_env, para_env_global
     471              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     472         5676 :          POINTER                                         :: sab_nl
     473              :       TYPE(qs_matrix_pools_type), POINTER                :: mpools
     474              :       TYPE(section_vals_type), POINTER                   :: scf_section
     475              : 
     476         5676 :       CALL timeset(routineN, handle)
     477              : 
     478         5676 :       NULLIFY (sab_nl)
     479              :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, use_real_wfn=use_real_wfn, kp_range=kp_range, &
     480              :                            nkp_groups=nkp_groups, kp_dist=kp_dist, sab_nl=sab_nl, &
     481         5676 :                            cell_to_index=cell_to_index)
     482         5676 :       CPASSERT(ASSOCIATED(sab_nl))
     483         5676 :       kplocal = kp_range(2) - kp_range(1) + 1
     484              : 
     485              :       !Whether we use DIIS for k-points
     486         5676 :       do_diis = .FALSE.
     487              :       IF (scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis .AND. .NOT. use_real_wfn &
     488         5676 :           .AND. PRESENT(diis_error) .AND. PRESENT(qs_env)) do_diis = .TRUE.
     489              : 
     490              :       ! allocate some work matrices
     491         5676 :       ALLOCATE (rmatrix, cmatrix, tmpmat)
     492              :       CALL dbcsr_create(rmatrix, template=matrix_ks(1, 1)%matrix, &
     493         5676 :                         matrix_type=dbcsr_type_symmetric)
     494              :       CALL dbcsr_create(cmatrix, template=matrix_ks(1, 1)%matrix, &
     495         5676 :                         matrix_type=dbcsr_type_antisymmetric)
     496              :       CALL dbcsr_create(tmpmat, template=matrix_ks(1, 1)%matrix, &
     497         5676 :                         matrix_type=dbcsr_type_no_symmetry)
     498         5676 :       CALL cp_dbcsr_alloc_block_from_nbl(rmatrix, sab_nl)
     499         5676 :       CALL cp_dbcsr_alloc_block_from_nbl(cmatrix, sab_nl)
     500              : 
     501         5676 :       fmwork => scf_env%scf_work1
     502              : 
     503              :       ! fm pools to be used within a kpoint group
     504         5676 :       CALL get_kpoint_info(kpoints, mpools=mpools)
     505         5676 :       CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
     506              : 
     507         5676 :       CALL fm_pool_create_fm(ao_ao_fm_pools(1)%pool, fmlocal)
     508         5676 :       CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
     509              : 
     510         5676 :       IF (use_real_wfn) THEN
     511           52 :          CALL cp_fm_create(rksmat, matrix_struct)
     512           52 :          CALL cp_fm_create(rsmat, matrix_struct)
     513              :       ELSE
     514         5624 :          CALL cp_cfm_create(cksmat, matrix_struct)
     515         5624 :          CALL cp_cfm_create(csmat, matrix_struct)
     516         5624 :          CALL cp_cfm_create(cwork, matrix_struct)
     517         5624 :          kp => kpoints%kp_env(1)%kpoint_env
     518         5624 :          CALL get_mo_set(kp%mos(1, 1), mo_coeff=mo_coeff)
     519         5624 :          CALL cp_fm_get_info(mo_coeff, matrix_struct=mo_struct)
     520         5624 :          CALL cp_cfm_create(cmos, mo_struct)
     521              :       END IF
     522              : 
     523         5676 :       para_env => kpoints%blacs_env_all%para_env
     524         5676 :       nspin = SIZE(matrix_ks, 1)
     525       185404 :       ALLOCATE (info(kplocal*nspin*nkp_groups, 4))
     526              : 
     527              :       ! Setup and start all the communication
     528         5676 :       indx = 0
     529        21136 :       DO ikp = 1, kplocal
     530        38488 :          DO ispin = 1, nspin
     531        57878 :             DO igroup = 1, nkp_groups
     532              :                ! number of current kpoint
     533        25066 :                ik = kp_dist(1, igroup) + ikp - 1
     534        25066 :                my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
     535        25066 :                indx = indx + 1
     536        25066 :                IF (use_real_wfn) THEN
     537              :                   ! FT of matrices KS and S, then transfer to FM type
     538           62 :                   CALL dbcsr_set(rmatrix, 0.0_dp)
     539              :                   CALL rskp_transform(rmatrix=rmatrix, rsmat=matrix_ks, ispin=ispin, &
     540           62 :                                       xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_nl)
     541           62 :                   CALL dbcsr_desymmetrize(rmatrix, tmpmat)
     542           62 :                   CALL copy_dbcsr_to_fm(tmpmat, fmwork(1))
     543              :                   ! s matrix is not spin dependent
     544           62 :                   CALL dbcsr_set(rmatrix, 0.0_dp)
     545              :                   CALL rskp_transform(rmatrix=rmatrix, rsmat=matrix_s, ispin=1, &
     546           62 :                                       xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_nl)
     547           62 :                   CALL dbcsr_desymmetrize(rmatrix, tmpmat)
     548           62 :                   CALL copy_dbcsr_to_fm(tmpmat, fmwork(3))
     549              :                ELSE
     550              :                   ! FT of matrices KS and S, then transfer to FM type
     551        25004 :                   CALL dbcsr_set(rmatrix, 0.0_dp)
     552        25004 :                   CALL dbcsr_set(cmatrix, 0.0_dp)
     553              :                   CALL rskp_transform(rmatrix=rmatrix, cmatrix=cmatrix, rsmat=matrix_ks, ispin=ispin, &
     554        25004 :                                       xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_nl)
     555        25004 :                   CALL dbcsr_desymmetrize(rmatrix, tmpmat)
     556        25004 :                   CALL copy_dbcsr_to_fm(tmpmat, fmwork(1))
     557        25004 :                   CALL dbcsr_desymmetrize(cmatrix, tmpmat)
     558        25004 :                   CALL copy_dbcsr_to_fm(tmpmat, fmwork(2))
     559              :                   ! s matrix is not spin dependent, double the work
     560        25004 :                   CALL dbcsr_set(rmatrix, 0.0_dp)
     561        25004 :                   CALL dbcsr_set(cmatrix, 0.0_dp)
     562              :                   CALL rskp_transform(rmatrix=rmatrix, cmatrix=cmatrix, rsmat=matrix_s, ispin=1, &
     563        25004 :                                       xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_nl)
     564        25004 :                   CALL dbcsr_desymmetrize(rmatrix, tmpmat)
     565        25004 :                   CALL copy_dbcsr_to_fm(tmpmat, fmwork(3))
     566        25004 :                   CALL dbcsr_desymmetrize(cmatrix, tmpmat)
     567        25004 :                   CALL copy_dbcsr_to_fm(tmpmat, fmwork(4))
     568              :                END IF
     569              :                ! transfer to kpoint group
     570              :                ! redistribution of matrices, new blacs environment
     571              :                ! fmwork -> fmlocal -> rksmat/cksmat
     572              :                ! fmwork -> fmlocal -> rsmat/csmat
     573        42418 :                IF (use_real_wfn) THEN
     574           62 :                   IF (my_kpgrp) THEN
     575           62 :                      CALL cp_fm_start_copy_general(fmwork(1), rksmat, para_env, info(indx, 1))
     576           62 :                      CALL cp_fm_start_copy_general(fmwork(3), rsmat, para_env, info(indx, 2))
     577              :                   ELSE
     578            0 :                      CALL cp_fm_start_copy_general(fmwork(1), fmdummy, para_env, info(indx, 1))
     579            0 :                      CALL cp_fm_start_copy_general(fmwork(3), fmdummy, para_env, info(indx, 2))
     580              :                   END IF
     581              :                ELSE
     582        25004 :                   IF (my_kpgrp) THEN
     583        17290 :                      CALL cp_fm_start_copy_general(fmwork(1), fmlocal, para_env, info(indx, 1))
     584        17290 :                      CALL cp_fm_start_copy_general(fmwork(2), fmlocal, para_env, info(indx, 2))
     585        17290 :                      CALL cp_fm_start_copy_general(fmwork(3), fmlocal, para_env, info(indx, 3))
     586        17290 :                      CALL cp_fm_start_copy_general(fmwork(4), fmlocal, para_env, info(indx, 4))
     587              :                   ELSE
     588         7714 :                      CALL cp_fm_start_copy_general(fmwork(1), fmdummy, para_env, info(indx, 1))
     589         7714 :                      CALL cp_fm_start_copy_general(fmwork(2), fmdummy, para_env, info(indx, 2))
     590         7714 :                      CALL cp_fm_start_copy_general(fmwork(3), fmdummy, para_env, info(indx, 3))
     591         7714 :                      CALL cp_fm_start_copy_general(fmwork(4), fmdummy, para_env, info(indx, 4))
     592              :                   END IF
     593              :                END IF
     594              :             END DO
     595              :          END DO
     596              :       END DO
     597              : 
     598              :       ! Finish communication then diagonalise in each group
     599         5676 :       IF (do_diis) THEN
     600         4068 :          CALL get_qs_env(qs_env, para_env=para_env_global)
     601         4068 :          scf_section => section_vals_get_subs_vals(qs_env%input, "DFT%SCF")
     602         4068 :          CALL qs_diis_b_info_kp(kpoints%scf_diis_buffer, ib, nb)
     603         4068 :          indx = 0
     604        13484 :          DO ikp = 1, kplocal
     605        24302 :             DO ispin = 1, nspin
     606        25894 :                DO igroup = 1, nkp_groups
     607              :                   ! number of current kpoint
     608        15076 :                   ik = kp_dist(1, igroup) + ikp - 1
     609        15076 :                   my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
     610         4258 :                   indx = indx + 1
     611        10818 :                   IF (my_kpgrp) THEN
     612        10818 :                      CALL cp_fm_finish_copy_general(fmlocal, info(indx, 1))
     613        10818 :                      CALL cp_cfm_scale_and_add_fm(z_zero, cksmat, z_one, fmlocal)
     614        10818 :                      CALL cp_fm_finish_copy_general(fmlocal, info(indx, 2))
     615        10818 :                      CALL cp_cfm_scale_and_add_fm(z_one, cksmat, gaussi, fmlocal)
     616        10818 :                      CALL cp_fm_finish_copy_general(fmlocal, info(indx, 3))
     617        10818 :                      CALL cp_cfm_scale_and_add_fm(z_zero, csmat, z_one, fmlocal)
     618        10818 :                      CALL cp_fm_finish_copy_general(fmlocal, info(indx, 4))
     619        10818 :                      CALL cp_cfm_scale_and_add_fm(z_one, csmat, gaussi, fmlocal)
     620              :                   END IF
     621              :                END DO  !igroup
     622              : 
     623        10818 :                kp => kpoints%kp_env(ikp)%kpoint_env
     624              :                CALL qs_diis_b_calc_err_kp(kpoints%scf_diis_buffer, ib, kp%mos, cksmat, csmat, &
     625        20234 :                                           ispin, ikp, kplocal, scf_section)
     626              : 
     627              :             END DO !ispin
     628              :          END DO !ikp
     629              : 
     630        12204 :          ALLOCATE (coeffs(nb))
     631              :          CALL qs_diis_b_step_kp(kpoints%scf_diis_buffer, coeffs, ib, nb, scf_env%iter_delta, diis_error, &
     632              :                                 diis_step, scf_control%eps_diis, nspin, nkp, kplocal, scf_control%nmixing, &
     633         4068 :                                 scf_section, para_env_global)
     634              : 
     635              :          !build the ks matrices and idagonalize
     636        17552 :          DO ikp = 1, kplocal
     637        24302 :             DO ispin = 1, nspin
     638        10818 :                kp => kpoints%kp_env(ikp)%kpoint_env
     639        10818 :                CALL cp_cfm_to_cfm(kpoints%scf_diis_buffer%smat(ikp), csmat)
     640              : 
     641        10818 :                CALL cp_cfm_set_all(cksmat, z_zero)
     642        42200 :                DO jb = 1, nb
     643        42200 :                   CALL cp_cfm_scale_and_add(z_one, cksmat, coeffs(jb), kpoints%scf_diis_buffer%param(jb, ispin, ikp))
     644              :                END DO
     645              : 
     646        10818 :                CALL get_mo_set(kp%mos(1, ispin), mo_coeff=rmos, eigenvalues=eigenvalues)
     647        10818 :                CALL get_mo_set(kp%mos(2, ispin), mo_coeff=imos)
     648        10818 :                IF (scf_env%cholesky_method == cholesky_off) THEN
     649              :                   CALL cp_cfm_geeig_canon(cksmat, csmat, cmos, eigenvalues, cwork, &
     650           16 :                                           scf_control%eps_eigval)
     651              :                ELSE
     652        10802 :                   CALL cp_cfm_geeig(cksmat, csmat, cmos, eigenvalues, cwork)
     653              :                END IF
     654              :                ! copy eigenvalues to imag set (keep them in sync)
     655       242748 :                kp%mos(2, ispin)%eigenvalues = eigenvalues
     656              :                ! split real and imaginary part of mos
     657        20234 :                CALL cp_cfm_to_fm(cmos, rmos, imos)
     658              :             END DO
     659              :          END DO
     660              : 
     661              :       ELSE !no DIIS
     662         1608 :          diis_step = .FALSE.
     663         1608 :          indx = 0
     664         7652 :          DO ikp = 1, kplocal
     665        14186 :             DO ispin = 1, nspin
     666        16524 :                DO igroup = 1, nkp_groups
     667              :                   ! number of current kpoint
     668         9990 :                   ik = kp_dist(1, igroup) + ikp - 1
     669         9990 :                   my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
     670         3456 :                   indx = indx + 1
     671         6534 :                   IF (my_kpgrp) THEN
     672         6534 :                      IF (use_real_wfn) THEN
     673           62 :                         CALL cp_fm_finish_copy_general(rksmat, info(indx, 1))
     674           62 :                         CALL cp_fm_finish_copy_general(rsmat, info(indx, 2))
     675              :                      ELSE
     676         6472 :                         CALL cp_fm_finish_copy_general(fmlocal, info(indx, 1))
     677         6472 :                         CALL cp_cfm_scale_and_add_fm(z_zero, cksmat, z_one, fmlocal)
     678         6472 :                         CALL cp_fm_finish_copy_general(fmlocal, info(indx, 2))
     679         6472 :                         CALL cp_cfm_scale_and_add_fm(z_one, cksmat, gaussi, fmlocal)
     680         6472 :                         CALL cp_fm_finish_copy_general(fmlocal, info(indx, 3))
     681         6472 :                         CALL cp_cfm_scale_and_add_fm(z_zero, csmat, z_one, fmlocal)
     682         6472 :                         CALL cp_fm_finish_copy_general(fmlocal, info(indx, 4))
     683         6472 :                         CALL cp_cfm_scale_and_add_fm(z_one, csmat, gaussi, fmlocal)
     684              :                      END IF
     685              :                   END IF
     686              :                END DO
     687              : 
     688              :                ! Each kpoint group has now information on a kpoint to be diagonalized
     689              :                ! General eigensolver Hermite or Symmetric
     690         6534 :                kp => kpoints%kp_env(ikp)%kpoint_env
     691        12578 :                IF (use_real_wfn) THEN
     692           62 :                   CALL get_mo_set(kp%mos(1, ispin), mo_coeff=mo_coeff, eigenvalues=eigenvalues)
     693           62 :                   IF (scf_env%cholesky_method == cholesky_off) THEN
     694              :                      CALL cp_fm_geeig_canon(rksmat, rsmat, mo_coeff, eigenvalues, fmlocal, &
     695           40 :                                             scf_control%eps_eigval)
     696              :                   ELSE
     697           22 :                      CALL cp_fm_geeig(rksmat, rsmat, mo_coeff, eigenvalues, fmlocal)
     698              :                   END IF
     699              :                ELSE
     700         6472 :                   CALL get_mo_set(kp%mos(1, ispin), mo_coeff=rmos, eigenvalues=eigenvalues)
     701         6472 :                   CALL get_mo_set(kp%mos(2, ispin), mo_coeff=imos)
     702         6472 :                   IF (scf_env%cholesky_method == cholesky_off) THEN
     703              :                      CALL cp_cfm_geeig_canon(cksmat, csmat, cmos, eigenvalues, cwork, &
     704          242 :                                              scf_control%eps_eigval)
     705              :                   ELSE
     706         6230 :                      CALL cp_cfm_geeig(cksmat, csmat, cmos, eigenvalues, cwork)
     707              :                   END IF
     708              :                   ! copy eigenvalues to imag set (keep them in sync)
     709       432284 :                   kp%mos(2, ispin)%eigenvalues = eigenvalues
     710              :                   ! split real and imaginary part of mos
     711         6472 :                   CALL cp_cfm_to_fm(cmos, rmos, imos)
     712              :                END IF
     713              :             END DO
     714              :          END DO
     715              :       END IF
     716              : 
     717              :       ! Clean up communication
     718         5676 :       indx = 0
     719        21136 :       DO ikp = 1, kplocal
     720        38488 :          DO ispin = 1, nspin
     721        57878 :             DO igroup = 1, nkp_groups
     722              :                ! number of current kpoint
     723        25066 :                ik = kp_dist(1, igroup) + ikp - 1
     724        25066 :                my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
     725        25066 :                indx = indx + 1
     726        42418 :                IF (use_real_wfn) THEN
     727           62 :                   CALL cp_fm_cleanup_copy_general(info(indx, 1))
     728           62 :                   CALL cp_fm_cleanup_copy_general(info(indx, 2))
     729              :                ELSE
     730        25004 :                   CALL cp_fm_cleanup_copy_general(info(indx, 1))
     731        25004 :                   CALL cp_fm_cleanup_copy_general(info(indx, 2))
     732        25004 :                   CALL cp_fm_cleanup_copy_general(info(indx, 3))
     733        25004 :                   CALL cp_fm_cleanup_copy_general(info(indx, 4))
     734              :                END IF
     735              :             END DO
     736              :          END DO
     737              :       END DO
     738              : 
     739              :       ! All done
     740       111616 :       DEALLOCATE (info)
     741              : 
     742         5676 :       IF (update_p) THEN
     743              :          ! MO occupations
     744         5666 :          IF (PRESENT(probe) .EQV. .TRUE.) THEN
     745            0 :             scf_control%smear%do_smear = .FALSE.
     746              :             CALL kpoint_set_mo_occupation(kpoints, scf_control%smear, &
     747            0 :                                           probe=probe)
     748              :          ELSE
     749         5666 :             CALL kpoint_set_mo_occupation(kpoints, scf_control%smear)
     750              :          END IF
     751              :          ! density matrices
     752         5666 :          CALL kpoint_density_matrices(kpoints)
     753              :          ! density matrices in real space
     754              :          CALL kpoint_density_transform(kpoints, scf_env%p_mix_new, .FALSE., &
     755         5666 :                                        matrix_s(1, 1)%matrix, sab_nl, fmwork)
     756              :       END IF
     757              : 
     758         5676 :       CALL dbcsr_deallocate_matrix(rmatrix)
     759         5676 :       CALL dbcsr_deallocate_matrix(cmatrix)
     760         5676 :       CALL dbcsr_deallocate_matrix(tmpmat)
     761              : 
     762         5676 :       IF (use_real_wfn) THEN
     763           52 :          CALL cp_fm_release(rksmat)
     764           52 :          CALL cp_fm_release(rsmat)
     765              :       ELSE
     766         5624 :          CALL cp_cfm_release(cksmat)
     767         5624 :          CALL cp_cfm_release(csmat)
     768         5624 :          CALL cp_cfm_release(cwork)
     769         5624 :          CALL cp_cfm_release(cmos)
     770              :       END IF
     771         5676 :       CALL fm_pool_give_back_fm(ao_ao_fm_pools(1)%pool, fmlocal)
     772              : 
     773         5676 :       CALL timestop(handle)
     774              : 
     775        17028 :    END SUBROUTINE do_general_diag_kp
     776              : 
     777              : ! **************************************************************************************************
     778              : !> \brief inner loop within MOS subspace, to refine occupation and density,
     779              : !>        before next diagonalization of the Hamiltonian
     780              : !> \param qs_env ...
     781              : !> \param scf_env ...
     782              : !> \param subspace_env ...
     783              : !> \param mos ...
     784              : !> \param rho ...
     785              : !> \param ks_env ...
     786              : !> \param scf_section ...
     787              : !> \param scf_control ...
     788              : !> \par History
     789              : !>      09.2009 created [MI]
     790              : !> \note  it is assumed that when diagonalization is used, also some mixing procedure is active
     791              : ! **************************************************************************************************
     792           10 :    SUBROUTINE do_scf_diag_subspace(qs_env, scf_env, subspace_env, mos, rho, &
     793              :                                    ks_env, scf_section, scf_control)
     794              : 
     795              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     796              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     797              :       TYPE(subspace_env_type), POINTER                   :: subspace_env
     798              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
     799              :       TYPE(qs_rho_type), POINTER                         :: rho
     800              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     801              :       TYPE(section_vals_type), POINTER                   :: scf_section
     802              :       TYPE(scf_control_type), POINTER                    :: scf_control
     803              : 
     804              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'do_scf_diag_subspace'
     805              :       REAL(KIND=dp), PARAMETER                           :: rone = 1.0_dp, rzero = 0.0_dp
     806              : 
     807              :       INTEGER                                            :: handle, i, iloop, ispin, nao, nmo, &
     808              :                                                             nspin, output_unit
     809              :       LOGICAL                                            :: converged
     810              :       REAL(dp)                                           :: ene_diff, ene_old, iter_delta, max_val, &
     811              :                                                             sum_band, sum_val, t1, t2
     812           10 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues, mo_occupations
     813           10 :       TYPE(cp_1d_r_p_type), ALLOCATABLE, DIMENSION(:)    :: eval_first, occ_first
     814              :       TYPE(cp_fm_type)                                   :: work
     815              :       TYPE(cp_fm_type), POINTER                          :: c0, chc, evec, mo_coeff
     816              :       TYPE(cp_logger_type), POINTER                      :: logger
     817           10 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s, rho_ao
     818           10 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
     819              :       TYPE(dft_control_type), POINTER                    :: dft_control
     820              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     821              :       TYPE(qs_energy_type), POINTER                      :: energy
     822           10 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho_atom
     823              : 
     824           10 :       CALL timeset(routineN, handle)
     825           10 :       NULLIFY (c0, chc, energy, evec, matrix_ks, mo_coeff, mo_eigenvalues, &
     826           10 :                mo_occupations, dft_control, rho_ao, rho_ao_kp)
     827              : 
     828           10 :       logger => cp_get_default_logger()
     829              :       output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DIAG_SUB_SCF", &
     830           10 :                                          extension=".scfLog")
     831              : 
     832              :       !Extra loop keeping mos unchanged and refining the subspace occupation
     833           10 :       nspin = SIZE(mos)
     834           10 :       CALL qs_rho_get(rho, rho_ao=rho_ao, rho_ao_kp=rho_ao_kp)
     835              : 
     836           40 :       ALLOCATE (eval_first(nspin))
     837           40 :       ALLOCATE (occ_first(nspin))
     838           20 :       DO ispin = 1, nspin
     839              :          CALL get_mo_set(mo_set=mos(ispin), &
     840              :                          nmo=nmo, &
     841              :                          eigenvalues=mo_eigenvalues, &
     842           10 :                          occupation_numbers=mo_occupations)
     843           30 :          ALLOCATE (eval_first(ispin)%array(nmo))
     844           20 :          ALLOCATE (occ_first(ispin)%array(nmo))
     845           50 :          eval_first(ispin)%array(1:nmo) = mo_eigenvalues(1:nmo)
     846           70 :          occ_first(ispin)%array(1:nmo) = mo_occupations(1:nmo)
     847              :       END DO
     848              : 
     849           20 :       DO ispin = 1, nspin
     850              :          ! does not yet handle k-points
     851           10 :          CALL dbcsr_copy(subspace_env%p_matrix_store(ispin)%matrix, rho_ao(ispin)%matrix)
     852           20 :          CALL dbcsr_copy(rho_ao(ispin)%matrix, scf_env%p_mix_new(ispin, 1)%matrix)
     853              :       END DO
     854              : 
     855           10 :       subspace_env%p_matrix_mix => scf_env%p_mix_new
     856              : 
     857           10 :       NULLIFY (matrix_ks, energy, para_env, matrix_s)
     858              :       CALL get_qs_env(qs_env, &
     859              :                       matrix_ks=matrix_ks, &
     860              :                       energy=energy, &
     861              :                       matrix_s=matrix_s, &
     862              :                       para_env=para_env, &
     863           10 :                       dft_control=dft_control)
     864              : 
     865              :       ! mixing storage allocation
     866           10 :       IF (subspace_env%mixing_method >= gspace_mixing_nr) THEN
     867              :          CALL mixing_allocate(qs_env, subspace_env%mixing_method, scf_env%p_mix_new, &
     868            0 :                               scf_env%p_delta, nspin, subspace_env%mixing_store)
     869            0 :          IF (dft_control%qs_control%gapw) THEN
     870            0 :             CALL get_qs_env(qs_env=qs_env, rho_atom_set=rho_atom)
     871              :             CALL mixing_init(subspace_env%mixing_method, rho, subspace_env%mixing_store, &
     872            0 :                              para_env, rho_atom=rho_atom)
     873            0 :          ELSEIF (dft_control%qs_control%dftb .OR. dft_control%qs_control%xtb) THEN
     874            0 :             CALL charge_mixing_init(subspace_env%mixing_store)
     875            0 :          ELSEIF (dft_control%qs_control%semi_empirical) THEN
     876            0 :             CPABORT('SE Code not possible')
     877              :          ELSE
     878            0 :             CALL mixing_init(subspace_env%mixing_method, rho, subspace_env%mixing_store, para_env)
     879              :          END IF
     880              :       END IF
     881              : 
     882           10 :       ene_old = 0.0_dp
     883           10 :       ene_diff = 0.0_dp
     884           10 :       IF (output_unit > 0) THEN
     885            0 :          WRITE (output_unit, "(/T19,A)") '<<<<<<<<<   SUBSPACE ROTATION    <<<<<<<<<<'
     886              :          WRITE (output_unit, "(T4,A,T13,A,T21,A,T38,A,T51,A,T65,A/,T4,A)") &
     887            0 :             "In-step", "Time", "Convergence", "Band ene.", "Total ene.", "Energy diff.", REPEAT("-", 74)
     888              :       END IF
     889              : 
     890              :       ! recalculate density matrix here
     891              : 
     892              :       ! update of density
     893           10 :       CALL qs_rho_update_rho(rho, qs_env=qs_env)
     894              : 
     895           22 :       DO iloop = 1, subspace_env%max_iter
     896           20 :          t1 = m_walltime()
     897           20 :          converged = .FALSE.
     898           20 :          ene_old = energy%total
     899              : 
     900           20 :          CALL qs_ks_did_change(ks_env, rho_changed=.TRUE.)
     901              :          CALL qs_ks_update_qs_env(qs_env, calculate_forces=.FALSE., &
     902           20 :                                   just_energy=.FALSE., print_active=.FALSE.)
     903              : 
     904           20 :          max_val = 0.0_dp
     905           20 :          sum_val = 0.0_dp
     906           20 :          sum_band = 0.0_dp
     907           40 :          DO ispin = 1, SIZE(matrix_ks)
     908              :             CALL get_mo_set(mo_set=mos(ispin), &
     909              :                             nao=nao, &
     910              :                             nmo=nmo, &
     911              :                             eigenvalues=mo_eigenvalues, &
     912              :                             occupation_numbers=mo_occupations, &
     913           20 :                             mo_coeff=mo_coeff)
     914              : 
     915              :             !compute C'HC
     916           20 :             chc => subspace_env%chc_mat(ispin)
     917           20 :             evec => subspace_env%c_vec(ispin)
     918           20 :             c0 => subspace_env%c0(ispin)
     919           20 :             CALL cp_fm_to_fm(mo_coeff, c0)
     920           20 :             CALL cp_fm_create(work, c0%matrix_struct)
     921           20 :             CALL cp_dbcsr_sm_fm_multiply(matrix_ks(ispin)%matrix, c0, work, nmo)
     922           20 :             CALL parallel_gemm('T', 'N', nmo, nmo, nao, rone, c0, work, rzero, chc)
     923           20 :             CALL cp_fm_release(work)
     924              :             !diagonalize C'HC
     925           20 :             CALL choose_eigv_solver(chc, evec, mo_eigenvalues)
     926              : 
     927              :             !rotate the mos by the eigenvectors of C'HC
     928           20 :             CALL parallel_gemm('N', 'N', nao, nmo, nmo, rone, c0, evec, rzero, mo_coeff)
     929              : 
     930              :             CALL set_mo_occupation(mo_set=mos(ispin), &
     931           20 :                                    smear=scf_control%smear)
     932              : 
     933              :             ! does not yet handle k-points
     934              :             CALL calculate_density_matrix(mos(ispin), &
     935           20 :                                           subspace_env%p_matrix_mix(ispin, 1)%matrix)
     936              : 
     937          160 :             DO i = 1, nmo
     938          100 :                sum_band = sum_band + mo_eigenvalues(i)*mo_occupations(i)
     939              :             END DO
     940              : 
     941              :             !check for self consistency
     942              :          END DO
     943              : 
     944           20 :          IF (subspace_env%mixing_method == direct_mixing_nr) THEN
     945              :             CALL scf_env_density_mixing(subspace_env%p_matrix_mix, &
     946           20 :                                         scf_env%mixing_store, rho_ao_kp, para_env, iter_delta, iloop)
     947              :          ELSE
     948              :             CALL self_consistency_check(rho_ao_kp, scf_env%p_delta, para_env, &
     949            0 :                                         subspace_env%p_matrix_mix, delta=iter_delta)
     950              :          END IF
     951              : 
     952           40 :          DO ispin = 1, nspin
     953              :             ! does not yet handle k-points
     954           40 :             CALL dbcsr_copy(rho_ao(ispin)%matrix, subspace_env%p_matrix_mix(ispin, 1)%matrix)
     955              :          END DO
     956              :          ! update of density
     957           20 :          CALL qs_rho_update_rho(rho, qs_env=qs_env)
     958              :          ! Mixing in reciprocal space
     959           20 :          IF (subspace_env%mixing_method >= gspace_mixing_nr) THEN
     960              :             CALL gspace_mixing(qs_env, scf_env%mixing_method, subspace_env%mixing_store, &
     961            0 :                                rho, para_env, scf_env%iter_count)
     962              :          END IF
     963              : 
     964           20 :          ene_diff = energy%total - ene_old
     965              :          converged = (ABS(ene_diff) < subspace_env%eps_ene .AND. &
     966           20 :                       iter_delta < subspace_env%eps_adapt*scf_env%iter_delta)
     967           20 :          t2 = m_walltime()
     968           20 :          IF (output_unit > 0) THEN
     969              :             WRITE (output_unit, "(T4,I5,T11,F8.3,T18,E14.4,T34,F12.5,T46,F16.8,T62,E14.4)") &
     970            0 :                iloop, t2 - t1, iter_delta, sum_band, energy%total, ene_diff
     971            0 :             CALL m_flush(output_unit)
     972              :          END IF
     973           22 :          IF (converged) THEN
     974            8 :             IF (output_unit > 0) WRITE (output_unit, "(T10,A,I6,A,/)") &
     975            0 :                " Reached convergence in ", iloop, " iterations "
     976              :             EXIT
     977              :          END IF
     978              : 
     979              :       END DO ! iloop
     980              : 
     981           10 :       NULLIFY (subspace_env%p_matrix_mix)
     982           20 :       DO ispin = 1, nspin
     983              :          ! does not yet handle k-points
     984           10 :          CALL dbcsr_copy(scf_env%p_mix_new(ispin, 1)%matrix, rho_ao(ispin)%matrix)
     985           10 :          CALL dbcsr_copy(rho_ao(ispin)%matrix, subspace_env%p_matrix_store(ispin)%matrix)
     986              : 
     987           20 :          DEALLOCATE (eval_first(ispin)%array, occ_first(ispin)%array)
     988              :       END DO
     989           10 :       DEALLOCATE (eval_first, occ_first)
     990              : 
     991           10 :       CALL timestop(handle)
     992              : 
     993           10 :    END SUBROUTINE do_scf_diag_subspace
     994              : 
     995              : ! **************************************************************************************************
     996              : !> \brief ...
     997              : !> \param subspace_env ...
     998              : !> \param qs_env ...
     999              : !> \param mos ...
    1000              : ! **************************************************************************************************
    1001            2 :    SUBROUTINE diag_subspace_allocate(subspace_env, qs_env, mos)
    1002              : 
    1003              :       TYPE(subspace_env_type), POINTER                   :: subspace_env
    1004              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1005              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos
    1006              : 
    1007              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'diag_subspace_allocate'
    1008              : 
    1009              :       INTEGER                                            :: handle, i, ispin, nmo, nspin
    1010              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
    1011              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1012            2 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    1013              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1014            2 :          POINTER                                         :: sab_orb
    1015              : 
    1016            2 :       CALL timeset(routineN, handle)
    1017              : 
    1018            2 :       NULLIFY (sab_orb, matrix_s)
    1019              :       CALL get_qs_env(qs_env=qs_env, sab_orb=sab_orb, &
    1020            2 :                       matrix_s=matrix_s)
    1021              : 
    1022            2 :       nspin = SIZE(mos)
    1023              : !   *** allocate p_atrix_store ***
    1024            2 :       IF (.NOT. ASSOCIATED(subspace_env%p_matrix_store)) THEN
    1025            2 :          CALL dbcsr_allocate_matrix_set(subspace_env%p_matrix_store, nspin)
    1026              : 
    1027            4 :          DO i = 1, nspin
    1028            2 :             ALLOCATE (subspace_env%p_matrix_store(i)%matrix)
    1029              :             CALL dbcsr_create(matrix=subspace_env%p_matrix_store(i)%matrix, template=matrix_s(1)%matrix, &
    1030            2 :                               name="DENSITY_STORE", matrix_type=dbcsr_type_symmetric)
    1031              :             CALL cp_dbcsr_alloc_block_from_nbl(subspace_env%p_matrix_store(i)%matrix, &
    1032            2 :                                                sab_orb)
    1033            4 :             CALL dbcsr_set(subspace_env%p_matrix_store(i)%matrix, 0.0_dp)
    1034              :          END DO
    1035              : 
    1036              :       END IF
    1037              : 
    1038            8 :       ALLOCATE (subspace_env%chc_mat(nspin))
    1039            8 :       ALLOCATE (subspace_env%c_vec(nspin))
    1040            8 :       ALLOCATE (subspace_env%c0(nspin))
    1041              : 
    1042            4 :       DO ispin = 1, nspin
    1043            2 :          CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nmo=nmo)
    1044            2 :          CALL cp_fm_create(subspace_env%c0(ispin), mo_coeff%matrix_struct)
    1045            2 :          NULLIFY (fm_struct_tmp)
    1046              :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nmo, ncol_global=nmo, &
    1047              :                                   para_env=mo_coeff%matrix_struct%para_env, &
    1048            2 :                                   context=mo_coeff%matrix_struct%context)
    1049            2 :          CALL cp_fm_create(subspace_env%chc_mat(ispin), fm_struct_tmp, "chc")
    1050            2 :          CALL cp_fm_create(subspace_env%c_vec(ispin), fm_struct_tmp, "vec")
    1051            6 :          CALL cp_fm_struct_release(fm_struct_tmp)
    1052              :       END DO
    1053              : 
    1054            2 :       CALL timestop(handle)
    1055              : 
    1056            2 :    END SUBROUTINE diag_subspace_allocate
    1057              : 
    1058              : ! **************************************************************************************************
    1059              : !> \brief the inner loop of scf, specific to diagonalization without S matrix
    1060              : !>       basically, in goes the ks matrix out goes a new p matrix
    1061              : !> \param scf_env ...
    1062              : !> \param mos ...
    1063              : !> \param matrix_ks ...
    1064              : !> \param scf_control ...
    1065              : !> \param scf_section ...
    1066              : !> \param diis_step ...
    1067              : !> \par History
    1068              : !>      03.2006 created [Joost VandeVondele]
    1069              : ! **************************************************************************************************
    1070        17898 :    SUBROUTINE do_special_diag(scf_env, mos, matrix_ks, scf_control, &
    1071              :                               scf_section, diis_step)
    1072              : 
    1073              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1074              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
    1075              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks
    1076              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1077              :       TYPE(section_vals_type), POINTER                   :: scf_section
    1078              :       LOGICAL, INTENT(INOUT)                             :: diis_step
    1079              : 
    1080              :       INTEGER                                            :: ispin, nspin
    1081              :       LOGICAL                                            :: do_level_shift, use_jacobi
    1082              :       REAL(KIND=dp)                                      :: diis_error
    1083              : 
    1084        17898 :       nspin = SIZE(matrix_ks)
    1085              : 
    1086        36570 :       DO ispin = 1, nspin
    1087        36570 :          CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, scf_env%scf_work1(ispin))
    1088              :       END DO
    1089        17898 :       IF (scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis) THEN
    1090              :          CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
    1091              :                              scf_env%scf_work2, scf_env%iter_delta, diis_error, diis_step, &
    1092              :                              scf_control%eps_diis, scf_control%nmixing, &
    1093        15304 :                              scf_section=scf_section)
    1094              :       ELSE
    1095         2594 :          diis_step = .FALSE.
    1096              :       END IF
    1097              : 
    1098        17898 :       IF ((scf_env%iter_count > 1) .AND. (scf_env%iter_delta < scf_control%diagonalization%eps_jacobi)) THEN
    1099           18 :          use_jacobi = .TRUE.
    1100              :       ELSE
    1101        17880 :          use_jacobi = .FALSE.
    1102              :       END IF
    1103              : 
    1104              :       do_level_shift = ((scf_control%level_shift /= 0.0_dp) .AND. &
    1105        17898 :                         ((scf_control%density_guess == core_guess) .OR. (scf_env%iter_count > 1)))
    1106        17898 :       IF (diis_step) THEN
    1107        11880 :          scf_env%iter_param = diis_error
    1108        11880 :          IF (use_jacobi) THEN
    1109           18 :             scf_env%iter_method = "DIIS/Jacobi"
    1110              :          ELSE
    1111        11862 :             scf_env%iter_method = "DIIS/Diag."
    1112              :          END IF
    1113              :       ELSE
    1114         6018 :          IF (scf_env%mixing_method == 1) THEN
    1115         6018 :             scf_env%iter_param = scf_env%p_mix_alpha
    1116         6018 :             IF (use_jacobi) THEN
    1117            0 :                scf_env%iter_method = "P_Mix/Jacobi"
    1118              :             ELSE
    1119         6018 :                scf_env%iter_method = "P_Mix/Diag."
    1120              :             END IF
    1121            0 :          ELSEIF (scf_env%mixing_method > 1) THEN
    1122            0 :             scf_env%iter_param = scf_env%mixing_store%alpha
    1123            0 :             IF (use_jacobi) THEN
    1124            0 :                scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Jacobi"
    1125              :             ELSE
    1126            0 :                scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
    1127              :             END IF
    1128              :          END IF
    1129              :       END IF
    1130        17898 :       scf_env%iter_delta = 0.0_dp
    1131              : 
    1132        36570 :       DO ispin = 1, nspin
    1133              :          CALL eigensolver_simple(matrix_ks=scf_env%scf_work1(ispin), &
    1134              :                                  mo_set=mos(ispin), &
    1135              :                                  work=scf_env%scf_work2, &
    1136              :                                  do_level_shift=do_level_shift, &
    1137              :                                  level_shift=scf_control%level_shift, &
    1138              :                                  use_jacobi=use_jacobi, &
    1139        36570 :                                  jacobi_threshold=scf_control%diagonalization%jacobi_threshold)
    1140              :       END DO
    1141              : 
    1142              :       CALL set_mo_occupation(mo_array=mos, &
    1143        17898 :                              smear=scf_control%smear)
    1144              : 
    1145        36570 :       DO ispin = 1, nspin
    1146              :          ! does not yet handle k-points
    1147              :          CALL calculate_density_matrix(mos(ispin), &
    1148        36570 :                                        scf_env%p_mix_new(ispin, 1)%matrix)
    1149              :       END DO
    1150              : 
    1151        17898 :    END SUBROUTINE do_special_diag
    1152              : 
    1153              : ! **************************************************************************************************
    1154              : !> \brief the inner loop of scf, specific to iterative diagonalization using OT
    1155              : !>        with S matrix; basically, in goes the ks matrix out goes a new p matrix
    1156              : !> \param scf_env ...
    1157              : !> \param mos ...
    1158              : !> \param matrix_ks ...
    1159              : !> \param matrix_s ...
    1160              : !> \param scf_control ...
    1161              : !> \param scf_section ...
    1162              : !> \param diis_step ...
    1163              : !> \par History
    1164              : !>      10.2008 created [JGH]
    1165              : ! **************************************************************************************************
    1166           64 :    SUBROUTINE do_ot_diag(scf_env, mos, matrix_ks, matrix_s, &
    1167              :                          scf_control, scf_section, diis_step)
    1168              : 
    1169              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1170              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
    1171              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
    1172              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1173              :       TYPE(section_vals_type), POINTER                   :: scf_section
    1174              :       LOGICAL, INTENT(INOUT)                             :: diis_step
    1175              : 
    1176              :       INTEGER                                            :: homo, ispin, nmo, nspin
    1177              :       REAL(KIND=dp)                                      :: diis_error, eps_iter
    1178           64 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues
    1179              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1180              : 
    1181           64 :       NULLIFY (eigenvalues)
    1182              : 
    1183           64 :       nspin = SIZE(matrix_ks)
    1184              : 
    1185          172 :       DO ispin = 1, nspin
    1186              :          CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, &
    1187          172 :                                scf_env%scf_work1(ispin))
    1188              :       END DO
    1189              : 
    1190           64 :       IF ((scf_env%iter_count > 1) .AND. (.NOT. scf_env%skip_diis)) THEN
    1191              :          CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
    1192              :                              scf_env%scf_work2, scf_env%iter_delta, diis_error, diis_step, &
    1193              :                              scf_control%eps_diis, scf_control%nmixing, &
    1194              :                              s_matrix=matrix_s, &
    1195           48 :                              scf_section=scf_section)
    1196              :       ELSE
    1197           16 :          diis_step = .FALSE.
    1198              :       END IF
    1199              : 
    1200           64 :       eps_iter = scf_control%diagonalization%eps_iter
    1201           64 :       IF (diis_step) THEN
    1202           20 :          scf_env%iter_param = diis_error
    1203           20 :          scf_env%iter_method = "DIIS/OTdiag"
    1204           54 :          DO ispin = 1, nspin
    1205              :             CALL copy_fm_to_dbcsr(scf_env%scf_work1(ispin), &
    1206           54 :                                   matrix_ks(ispin)%matrix, keep_sparsity=.TRUE.)
    1207              :          END DO
    1208           20 :          eps_iter = MAX(eps_iter, scf_control%diagonalization%eps_adapt*diis_error)
    1209              :       ELSE
    1210           44 :          IF (scf_env%mixing_method == 1) THEN
    1211           44 :             scf_env%iter_param = scf_env%p_mix_alpha
    1212           44 :             scf_env%iter_method = "P_Mix/OTdiag."
    1213            0 :          ELSEIF (scf_env%mixing_method > 1) THEN
    1214            0 :             scf_env%iter_param = scf_env%mixing_store%alpha
    1215            0 :             scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/OTdiag."
    1216              :          END IF
    1217              :       END IF
    1218              : 
    1219           64 :       scf_env%iter_delta = 0.0_dp
    1220              : 
    1221          172 :       DO ispin = 1, nspin
    1222              :          CALL get_mo_set(mos(ispin), &
    1223              :                          mo_coeff=mo_coeff, &
    1224              :                          eigenvalues=eigenvalues, &
    1225              :                          nmo=nmo, &
    1226          108 :                          homo=homo)
    1227              :          CALL ot_eigensolver(matrix_h=matrix_ks(ispin)%matrix, &
    1228              :                              matrix_s=matrix_s(1)%matrix, &
    1229              :                              matrix_c_fm=mo_coeff, &
    1230              :                              preconditioner=scf_env%ot_preconditioner(1)%preconditioner, &
    1231              :                              eps_gradient=eps_iter, &
    1232              :                              iter_max=scf_control%diagonalization%max_iter, &
    1233              :                              silent=.TRUE., &
    1234          108 :                              ot_settings=scf_control%diagonalization%ot_settings)
    1235              :          CALL calculate_subspace_eigenvalues(mo_coeff, matrix_ks(ispin)%matrix, &
    1236              :                                              evals_arg=eigenvalues, &
    1237          108 :                                              do_rotation=.TRUE.)
    1238              :          CALL copy_fm_to_dbcsr(mos(ispin)%mo_coeff, &
    1239          280 :                                mos(ispin)%mo_coeff_b)
    1240              :          !fm->dbcsr
    1241              :       END DO
    1242              : 
    1243              :       CALL set_mo_occupation(mo_array=mos, &
    1244           64 :                              smear=scf_control%smear)
    1245              : 
    1246          172 :       DO ispin = 1, nspin
    1247              :          ! does not yet handle k-points
    1248              :          CALL calculate_density_matrix(mos(ispin), &
    1249          172 :                                        scf_env%p_mix_new(ispin, 1)%matrix)
    1250              :       END DO
    1251              : 
    1252           64 :    END SUBROUTINE do_ot_diag
    1253              : 
    1254              : ! **************************************************************************************************
    1255              : !> \brief Solve a set restricted open Kohn-Sham (ROKS) equations based on the
    1256              : !>         alpha and beta Kohn-Sham matrices from unrestricted Kohn-Sham.
    1257              : !> \param scf_env ...
    1258              : !> \param mos ...
    1259              : !> \param matrix_ks ...
    1260              : !> \param matrix_s ...
    1261              : !> \param scf_control ...
    1262              : !> \param scf_section ...
    1263              : !> \param diis_step ...
    1264              : !> \param orthogonal_basis ...
    1265              : !> \par History
    1266              : !>      04.2006 created [MK]
    1267              : !>      Revised (01.05.06,MK)
    1268              : !> \note
    1269              : !>         this is only a high-spin ROKS.
    1270              : ! **************************************************************************************************
    1271         1104 :    SUBROUTINE do_roks_diag(scf_env, mos, matrix_ks, matrix_s, &
    1272              :                            scf_control, scf_section, diis_step, &
    1273              :                            orthogonal_basis)
    1274              : 
    1275              :       ! Literature: - C. C. J. Roothaan, Rev. Mod. Phys. 32, 179 (1960)
    1276              :       !             - M. F. Guest and V. R. Saunders, Mol. Phys. 28(3), 819 (1974)
    1277              :       !             - M. Filatov and S. Shaik, Chem. Phys. Lett. 288, 689 (1998)
    1278              : 
    1279              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1280              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos
    1281              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
    1282              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1283              :       TYPE(section_vals_type), POINTER                   :: scf_section
    1284              :       LOGICAL, INTENT(INOUT)                             :: diis_step
    1285              :       LOGICAL, INTENT(IN)                                :: orthogonal_basis
    1286              : 
    1287              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'do_roks_diag'
    1288              : 
    1289              :       INTEGER                                            :: handle, homoa, homob, imo, nalpha, nao, &
    1290              :                                                             nbeta, nmo
    1291              :       REAL(KIND=dp)                                      :: diis_error, level_shift_loc
    1292         1104 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eiga, eigb, occa, occb
    1293              :       TYPE(cp_fm_type), POINTER                          :: ksa, ksb, mo2ao, moa, mob, ortho, work
    1294              : 
    1295              : ! -------------------------------------------------------------------------
    1296              : 
    1297         1104 :       CALL timeset(routineN, handle)
    1298              : 
    1299         1104 :       IF (scf_env%cholesky_method == cholesky_inverse) THEN
    1300            0 :          ortho => scf_env%ortho_m1
    1301              :       ELSE
    1302         1104 :          ortho => scf_env%ortho
    1303              :       END IF
    1304         1104 :       work => scf_env%scf_work2
    1305              : 
    1306         1104 :       ksa => scf_env%scf_work1(1)
    1307         1104 :       ksb => scf_env%scf_work1(2)
    1308              : 
    1309         1104 :       CALL copy_dbcsr_to_fm(matrix_ks(1)%matrix, ksa)
    1310         1104 :       CALL copy_dbcsr_to_fm(matrix_ks(2)%matrix, ksb)
    1311              : 
    1312              :       ! Get MO information
    1313              : 
    1314              :       CALL get_mo_set(mo_set=mos(1), &
    1315              :                       nao=nao, &
    1316              :                       nmo=nmo, &
    1317              :                       nelectron=nalpha, &
    1318              :                       homo=homoa, &
    1319              :                       eigenvalues=eiga, &
    1320              :                       occupation_numbers=occa, &
    1321         1104 :                       mo_coeff=moa)
    1322              : 
    1323              :       CALL get_mo_set(mo_set=mos(2), &
    1324              :                       nelectron=nbeta, &
    1325              :                       homo=homob, &
    1326              :                       eigenvalues=eigb, &
    1327              :                       occupation_numbers=occb, &
    1328         1104 :                       mo_coeff=mob)
    1329              : 
    1330              :       ! Define the amount of level-shifting
    1331              : 
    1332         1104 :       IF ((scf_control%level_shift /= 0.0_dp) .AND. &
    1333              :           ((scf_control%density_guess == core_guess) .OR. &
    1334              :            (scf_control%density_guess == restart_guess) .OR. &
    1335              :            (scf_env%iter_count > 1))) THEN
    1336           20 :          level_shift_loc = scf_control%level_shift
    1337              :       ELSE
    1338         1084 :          level_shift_loc = 0.0_dp
    1339              :       END IF
    1340              : 
    1341              :       IF ((scf_env%iter_count > 1) .OR. &
    1342         1104 :           (scf_control%density_guess == core_guess) .OR. &
    1343              :           (scf_control%density_guess == restart_guess)) THEN
    1344              : 
    1345              :          ! Transform the spin unrestricted alpha and beta Kohn-Sham matrices
    1346              :          ! from AO basis to MO basis: K(MO) = C(T)*K(AO)*C
    1347              : 
    1348          998 :          CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksa, moa, 0.0_dp, work)
    1349          998 :          CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, moa, work, 0.0_dp, ksa)
    1350              : 
    1351          998 :          CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksb, moa, 0.0_dp, work)
    1352          998 :          CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, moa, work, 0.0_dp, ksb)
    1353              : 
    1354              :          ! Combine the spin unrestricted alpha and beta Kohn-Sham matrices
    1355              :          ! in the MO basis
    1356              : 
    1357          998 :          IF (scf_control%roks_scheme == general_roks) THEN
    1358              :             CALL combine_ks_matrices(ksa, ksb, occa, occb, scf_control%roks_f, &
    1359            0 :                                      nalpha, nbeta)
    1360          998 :          ELSE IF (scf_control%roks_scheme == high_spin_roks) THEN
    1361          998 :             CALL combine_ks_matrices(ksa, ksb, occa, occb, scf_control%roks_parameter)
    1362              :          ELSE
    1363            0 :             CPABORT("Unknown ROKS scheme requested")
    1364              :          END IF
    1365              : 
    1366              :          ! Back-transform the restricted open Kohn-Sham matrix from MO basis
    1367              :          ! to AO basis
    1368              : 
    1369          998 :          IF (orthogonal_basis) THEN
    1370              :             ! Q = C
    1371          454 :             mo2ao => moa
    1372              :          ELSE
    1373              :             ! Q = S*C
    1374          544 :             mo2ao => mob
    1375              : !MK     CALL copy_sm_to_fm(matrix_s(1)%matrix,work)
    1376              : !MK     CALL cp_fm_symm("L", "U",nao, nao, 1.0_dp, work, moa, 0.0_dp, mo2ao)
    1377          544 :             CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, moa, mo2ao, nao)
    1378              :          END IF
    1379              : 
    1380              :          ! K(AO) = Q*K(MO)*Q(T)
    1381              : 
    1382          998 :          CALL parallel_gemm("N", "T", nao, nao, nao, 1.0_dp, ksa, mo2ao, 0.0_dp, work)
    1383          998 :          CALL parallel_gemm("N", "N", nao, nao, nao, 1.0_dp, mo2ao, work, 0.0_dp, ksa)
    1384              : 
    1385              :       ELSE
    1386              : 
    1387              :          ! No transformation matrix available, yet. The closed shell part,
    1388              :          ! i.e. the beta Kohn-Sham matrix in AO basis, is taken.
    1389              :          ! There might be better choices, anyhow.
    1390              : 
    1391          106 :          CALL cp_fm_to_fm(ksb, ksa)
    1392              : 
    1393              :       END IF
    1394              : 
    1395              :       ! Update DIIS buffer and possibly perform DIIS extrapolation step
    1396              : 
    1397         1104 :       IF (scf_env%iter_count > 1) THEN
    1398          992 :          IF (orthogonal_basis) THEN
    1399              :             CALL qs_diis_b_step(diis_buffer=scf_env%scf_diis_buffer, &
    1400              :                                 mo_array=mos, &
    1401              :                                 kc=scf_env%scf_work1, &
    1402              :                                 sc=work, &
    1403              :                                 delta=scf_env%iter_delta, &
    1404              :                                 error_max=diis_error, &
    1405              :                                 diis_step=diis_step, &
    1406              :                                 eps_diis=scf_control%eps_diis, &
    1407              :                                 scf_section=scf_section, &
    1408          450 :                                 roks=.TRUE.)
    1409          450 :             CPASSERT(scf_env%iter_delta == scf_env%iter_delta)
    1410              :          ELSE
    1411              :             CALL qs_diis_b_step(diis_buffer=scf_env%scf_diis_buffer, &
    1412              :                                 mo_array=mos, &
    1413              :                                 kc=scf_env%scf_work1, &
    1414              :                                 sc=work, &
    1415              :                                 delta=scf_env%iter_delta, &
    1416              :                                 error_max=diis_error, &
    1417              :                                 diis_step=diis_step, &
    1418              :                                 eps_diis=scf_control%eps_diis, &
    1419              :                                 scf_section=scf_section, &
    1420              :                                 s_matrix=matrix_s, &
    1421          542 :                                 roks=.TRUE.)
    1422              :          END IF
    1423              :       END IF
    1424              : 
    1425         1104 :       IF (diis_step) THEN
    1426          692 :          scf_env%iter_param = diis_error
    1427          692 :          scf_env%iter_method = "DIIS/Diag."
    1428              :       ELSE
    1429          412 :          IF (scf_env%mixing_method == 1) THEN
    1430          412 :             scf_env%iter_param = scf_env%p_mix_alpha
    1431          412 :             scf_env%iter_method = "P_Mix/Diag."
    1432            0 :          ELSEIF (scf_env%mixing_method > 1) THEN
    1433            0 :             scf_env%iter_param = scf_env%mixing_store%alpha
    1434            0 :             scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
    1435              :          END IF
    1436              :       END IF
    1437              : 
    1438         1104 :       scf_env%iter_delta = 0.0_dp
    1439              : 
    1440         1104 :       IF (level_shift_loc /= 0.0_dp) THEN
    1441              : 
    1442              :          ! Transform the current Kohn-Sham matrix from AO to MO basis
    1443              :          ! for level-shifting using the current MO set
    1444              : 
    1445           20 :          CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksa, moa, 0.0_dp, work)
    1446           20 :          CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, moa, work, 0.0_dp, ksa)
    1447              : 
    1448              :          ! Apply level-shifting using 50:50 split of the shift (could be relaxed)
    1449              : 
    1450           60 :          DO imo = homob + 1, homoa
    1451           60 :             CALL cp_fm_add_to_element(ksa, imo, imo, 0.5_dp*level_shift_loc)
    1452              :          END DO
    1453          220 :          DO imo = homoa + 1, nmo
    1454          220 :             CALL cp_fm_add_to_element(ksa, imo, imo, level_shift_loc)
    1455              :          END DO
    1456              : 
    1457         1084 :       ELSE IF (.NOT. orthogonal_basis) THEN
    1458              : 
    1459              :          ! Transform the current Kohn-Sham matrix to an orthogonal basis
    1460          572 :          SELECT CASE (scf_env%cholesky_method)
    1461              :          CASE (cholesky_reduce)
    1462            0 :             CALL cp_fm_cholesky_reduce(ksa, ortho)
    1463              :          CASE (cholesky_restore)
    1464          508 :             CALL cp_fm_uplo_to_full(ksa, work)
    1465              :             CALL cp_fm_cholesky_restore(ksa, nao, ortho, work, &
    1466          508 :                                         "SOLVE", pos="RIGHT")
    1467              :             CALL cp_fm_cholesky_restore(work, nao, ortho, ksa, &
    1468          508 :                                         "SOLVE", pos="LEFT", transa="T")
    1469              :          CASE (cholesky_inverse)
    1470            0 :             CALL cp_fm_uplo_to_full(ksa, work)
    1471              :             CALL cp_fm_cholesky_restore(ksa, nao, ortho, work, &
    1472            0 :                                         "MULTIPLY", pos="RIGHT")
    1473              :             CALL cp_fm_cholesky_restore(work, nao, ortho, ksa, &
    1474            0 :                                         "MULTIPLY", pos="LEFT", transa="T")
    1475              :          CASE (cholesky_off)
    1476           64 :             CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksa, ortho, 0.0_dp, work)
    1477          636 :             CALL parallel_gemm("N", "N", nao, nao, nao, 1.0_dp, ortho, work, 0.0_dp, ksa)
    1478              :          END SELECT
    1479              : 
    1480              :       END IF
    1481              : 
    1482              :       ! Diagonalization of the ROKS operator matrix
    1483              : 
    1484         1104 :       CALL choose_eigv_solver(ksa, work, eiga)
    1485              : 
    1486              :       ! Back-transformation of the orthonormal eigenvectors if needed
    1487              : 
    1488         1104 :       IF (level_shift_loc /= 0.0_dp) THEN
    1489              :          ! Use old MO set for back-transformation if level-shifting was applied
    1490           20 :          CALL cp_fm_to_fm(moa, ortho)
    1491           20 :          CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, ortho, work, 0.0_dp, moa)
    1492              :       ELSE
    1493         1084 :          IF (orthogonal_basis) THEN
    1494          512 :             CALL cp_fm_to_fm(work, moa)
    1495              :          ELSE
    1496         1080 :             SELECT CASE (scf_env%cholesky_method)
    1497              :             CASE (cholesky_reduce, cholesky_restore)
    1498          508 :                CALL cp_fm_cholesky_restore(work, nmo, ortho, moa, "SOLVE")
    1499              :             CASE (cholesky_inverse)
    1500            0 :                CALL cp_fm_cholesky_restore(work, nmo, ortho, moa, "MULTIPLY")
    1501              :             CASE (cholesky_off)
    1502          572 :                CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, ortho, work, 0.0_dp, moa)
    1503              :             END SELECT
    1504              :          END IF
    1505              :       END IF
    1506              : 
    1507              :       ! Correct MO eigenvalues, if level-shifting was applied
    1508              : 
    1509         1104 :       IF (level_shift_loc /= 0.0_dp) THEN
    1510           60 :          DO imo = homob + 1, homoa
    1511           60 :             eiga(imo) = eiga(imo) - 0.5_dp*level_shift_loc
    1512              :          END DO
    1513          220 :          DO imo = homoa + 1, nmo
    1514          220 :             eiga(imo) = eiga(imo) - level_shift_loc
    1515              :          END DO
    1516              :       END IF
    1517              : 
    1518              :       ! Update also the beta MO set
    1519              : 
    1520        34556 :       eigb(:) = eiga(:)
    1521         1104 :       CALL cp_fm_to_fm(moa, mob)
    1522              : 
    1523              :       ! Calculate the new alpha and beta density matrix
    1524              : 
    1525              :       ! does not yet handle k-points
    1526         1104 :       CALL calculate_density_matrix(mos(1), scf_env%p_mix_new(1, 1)%matrix)
    1527         1104 :       CALL calculate_density_matrix(mos(2), scf_env%p_mix_new(2, 1)%matrix)
    1528              : 
    1529         1104 :       CALL timestop(handle)
    1530              : 
    1531         1104 :    END SUBROUTINE do_roks_diag
    1532              : 
    1533              : ! **************************************************************************************************
    1534              : !> \brief iterative diagonalization using the block Krylov-space approach
    1535              : !> \param scf_env ...
    1536              : !> \param mos ...
    1537              : !> \param matrix_ks ...
    1538              : !> \param scf_control ...
    1539              : !> \param scf_section ...
    1540              : !> \param check_moconv_only ...
    1541              : !> \param
    1542              : !> \par History
    1543              : !>      05.2009 created [MI]
    1544              : ! **************************************************************************************************
    1545              : 
    1546           38 :    SUBROUTINE do_block_krylov_diag(scf_env, mos, matrix_ks, &
    1547              :                                    scf_control, scf_section, check_moconv_only)
    1548              : 
    1549              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1550              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
    1551              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks
    1552              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1553              :       TYPE(section_vals_type), POINTER                   :: scf_section
    1554              :       LOGICAL, INTENT(IN), OPTIONAL                      :: check_moconv_only
    1555              : 
    1556              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'do_block_krylov_diag'
    1557              :       REAL(KIND=dp), PARAMETER                           :: rone = 1.0_dp, rzero = 0.0_dp
    1558              : 
    1559              :       INTEGER                                            :: handle, homo, ispin, iter, nao, nmo, &
    1560              :                                                             output_unit
    1561              :       LOGICAL                                            :: converged, my_check_moconv_only
    1562              :       REAL(dp)                                           :: eps_iter, t1, t2
    1563           38 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues
    1564              :       TYPE(cp_fm_type), POINTER                          :: c0, c1, chc, evec, ks, mo_coeff, ortho, &
    1565              :                                                             work
    1566              :       TYPE(cp_logger_type), POINTER                      :: logger
    1567              : 
    1568           76 :       logger => cp_get_default_logger()
    1569           38 :       CALL timeset(routineN, handle)
    1570              : 
    1571              :       output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%LANCZOS", &
    1572           38 :                                          extension=".scfLog")
    1573              : 
    1574           38 :       my_check_moconv_only = .FALSE.
    1575           38 :       IF (PRESENT(check_moconv_only)) my_check_moconv_only = check_moconv_only
    1576              : 
    1577           38 :       NULLIFY (mo_coeff, ortho, work, ks)
    1578           38 :       NULLIFY (mo_eigenvalues)
    1579           38 :       NULLIFY (c0, c1)
    1580              : 
    1581           38 :       IF (scf_env%cholesky_method == cholesky_inverse) THEN
    1582           38 :          ortho => scf_env%ortho_m1
    1583              :       ELSE
    1584            0 :          ortho => scf_env%ortho
    1585              :       END IF
    1586           38 :       work => scf_env%scf_work2
    1587              : 
    1588           76 :       DO ispin = 1, SIZE(matrix_ks)
    1589              :          CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, &
    1590           76 :                                scf_env%scf_work1(ispin))
    1591              :       END DO
    1592              : 
    1593           38 :       IF (scf_env%mixing_method == 1) THEN
    1594            0 :          scf_env%iter_param = scf_env%p_mix_alpha
    1595            0 :          scf_env%iter_method = "P_Mix/Lanczos"
    1596              :       ELSE
    1597              : !        scf_env%iter_param = scf_env%mixing_store%alpha
    1598           38 :          scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Lanc."
    1599              :       END IF
    1600              : 
    1601           76 :       DO ispin = 1, SIZE(matrix_ks)
    1602              : 
    1603           38 :          ks => scf_env%scf_work1(ispin)
    1604           38 :          CALL cp_fm_uplo_to_full(ks, work)
    1605              : 
    1606              :          CALL get_mo_set(mo_set=mos(ispin), &
    1607              :                          nao=nao, &
    1608              :                          nmo=nmo, &
    1609              :                          homo=homo, &
    1610              :                          eigenvalues=mo_eigenvalues, &
    1611           38 :                          mo_coeff=mo_coeff)
    1612              : 
    1613           38 :          NULLIFY (c0, c1)
    1614           38 :          c0 => scf_env%krylov_space%mo_conv(ispin)
    1615           38 :          c1 => scf_env%krylov_space%mo_refine(ispin)
    1616           38 :          SELECT CASE (scf_env%cholesky_method)
    1617              :          CASE (cholesky_reduce)
    1618            0 :             CALL cp_fm_cholesky_reduce(ks, ortho)
    1619            0 :             CALL cp_fm_uplo_to_full(ks, work)
    1620            0 :             CALL cp_fm_cholesky_restore(mo_coeff, nmo, ortho, c0, "MULTIPLY")
    1621              :          CASE (cholesky_restore)
    1622              :             CALL cp_fm_cholesky_restore(ks, nao, ortho, work, &
    1623            0 :                                         "SOLVE", pos="RIGHT")
    1624              :             CALL cp_fm_cholesky_restore(work, nao, ortho, ks, &
    1625            0 :                                         "SOLVE", pos="LEFT", transa="T")
    1626            0 :             CALL cp_fm_cholesky_restore(mo_coeff, nmo, ortho, c0, "MULTIPLY")
    1627              :          CASE (cholesky_inverse)
    1628              :             CALL cp_fm_cholesky_restore(ks, nao, ortho, work, &
    1629           38 :                                         "MULTIPLY", pos="RIGHT")
    1630              :             CALL cp_fm_cholesky_restore(work, nao, ortho, ks, &
    1631           38 :                                         "MULTIPLY", pos="LEFT", transa="T")
    1632           76 :             CALL cp_fm_cholesky_restore(mo_coeff, nmo, ortho, c0, "SOLVE")
    1633              :          END SELECT
    1634              : 
    1635           38 :          scf_env%krylov_space%nmo_nc = nmo
    1636           38 :          scf_env%krylov_space%nmo_conv = 0
    1637              : 
    1638           38 :          t1 = m_walltime()
    1639           38 :          IF (output_unit > 0) THEN
    1640            0 :             WRITE (output_unit, "(/T15,A)") '<<<<<<<<<   LANCZOS REFINEMENT    <<<<<<<<<<'
    1641              :             WRITE (output_unit, "(T8,A,T15,A,T23,A,T36,A,T49,A,T60,A,/,T8,A)") &
    1642            0 :                " Spin ", " Cycle ", &
    1643            0 :                " conv. MOS ", " B2MAX ", " B2MIN ", " Time", REPEAT("-", 60)
    1644              :          END IF
    1645           38 :          eps_iter = MAX(scf_env%krylov_space%eps_conv, scf_env%krylov_space%eps_adapt*scf_env%iter_delta)
    1646           38 :          iter = 0
    1647           38 :          converged = .FALSE.
    1648              :          !Check convergence of MOS
    1649          114 :          IF (my_check_moconv_only) THEN
    1650              : 
    1651              :             CALL lanczos_refinement(scf_env%krylov_space, ks, c0, c1, mo_eigenvalues, &
    1652            0 :                                     nao, eps_iter, ispin, check_moconv_only=my_check_moconv_only)
    1653            0 :             t2 = m_walltime()
    1654            0 :             IF (output_unit > 0) &
    1655              :                WRITE (output_unit, '(T8,I3,T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
    1656            0 :                ispin, iter, scf_env%krylov_space%nmo_conv, &
    1657            0 :                scf_env%krylov_space%max_res_norm, scf_env%krylov_space%min_res_norm, t2 - t1
    1658              : 
    1659              :             CYCLE
    1660              :          ELSE
    1661              :             !Block Lanczos refinement
    1662          620 :             DO iter = 1, scf_env%krylov_space%max_iter
    1663              :                CALL lanczos_refinement_2v(scf_env%krylov_space, ks, c0, c1, mo_eigenvalues, &
    1664          592 :                                           nao, eps_iter, ispin)
    1665          592 :                t2 = m_walltime()
    1666          592 :                IF (output_unit > 0) THEN
    1667              :                   WRITE (output_unit, '(T8,I3,T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
    1668            0 :                      ispin, iter, scf_env%krylov_space%nmo_conv, &
    1669            0 :                      scf_env%krylov_space%max_res_norm, scf_env%krylov_space%min_res_norm, t2 - t1
    1670              :                END IF
    1671          592 :                t1 = m_walltime()
    1672          620 :                IF (scf_env%krylov_space%max_res_norm < eps_iter) THEN
    1673           10 :                   converged = .TRUE.
    1674           10 :                   IF (output_unit > 0) WRITE (output_unit, *) &
    1675            0 :                      " Reached convergence in ", iter, " iterations "
    1676              :                   EXIT
    1677              :                END IF
    1678              :             END DO
    1679              : 
    1680           38 :             IF (.NOT. converged .AND. output_unit > 0) THEN
    1681              :                WRITE (output_unit, "(T4, A)") " WARNING Lanczos refinement could "// &
    1682            0 :                   "not converge all the mos:"
    1683            0 :                WRITE (output_unit, "(T40,A,T70,I10)") " number of not converged mos ", &
    1684            0 :                   scf_env%krylov_space%nmo_nc
    1685            0 :                WRITE (output_unit, "(T40,A,T70,E10.2)") " max norm of the residual ", &
    1686            0 :                   scf_env%krylov_space%max_res_norm
    1687              : 
    1688              :             END IF
    1689              : 
    1690              :             ! For the moment skip the re-orthogonalization
    1691              :             IF (.FALSE.) THEN
    1692              :                !Re-orthogonalization
    1693              :                NULLIFY (chc, evec)
    1694              :                chc => scf_env%krylov_space%chc_mat(ispin)
    1695              :                evec => scf_env%krylov_space%c_vec(ispin)
    1696              :                CALL parallel_gemm('N', 'N', nao, nmo, nao, rone, ks, c0, rzero, work)
    1697              :                CALL parallel_gemm('T', 'N', nmo, nmo, nao, rone, c0, work, rzero, chc)
    1698              :                !Diagonalize  (C^t)HC
    1699              :                CALL choose_eigv_solver(chc, evec, mo_eigenvalues)
    1700              :                !Rotate the C vectors
    1701              :                CALL parallel_gemm('N', 'N', nao, nmo, nmo, rone, c0, evec, rzero, c1)
    1702              :                c0 => scf_env%krylov_space%mo_refine(ispin)
    1703              :             END IF
    1704              : 
    1705           38 :             IF (scf_env%cholesky_method == cholesky_inverse) THEN
    1706           38 :                CALL cp_fm_cholesky_restore(c0, nmo, ortho, mo_coeff, "MULTIPLY")
    1707              :             ELSE
    1708            0 :                CALL cp_fm_cholesky_restore(c0, nmo, ortho, mo_coeff, "SOLVE")
    1709              :             END IF
    1710              : 
    1711              :             CALL set_mo_occupation(mo_set=mos(ispin), &
    1712           38 :                                    smear=scf_control%smear)
    1713              : 
    1714              :             ! does not yet handle k-points
    1715              :             CALL calculate_density_matrix(mos(ispin), &
    1716           38 :                                           scf_env%p_mix_new(ispin, 1)%matrix)
    1717              :          END IF
    1718              :       END DO ! ispin
    1719              : 
    1720           38 :       IF (output_unit > 0) THEN
    1721            0 :          WRITE (output_unit, "(T15,A/)") '<<<<<<<<< END LANCZOS REFINEMENT  <<<<<<<<<<'
    1722              :       END IF
    1723              : 
    1724              :       CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
    1725           38 :                                         "PRINT%LANCZOS")
    1726              : 
    1727           38 :       CALL timestop(handle)
    1728              : 
    1729           38 :    END SUBROUTINE do_block_krylov_diag
    1730              : 
    1731              : ! **************************************************************************************************
    1732              : !> \brief iterative diagonalization using the block davidson space approach
    1733              : !> \param qs_env ...
    1734              : !> \param scf_env ...
    1735              : !> \param mos ...
    1736              : !> \param matrix_ks ...
    1737              : !> \param matrix_s ...
    1738              : !> \param scf_control ...
    1739              : !> \param scf_section ...
    1740              : !> \param check_moconv_only ...
    1741              : !> \param
    1742              : !> \par History
    1743              : !>      05.2011 created [MI]
    1744              : ! **************************************************************************************************
    1745              : 
    1746           84 :    SUBROUTINE do_block_davidson_diag(qs_env, scf_env, mos, matrix_ks, matrix_s, &
    1747              :                                      scf_control, scf_section, check_moconv_only)
    1748              : 
    1749              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1750              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1751              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
    1752              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
    1753              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1754              :       TYPE(section_vals_type), POINTER                   :: scf_section
    1755              :       LOGICAL, INTENT(IN), OPTIONAL                      :: check_moconv_only
    1756              : 
    1757              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'do_block_davidson_diag'
    1758              : 
    1759              :       INTEGER                                            :: handle, ispin, nspins, output_unit
    1760              :       LOGICAL                                            :: do_prec, my_check_moconv_only
    1761              :       TYPE(cp_logger_type), POINTER                      :: logger
    1762              : 
    1763           84 :       logger => cp_get_default_logger()
    1764           84 :       CALL timeset(routineN, handle)
    1765              : 
    1766              :       output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DAVIDSON", &
    1767           84 :                                          extension=".scfLog")
    1768              : 
    1769           84 :       IF (output_unit > 0) &
    1770            0 :          WRITE (output_unit, "(/T15,A)") '<<<<<<<<<  DAVIDSON ITERATIONS   <<<<<<<<<<'
    1771              : 
    1772           84 :       IF (scf_env%mixing_method == 1) THEN
    1773            0 :          scf_env%iter_param = scf_env%p_mix_alpha
    1774            0 :          scf_env%iter_method = "P_Mix/Dav."
    1775              :       ELSE
    1776           84 :          scf_env%iter_param = scf_env%mixing_store%alpha
    1777           84 :          scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Dav."
    1778              :       END IF
    1779              : 
    1780           84 :       my_check_moconv_only = .FALSE.
    1781           84 :       IF (PRESENT(check_moconv_only)) my_check_moconv_only = check_moconv_only
    1782           84 :       do_prec = .FALSE.
    1783           84 :       IF (scf_env%block_davidson_env(1)%prec_type /= 0 .AND. &
    1784              :           scf_env%iter_count >= scf_env%block_davidson_env(1)%first_prec) THEN
    1785           76 :          do_prec = .TRUE.
    1786              :       END IF
    1787              : 
    1788           84 :       nspins = SIZE(matrix_ks)
    1789              : 
    1790           84 :       IF (do_prec .AND. (scf_env%iter_count == scf_env%block_davidson_env(1)%first_prec .OR. &
    1791              :                          MODULO(scf_env%iter_count, scf_env%block_davidson_env(1)%niter_new_prec) == 0)) THEN
    1792              :          CALL restart_preconditioner(qs_env, scf_env%ot_preconditioner, &
    1793           16 :                                      prec_type=scf_env%block_davidson_env(1)%prec_type, nspins=nspins)
    1794              :          CALL prepare_preconditioner(qs_env, mos, matrix_ks, matrix_s, scf_env%ot_preconditioner, &
    1795              :                                      scf_env%block_davidson_env(1)%prec_type, &
    1796              :                                      scf_env%block_davidson_env(1)%solver_type, &
    1797              :                                      scf_env%block_davidson_env(1)%energy_gap, nspins, &
    1798              :                                      convert_to_dbcsr=scf_env%block_davidson_env(1)%use_sparse_mos, &
    1799           16 :                                      full_mo_set=.TRUE.)
    1800              :       END IF
    1801              : 
    1802          178 :       DO ispin = 1, nspins
    1803          178 :          IF (scf_env%block_davidson_env(ispin)%use_sparse_mos) THEN
    1804           64 :             IF (.NOT. do_prec) THEN
    1805              :                CALL generate_extended_space_sparse(scf_env%block_davidson_env(ispin), mos(ispin), &
    1806            8 :                                                    matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit)
    1807              :             ELSE
    1808              :                CALL generate_extended_space_sparse(scf_env%block_davidson_env(ispin), mos(ispin), &
    1809              :                                                    matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit, &
    1810           56 :                                                    scf_env%ot_preconditioner(ispin)%preconditioner)
    1811              :             END IF
    1812              : 
    1813              :          ELSE
    1814           30 :             IF (.NOT. do_prec) THEN
    1815              :                CALL generate_extended_space(scf_env%block_davidson_env(ispin), mos(ispin), &
    1816            2 :                                             matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit)
    1817              :             ELSE
    1818              :                CALL generate_extended_space(scf_env%block_davidson_env(ispin), mos(ispin), &
    1819              :                                             matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit, &
    1820           28 :                                             scf_env%ot_preconditioner(ispin)%preconditioner)
    1821              :             END IF
    1822              :          END IF
    1823              :       END DO !ispin
    1824              : 
    1825              :       CALL set_mo_occupation(mo_array=mos, &
    1826           84 :                              smear=scf_control%smear)
    1827              : 
    1828          178 :       DO ispin = 1, nspins
    1829              :          ! does not yet handle k-points
    1830              :          CALL calculate_density_matrix(mos(ispin), &
    1831          178 :                                        scf_env%p_mix_new(ispin, 1)%matrix)
    1832              :       END DO
    1833              : 
    1834           84 :       IF (output_unit > 0) THEN
    1835            0 :          WRITE (output_unit, "(T15,A/)") '<<<<<<<<< END DAVIDSON ITERATION  <<<<<<<<<<'
    1836              :       END IF
    1837              : 
    1838              :       CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
    1839           84 :                                         "PRINT%DAVIDSON")
    1840              : 
    1841           84 :       CALL timestop(handle)
    1842              : 
    1843           84 :    END SUBROUTINE do_block_davidson_diag
    1844              : 
    1845              : ! **************************************************************************************************
    1846              : !> \brief Kpoint diagonalization routine
    1847              : !>        Transforms matrices to kpoint, distributes kpoint groups, performs diagonalization
    1848              : !> \param matrix_s     Overlap matrices (RS indices, global)
    1849              : !> \param kpoints      Kpoint environment
    1850              : !> \param fmwork       full matrices distributed over all groups
    1851              : !> \par History
    1852              : !>      02.2026 created [JGH]
    1853              : ! **************************************************************************************************
    1854            0 :    SUBROUTINE diag_kp_smat(matrix_s, kpoints, fmwork)
    1855              : 
    1856              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_s
    1857              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1858              :       TYPE(cp_fm_type), DIMENSION(:)                     :: fmwork
    1859              : 
    1860              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'diag_kp_smat'
    1861              :       COMPLEX(KIND=dp), PARAMETER                        :: cone = (1.0_dp, 0.0_dp), &
    1862              :                                                             czero = (0.0_dp, 0.0_dp)
    1863              : 
    1864            0 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: ceig
    1865              :       INTEGER                                            :: handle, igroup, ik, ikp, indx, kplocal, &
    1866              :                                                             nao, nkp, nkp_groups
    1867              :       INTEGER, DIMENSION(2)                              :: kp_range
    1868            0 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
    1869            0 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1870              :       LOGICAL                                            :: my_kpgrp, use_real_wfn
    1871            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenvalues
    1872            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    1873            0 :       TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:, :) :: info
    1874              :       TYPE(cp_cfm_type)                                  :: csmat, cwork
    1875            0 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_ao_fm_pools
    1876              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    1877              :       TYPE(cp_fm_type)                                   :: fmdummy, fmlocal, rsmat
    1878              :       TYPE(dbcsr_type), POINTER                          :: cmatrix, rmatrix, tmpmat
    1879              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1880              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1881              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1882            0 :          POINTER                                         :: sab_nl
    1883              :       TYPE(qs_matrix_pools_type), POINTER                :: mpools
    1884              : 
    1885            0 :       CALL timeset(routineN, handle)
    1886              : 
    1887            0 :       NULLIFY (sab_nl)
    1888              :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, use_real_wfn=use_real_wfn, kp_range=kp_range, &
    1889              :                            nkp_groups=nkp_groups, kp_dist=kp_dist, sab_nl=sab_nl, &
    1890            0 :                            cell_to_index=cell_to_index)
    1891            0 :       CPASSERT(ASSOCIATED(sab_nl))
    1892            0 :       kplocal = kp_range(2) - kp_range(1) + 1
    1893              : 
    1894              :       ! allocate some work matrices
    1895            0 :       ALLOCATE (rmatrix, cmatrix, tmpmat)
    1896              :       CALL dbcsr_create(rmatrix, template=matrix_s(1, 1)%matrix, &
    1897            0 :                         matrix_type=dbcsr_type_symmetric)
    1898              :       CALL dbcsr_create(cmatrix, template=matrix_s(1, 1)%matrix, &
    1899            0 :                         matrix_type=dbcsr_type_antisymmetric)
    1900              :       CALL dbcsr_create(tmpmat, template=matrix_s(1, 1)%matrix, &
    1901            0 :                         matrix_type=dbcsr_type_no_symmetry)
    1902            0 :       CALL cp_dbcsr_alloc_block_from_nbl(rmatrix, sab_nl)
    1903            0 :       CALL cp_dbcsr_alloc_block_from_nbl(cmatrix, sab_nl)
    1904              : 
    1905              :       ! fm pools to be used within a kpoint group
    1906            0 :       CALL get_kpoint_info(kpoints, mpools=mpools)
    1907            0 :       CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
    1908              : 
    1909            0 :       CALL fm_pool_create_fm(ao_ao_fm_pools(1)%pool, fmlocal)
    1910            0 :       CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
    1911              : 
    1912            0 :       IF (use_real_wfn) THEN
    1913            0 :          CALL cp_fm_create(rsmat, matrix_struct)
    1914              :       ELSE
    1915            0 :          CALL cp_cfm_create(csmat, matrix_struct)
    1916            0 :          CALL cp_cfm_create(cwork, matrix_struct)
    1917              :       END IF
    1918              : 
    1919            0 :       CALL cp_fm_get_info(fmwork(1), nrow_global=nao)
    1920            0 :       ALLOCATE (eigenvalues(nao), ceig(nao))
    1921              : 
    1922            0 :       para_env => kpoints%blacs_env_all%para_env
    1923            0 :       ALLOCATE (info(kplocal*nkp_groups, 2))
    1924              : 
    1925              :       ! Setup and start all the communication
    1926            0 :       indx = 0
    1927            0 :       DO ikp = 1, kplocal
    1928            0 :          DO igroup = 1, nkp_groups
    1929              :             ! number of current kpoint
    1930            0 :             ik = kp_dist(1, igroup) + ikp - 1
    1931            0 :             my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    1932            0 :             indx = indx + 1
    1933            0 :             IF (use_real_wfn) THEN
    1934            0 :                CALL dbcsr_set(rmatrix, 0.0_dp)
    1935              :                CALL rskp_transform(rmatrix=rmatrix, rsmat=matrix_s, ispin=1, &
    1936            0 :                                    xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_nl)
    1937            0 :                CALL dbcsr_desymmetrize(rmatrix, tmpmat)
    1938            0 :                CALL copy_dbcsr_to_fm(tmpmat, fmwork(1))
    1939              :             ELSE
    1940            0 :                CALL dbcsr_set(rmatrix, 0.0_dp)
    1941            0 :                CALL dbcsr_set(cmatrix, 0.0_dp)
    1942              :                CALL rskp_transform(rmatrix=rmatrix, cmatrix=cmatrix, rsmat=matrix_s, ispin=1, &
    1943            0 :                                    xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_nl)
    1944            0 :                CALL dbcsr_desymmetrize(rmatrix, tmpmat)
    1945            0 :                CALL copy_dbcsr_to_fm(tmpmat, fmwork(1))
    1946            0 :                CALL dbcsr_desymmetrize(cmatrix, tmpmat)
    1947            0 :                CALL copy_dbcsr_to_fm(tmpmat, fmwork(2))
    1948              :             END IF
    1949              :             ! transfer to kpoint group
    1950              :             ! redistribution of matrices, new blacs environment
    1951              :             ! fmwork -> fmlocal -> rsmat/csmat
    1952            0 :             IF (use_real_wfn) THEN
    1953            0 :                IF (my_kpgrp) THEN
    1954            0 :                   CALL cp_fm_start_copy_general(fmwork(1), rsmat, para_env, info(indx, 1))
    1955              :                ELSE
    1956            0 :                   CALL cp_fm_start_copy_general(fmwork(1), fmdummy, para_env, info(indx, 1))
    1957              :                END IF
    1958              :             ELSE
    1959            0 :                IF (my_kpgrp) THEN
    1960            0 :                   CALL cp_fm_start_copy_general(fmwork(1), fmlocal, para_env, info(indx, 1))
    1961            0 :                   CALL cp_fm_start_copy_general(fmwork(2), fmlocal, para_env, info(indx, 2))
    1962              :                ELSE
    1963            0 :                   CALL cp_fm_start_copy_general(fmwork(1), fmdummy, para_env, info(indx, 1))
    1964            0 :                   CALL cp_fm_start_copy_general(fmwork(2), fmdummy, para_env, info(indx, 2))
    1965              :                END IF
    1966              :             END IF
    1967              :          END DO
    1968              :       END DO
    1969              : 
    1970              :       ! Finish communication then diagonalise in each group
    1971              :       indx = 0
    1972            0 :       DO ikp = 1, kplocal
    1973            0 :          DO igroup = 1, nkp_groups
    1974              :             ! number of current kpoint
    1975            0 :             ik = kp_dist(1, igroup) + ikp - 1
    1976            0 :             my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    1977            0 :             indx = indx + 1
    1978            0 :             IF (my_kpgrp) THEN
    1979            0 :                IF (use_real_wfn) THEN
    1980            0 :                   CALL cp_fm_finish_copy_general(rsmat, info(indx, 1))
    1981              :                ELSE
    1982            0 :                   CALL cp_fm_finish_copy_general(fmlocal, info(indx, 1))
    1983            0 :                   CALL cp_cfm_scale_and_add_fm(z_zero, csmat, z_one, fmlocal)
    1984            0 :                   CALL cp_fm_finish_copy_general(fmlocal, info(indx, 2))
    1985            0 :                   CALL cp_cfm_scale_and_add_fm(z_one, csmat, gaussi, fmlocal)
    1986              :                END IF
    1987              :             END IF
    1988              :          END DO
    1989              : 
    1990              :          ! Each kpoint group has now information on a kpoint to be diagonalized
    1991              :          ! Eigensolver Hermite or Symmetric
    1992            0 :          kp => kpoints%kp_env(ikp)%kpoint_env
    1993            0 :          IF (use_real_wfn) THEN
    1994            0 :             CALL choose_eigv_solver(rsmat, fmlocal, eigenvalues)
    1995              :          ELSE
    1996            0 :             CALL cp_cfm_heevd(csmat, cwork, eigenvalues)
    1997              :          END IF
    1998            0 :          CPASSERT(ALL(eigenvalues(1:nao) >= 0.0_dp))
    1999            0 :          IF (use_real_wfn) THEN
    2000            0 :             CALL cp_fm_release(kp%shalf)
    2001            0 :             CALL cp_fm_create(kp%shalf, matrix_struct)
    2002            0 :             eigenvalues(1:nao) = SQRT(eigenvalues(1:nao))
    2003            0 :             CALL cp_fm_to_fm(fmlocal, rsmat)
    2004            0 :             CALL cp_fm_column_scale(rsmat, eigenvalues)
    2005              :             CALL parallel_gemm("N", "T", nao, nao, nao, 1.0_dp, rsmat, fmlocal, &
    2006            0 :                                0.0_dp, kp%shalf)
    2007              :          ELSE
    2008            0 :             CALL cp_cfm_release(kp%cshalf)
    2009            0 :             CALL cp_cfm_create(kp%cshalf, matrix_struct)
    2010            0 :             ceig(1:nao) = SQRT(eigenvalues(1:nao))
    2011            0 :             CALL cp_cfm_to_cfm(cwork, csmat)
    2012            0 :             CALL cp_cfm_column_scale(csmat, ceig)
    2013              :             CALL parallel_gemm("N", "T", nao, nao, nao, cone, csmat, cwork, &
    2014            0 :                                czero, kp%cshalf)
    2015              :          END IF
    2016              :       END DO
    2017              : 
    2018              :       ! Clean up communication
    2019              :       indx = 0
    2020            0 :       DO ikp = 1, kplocal
    2021            0 :          DO igroup = 1, nkp_groups
    2022              :             ! number of current kpoint
    2023            0 :             ik = kp_dist(1, igroup) + ikp - 1
    2024            0 :             my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    2025            0 :             indx = indx + 1
    2026            0 :             IF (use_real_wfn) THEN
    2027            0 :                CALL cp_fm_cleanup_copy_general(info(indx, 1))
    2028              :             ELSE
    2029            0 :                CALL cp_fm_cleanup_copy_general(info(indx, 1))
    2030            0 :                CALL cp_fm_cleanup_copy_general(info(indx, 2))
    2031              :             END IF
    2032              :          END DO
    2033              :       END DO
    2034              : 
    2035              :       ! All done
    2036            0 :       DEALLOCATE (info)
    2037            0 :       DEALLOCATE (eigenvalues, ceig)
    2038              : 
    2039            0 :       CALL dbcsr_deallocate_matrix(rmatrix)
    2040            0 :       CALL dbcsr_deallocate_matrix(cmatrix)
    2041            0 :       CALL dbcsr_deallocate_matrix(tmpmat)
    2042              : 
    2043            0 :       IF (use_real_wfn) THEN
    2044            0 :          CALL cp_fm_release(rsmat)
    2045              :       ELSE
    2046            0 :          CALL cp_cfm_release(csmat)
    2047            0 :          CALL cp_cfm_release(cwork)
    2048              :       END IF
    2049            0 :       CALL fm_pool_give_back_fm(ao_ao_fm_pools(1)%pool, fmlocal)
    2050              : 
    2051            0 :       CALL timestop(handle)
    2052              : 
    2053            0 :    END SUBROUTINE diag_kp_smat
    2054              : 
    2055              : END MODULE qs_scf_diagonalization
        

Generated by: LCOV version 2.0-1