LCOV - code coverage report
Current view: top level - src - qs_scf_diagonalization.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:c24029e) Lines: 85.4 % 914 781
Test Date: 2026-07-04 06:36:57 Functions: 100.0 % 12 12

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

Generated by: LCOV version 2.0-1