LCOV - code coverage report
Current view: top level - src - qs_diis.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:32ddf85) Lines: 396 426 93.0 %
Date: 2025-05-17 08:08:58 Functions: 14 14 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Apply the direct inversion in the iterative subspace (DIIS) of Pulay
      10             : !>      in the framework of an SCF iteration for convergence acceleration
      11             : !> \par Literature
      12             : !>      - P. Pulay, Chem. Phys. Lett. 73, 393 (1980)
      13             : !>      - P. Pulay, J. Comput. Chem. 3, 556 (1982)
      14             : !> \par History
      15             : !>      - Changed to BLACS matrix usage (08.06.2001,MK)
      16             : !>      - rewritten to include LSD (1st attempt) (01.2003, Joost VandeVondele)
      17             : !>      - DIIS for ROKS (05.04.06,MK)
      18             : !>      - DIIS for k-points (04.2023, Augustin Bussy)
      19             : !> \author Matthias Krack (28.06.2000)
      20             : ! **************************************************************************************************
      21             : MODULE qs_diis
      22             :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_trace
      23             :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      24             :                                               cp_cfm_get_info,&
      25             :                                               cp_cfm_release,&
      26             :                                               cp_cfm_to_cfm,&
      27             :                                               cp_cfm_to_fm,&
      28             :                                               cp_cfm_type,&
      29             :                                               cp_fm_to_cfm
      30             :    USE cp_dbcsr_api,                    ONLY: &
      31             :         dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_multiply, dbcsr_p_type, dbcsr_release, &
      32             :         dbcsr_set, dbcsr_transposed, dbcsr_type
      33             :    USE cp_dbcsr_contrib,                ONLY: dbcsr_dot,&
      34             :                                               dbcsr_maxabs
      35             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm
      36             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      37             :                                               cp_fm_scale,&
      38             :                                               cp_fm_scale_and_add,&
      39             :                                               cp_fm_symm,&
      40             :                                               cp_fm_trace
      41             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_type
      42             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      43             :                                               cp_fm_get_info,&
      44             :                                               cp_fm_maxabsval,&
      45             :                                               cp_fm_release,&
      46             :                                               cp_fm_set_all,&
      47             :                                               cp_fm_to_fm,&
      48             :                                               cp_fm_type
      49             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      50             :                                               cp_logger_type,&
      51             :                                               cp_to_string
      52             :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      53             :                                               cp_print_key_unit_nr
      54             :    USE dm_ls_scf_types,                 ONLY: ls_scf_env_type
      55             :    USE input_section_types,             ONLY: section_vals_type
      56             :    USE kinds,                           ONLY: default_string_length,&
      57             :                                               dp
      58             :    USE mathlib,                         ONLY: diag_complex,&
      59             :                                               diamat_all
      60             :    USE message_passing,                 ONLY: mp_para_env_type
      61             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      62             :    USE qs_diis_types,                   ONLY: qs_diis_buffer_type,&
      63             :                                               qs_diis_buffer_type_kp,&
      64             :                                               qs_diis_buffer_type_sparse
      65             :    USE qs_environment_types,            ONLY: get_qs_env,&
      66             :                                               qs_environment_type
      67             :    USE qs_mo_types,                     ONLY: get_mo_set,&
      68             :                                               mo_set_type
      69             :    USE string_utilities,                ONLY: compress
      70             : #include "./base/base_uses.f90"
      71             : 
      72             :    IMPLICIT NONE
      73             : 
      74             :    PRIVATE
      75             : 
      76             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_diis'
      77             : 
      78             :    ! Public subroutines
      79             : 
      80             :    PUBLIC :: qs_diis_b_clear, &
      81             :              qs_diis_b_create, &
      82             :              qs_diis_b_step
      83             :    PUBLIC :: qs_diis_b_clear_sparse, &
      84             :              qs_diis_b_create_sparse, &
      85             :              qs_diis_b_step_4lscf
      86             :    PUBLIC :: qs_diis_b_clear_kp, &
      87             :              qs_diis_b_create_kp, &
      88             :              qs_diis_b_step_kp, &
      89             :              qs_diis_b_calc_err_kp, &
      90             :              qs_diis_b_info_kp
      91             : 
      92             : CONTAINS
      93             : 
      94             : ! **************************************************************************************************
      95             : !> \brief Allocates an SCF DIIS buffer
      96             : !> \param diis_buffer the buffer to create
      97             : !> \param nbuffer ...
      98             : !> \par History
      99             : !>      02.2003 created [fawzi]
     100             : !> \author fawzi
     101             : ! **************************************************************************************************
     102        3898 :    SUBROUTINE qs_diis_b_create(diis_buffer, nbuffer)
     103             : 
     104             :       TYPE(qs_diis_buffer_type), INTENT(OUT)             :: diis_buffer
     105             :       INTEGER, INTENT(in)                                :: nbuffer
     106             : 
     107             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_diis_b_create'
     108             : 
     109             :       INTEGER                                            :: handle
     110             : 
     111             : ! -------------------------------------------------------------------------
     112             : 
     113        3898 :       CALL timeset(routineN, handle)
     114             : 
     115        3898 :       NULLIFY (diis_buffer%b_matrix)
     116        3898 :       NULLIFY (diis_buffer%error)
     117        3898 :       NULLIFY (diis_buffer%param)
     118        3898 :       diis_buffer%nbuffer = nbuffer
     119        3898 :       diis_buffer%ncall = 0
     120             : 
     121        3898 :       CALL timestop(handle)
     122             : 
     123        3898 :    END SUBROUTINE qs_diis_b_create
     124             : 
     125             : ! **************************************************************************************************
     126             : !> \brief Allocate and initialize a DIIS buffer for nao*nao parameter
     127             : !>      variables and with a buffer size of nbuffer.
     128             : !> \param diis_buffer the buffer to initialize
     129             : !> \param matrix_struct the structure for the matrix of the buffer
     130             : !> \param nspin ...
     131             : !> \param scf_section ...
     132             : !> \par History
     133             : !>      - Creation (07.05.2001, Matthias Krack)
     134             : !>      - Changed to BLACS matrix usage (08.06.2001,MK)
     135             : !>      - DIIS for ROKS (05.04.06,MK)
     136             : !> \author Matthias Krack
     137             : !> \note
     138             : !>      check to allocate matrixes only when needed, using a linked list?
     139             : ! **************************************************************************************************
     140       70615 :    SUBROUTINE qs_diis_b_check_i_alloc(diis_buffer, matrix_struct, nspin, &
     141             :                                       scf_section)
     142             : 
     143             :       TYPE(qs_diis_buffer_type), INTENT(INOUT)           :: diis_buffer
     144             :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     145             :       INTEGER, INTENT(IN)                                :: nspin
     146             :       TYPE(section_vals_type), POINTER                   :: scf_section
     147             : 
     148             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_diis_b_check_i_alloc'
     149             : 
     150             :       INTEGER                                            :: handle, ibuffer, ispin, nbuffer, &
     151             :                                                             output_unit
     152             :       TYPE(cp_logger_type), POINTER                      :: logger
     153             : 
     154             : ! -------------------------------------------------------------------------
     155             : 
     156       70615 :       CALL timeset(routineN, handle)
     157             : 
     158       70615 :       logger => cp_get_default_logger()
     159             : 
     160       70615 :       nbuffer = diis_buffer%nbuffer
     161             : 
     162       70615 :       IF (.NOT. ASSOCIATED(diis_buffer%error)) THEN
     163       29406 :          ALLOCATE (diis_buffer%error(nbuffer, nspin))
     164             : 
     165        6468 :          DO ispin = 1, nspin
     166       20604 :             DO ibuffer = 1, nbuffer
     167             :                CALL cp_fm_create(diis_buffer%error(ibuffer, ispin), &
     168             :                                  name="qs_diis_b%error("// &
     169             :                                  TRIM(ADJUSTL(cp_to_string(ibuffer)))//","// &
     170             :                                  TRIM(ADJUSTL(cp_to_string(ibuffer)))//")", &
     171       17670 :                                  matrix_struct=matrix_struct)
     172             :             END DO
     173             :          END DO
     174             :       END IF
     175             : 
     176       70615 :       IF (.NOT. ASSOCIATED(diis_buffer%param)) THEN
     177       29406 :          ALLOCATE (diis_buffer%param(nbuffer, nspin))
     178             : 
     179        6468 :          DO ispin = 1, nspin
     180       20604 :             DO ibuffer = 1, nbuffer
     181             :                CALL cp_fm_create(diis_buffer%param(ibuffer, ispin), &
     182             :                                  name="qs_diis_b%param("// &
     183             :                                  TRIM(ADJUSTL(cp_to_string(ibuffer)))//","// &
     184             :                                  TRIM(ADJUSTL(cp_to_string(ibuffer)))//")", &
     185       17670 :                                  matrix_struct=matrix_struct)
     186             :             END DO
     187             :          END DO
     188             :       END IF
     189             : 
     190       70615 :       IF (.NOT. ASSOCIATED(diis_buffer%b_matrix)) THEN
     191       14670 :          ALLOCATE (diis_buffer%b_matrix(nbuffer + 1, nbuffer + 1))
     192       90954 :          diis_buffer%b_matrix = 0.0_dp
     193             :          output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DIIS_INFO", &
     194        2934 :                                             extension=".scfLog")
     195        2934 :          IF (output_unit > 0) THEN
     196             :             WRITE (UNIT=output_unit, FMT="(/,T9,A)") &
     197          16 :                "DIIS | The SCF DIIS buffer was allocated and initialized"
     198             :          END IF
     199             :          CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
     200        2934 :                                            "PRINT%DIIS_INFO")
     201             :       END IF
     202             : 
     203       70615 :       CALL timestop(handle)
     204             : 
     205       70615 :    END SUBROUTINE qs_diis_b_check_i_alloc
     206             : 
     207             : ! **************************************************************************************************
     208             : !> \brief Update the SCF DIIS buffer, and if appropriate does a diis step.
     209             : !> \param diis_buffer ...
     210             : !> \param mo_array ...
     211             : !> \param kc ...
     212             : !> \param sc ...
     213             : !> \param delta ...
     214             : !> \param error_max ...
     215             : !> \param diis_step ...
     216             : !> \param eps_diis ...
     217             : !> \param nmixing ...
     218             : !> \param s_matrix ...
     219             : !> \param scf_section ...
     220             : !> \param roks ...
     221             : !> \par History
     222             : !>      - Creation (07.05.2001, Matthias Krack)
     223             : !>      - Changed to BLACS matrix usage (08.06.2001, MK)
     224             : !>      - 03.2003 rewamped [fawzi]
     225             : !>      - Adapted for high-spin ROKS (08.04.06,MK)
     226             : !> \author Matthias Krack
     227             : ! **************************************************************************************************
     228       70615 :    SUBROUTINE qs_diis_b_step(diis_buffer, mo_array, kc, sc, delta, error_max, &
     229             :                              diis_step, eps_diis, nmixing, s_matrix, scf_section, roks)
     230             : 
     231             :       TYPE(qs_diis_buffer_type), POINTER                 :: diis_buffer
     232             :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mo_array
     233             :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: kc
     234             :       TYPE(cp_fm_type), INTENT(IN)                       :: sc
     235             :       REAL(KIND=dp), INTENT(IN)                          :: delta
     236             :       REAL(KIND=dp), INTENT(OUT)                         :: error_max
     237             :       LOGICAL, INTENT(OUT)                               :: diis_step
     238             :       REAL(KIND=dp), INTENT(IN)                          :: eps_diis
     239             :       INTEGER, INTENT(IN), OPTIONAL                      :: nmixing
     240             :       TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
     241             :          POINTER                                         :: s_matrix
     242             :       TYPE(section_vals_type), POINTER                   :: scf_section
     243             :       LOGICAL, INTENT(IN), OPTIONAL                      :: roks
     244             : 
     245             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_diis_b_step'
     246             :       REAL(KIND=dp), PARAMETER :: eigenvalue_threshold = 1.0E-12_dp
     247             : 
     248             :       CHARACTER(LEN=2*default_string_length)             :: message
     249             :       INTEGER                                            :: handle, homo, ib, imo, ispin, jb, &
     250             :                                                             my_nmixing, nao, nb, nb1, nmo, nspin, &
     251             :                                                             output_unit
     252             :       LOGICAL                                            :: eigenvectors_discarded, my_roks
     253             :       REAL(KIND=dp)                                      :: maxocc, tmp
     254       70615 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: ev, occ
     255       70615 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: occa, occb
     256       70615 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: a, b
     257             :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     258             :       TYPE(cp_fm_type), POINTER                          :: c, new_errors, old_errors, parameters
     259             :       TYPE(cp_logger_type), POINTER                      :: logger
     260             : 
     261             : ! -------------------------------------------------------------------------
     262             : 
     263       70615 :       CALL timeset(routineN, handle)
     264             : 
     265       70615 :       nspin = SIZE(mo_array)
     266       70615 :       diis_step = .FALSE.
     267             : 
     268       70615 :       IF (PRESENT(roks)) THEN
     269         934 :          my_roks = .TRUE.
     270         934 :          nspin = 1
     271             :       ELSE
     272             :          my_roks = .FALSE.
     273             :       END IF
     274             : 
     275       70615 :       my_nmixing = 2
     276       70615 :       IF (PRESENT(nmixing)) my_nmixing = nmixing
     277             : 
     278       70615 :       NULLIFY (c, new_errors, old_errors, parameters, matrix_struct, a, b, occa, occb)
     279       70615 :       logger => cp_get_default_logger()
     280             : 
     281             :       ! Quick return, if no DIIS is requested
     282             : 
     283       70615 :       IF (diis_buffer%nbuffer < 1) THEN
     284           0 :          CALL timestop(handle)
     285             :          RETURN
     286             :       END IF
     287             : 
     288             :       CALL cp_fm_get_info(kc(1), &
     289       70615 :                           matrix_struct=matrix_struct)
     290             :       CALL qs_diis_b_check_i_alloc(diis_buffer, &
     291             :                                    matrix_struct=matrix_struct, &
     292             :                                    nspin=nspin, &
     293       70615 :                                    scf_section=scf_section)
     294             : 
     295       70615 :       error_max = 0.0_dp
     296             : 
     297       70615 :       ib = MODULO(diis_buffer%ncall, diis_buffer%nbuffer) + 1
     298       70615 :       diis_buffer%ncall = diis_buffer%ncall + 1
     299       70615 :       nb = MIN(diis_buffer%ncall, diis_buffer%nbuffer)
     300             : 
     301      150118 :       DO ispin = 1, nspin
     302             : 
     303             :          CALL get_mo_set(mo_set=mo_array(ispin), &
     304             :                          nao=nao, &
     305             :                          nmo=nmo, &
     306             :                          homo=homo, &
     307             :                          mo_coeff=c, &
     308             :                          occupation_numbers=occa, &
     309       79503 :                          maxocc=maxocc)
     310             : 
     311       79503 :          new_errors => diis_buffer%error(ib, ispin)
     312       79503 :          parameters => diis_buffer%param(ib, ispin)
     313             : 
     314             :          ! Copy the Kohn-Sham matrix K to the DIIS buffer
     315             : 
     316       79503 :          CALL cp_fm_to_fm(kc(ispin), parameters)
     317             : 
     318       79503 :          IF (my_roks) THEN
     319             : 
     320        2802 :             ALLOCATE (occ(nmo))
     321             : 
     322             :             CALL get_mo_set(mo_set=mo_array(2), &
     323         934 :                             occupation_numbers=occb)
     324             : 
     325       15120 :             DO imo = 1, nmo
     326       15120 :                occ(imo) = SQRT(occa(imo) + occb(imo))
     327             :             END DO
     328             : 
     329         934 :             CALL cp_fm_to_fm(c, sc)
     330         934 :             CALL cp_fm_column_scale(sc, occ(1:homo))
     331             : 
     332             :             ! KC <- K*C
     333         934 :             CALL cp_fm_symm("L", "U", nao, homo, 1.0_dp, parameters, sc, 0.0_dp, kc(ispin))
     334             : 
     335         934 :             IF (PRESENT(s_matrix)) THEN
     336         484 :                CALL copy_dbcsr_to_fm(s_matrix(1)%matrix, new_errors)
     337             :                ! SC <- S*C
     338         484 :                CALL cp_fm_symm("L", "U", nao, homo, 1.0_dp, new_errors, c, 0.0_dp, sc)
     339         484 :                CALL cp_fm_column_scale(sc, occ(1:homo))
     340             :             END IF
     341             : 
     342             :             ! new_errors <- KC*(SC)^T - (SC)*(KC)^T = K*P*S - S*P*K
     343             :             ! or for an orthogonal basis
     344             :             ! new_errors <- KC*C^T - C*(KC)^T = K*P - P*K with S = I
     345         934 :             CALL parallel_gemm("N", "T", nao, nao, homo, 1.0_dp, sc, kc(ispin), 0.0_dp, new_errors)
     346         934 :             CALL parallel_gemm("N", "T", nao, nao, homo, 1.0_dp, kc(ispin), sc, -1.0_dp, new_errors)
     347             : 
     348         934 :             DEALLOCATE (occ)
     349             : 
     350             :          ELSE
     351             : 
     352             :             ! KC <- K*C
     353       78569 :             CALL cp_fm_symm("L", "U", nao, homo, maxocc, parameters, c, 0.0_dp, kc(ispin))
     354             : 
     355       78569 :             IF (PRESENT(s_matrix)) THEN
     356             :                ! I guess that this copy can be avoided for LSD
     357       62563 :                CALL copy_dbcsr_to_fm(s_matrix(1)%matrix, new_errors)
     358             :                ! sc <- S*C
     359       62563 :                CALL cp_fm_symm("L", "U", nao, homo, 2.0_dp, new_errors, c, 0.0_dp, sc)
     360             :                ! new_errors <- KC*(SC)^T - (SC)*(KC)^T = K*P*S - S*P*K
     361       62563 :                CALL parallel_gemm("N", "T", nao, nao, homo, 1.0_dp, sc, kc(ispin), 0.0_dp, new_errors)
     362       62563 :                CALL parallel_gemm("N", "T", nao, nao, homo, 1.0_dp, kc(ispin), sc, -1.0_dp, new_errors)
     363             :             ELSE
     364             :                ! new_errors <- KC*(C)^T - C*(KC)^T = K*P - P*K
     365       16006 :                CALL parallel_gemm("N", "T", nao, nao, homo, 1.0_dp, c, kc(ispin), 0.0_dp, new_errors)
     366       16006 :                CALL parallel_gemm("N", "T", nao, nao, homo, 1.0_dp, kc(ispin), c, -1.0_dp, new_errors)
     367             :             END IF
     368             : 
     369             :          END IF
     370             : 
     371       79503 :          CALL cp_fm_maxabsval(new_errors, tmp)
     372      229621 :          error_max = MAX(error_max, tmp)
     373             : 
     374             :       END DO
     375             : 
     376             :       ! Check, if a DIIS step is appropriate
     377             : 
     378       70615 :       diis_step = ((diis_buffer%ncall >= my_nmixing) .AND. (delta < eps_diis))
     379             : 
     380             :       output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DIIS_INFO", &
     381       70615 :                                          extension=".scfLog")
     382       70615 :       IF (output_unit > 0) THEN
     383             :          WRITE (UNIT=output_unit, FMT="(/,T9,A,I4,/,(T9,A,ES12.3))") &
     384         270 :             "DIIS | Current SCF DIIS buffer size:         ", nb, &
     385         270 :             "DIIS | Maximum SCF DIIS error vector element:", error_max, &
     386         270 :             "DIIS | Current SCF convergence:              ", delta, &
     387         540 :             "DIIS | Threshold value for a DIIS step:      ", eps_diis
     388         270 :          IF (error_max < eps_diis) THEN
     389             :             WRITE (UNIT=output_unit, FMT="(T9,A)") &
     390         257 :                "DIIS | => The SCF DIIS buffer will be updated"
     391             :          ELSE
     392             :             WRITE (UNIT=output_unit, FMT="(T9,A)") &
     393          13 :                "DIIS | => No update of the SCF DIIS buffer"
     394             :          END IF
     395         270 :          IF (diis_step .AND. (error_max < eps_diis)) THEN
     396             :             WRITE (UNIT=output_unit, FMT="(T9,A,/)") &
     397         145 :                "DIIS | => A SCF DIIS step will be performed"
     398             :          ELSE
     399             :             WRITE (UNIT=output_unit, FMT="(T9,A,/)") &
     400         125 :                "DIIS | => No SCF DIIS step will be performed"
     401             :          END IF
     402             :       END IF
     403             : 
     404             :       ! Update the SCF DIIS buffer
     405             : 
     406       70615 :       IF (error_max < eps_diis) THEN
     407             : 
     408       67931 :          b => diis_buffer%b_matrix
     409             : 
     410      285339 :          DO jb = 1, nb
     411      217408 :             b(jb, ib) = 0.0_dp
     412      463102 :             DO ispin = 1, nspin
     413      245694 :                old_errors => diis_buffer%error(jb, ispin)
     414      245694 :                new_errors => diis_buffer%error(ib, ispin)
     415      245694 :                CALL cp_fm_trace(old_errors, new_errors, tmp)
     416      463102 :                b(jb, ib) = b(jb, ib) + tmp
     417             :             END DO
     418      285339 :             b(ib, jb) = b(jb, ib)
     419             :          END DO
     420             : 
     421             :       ELSE
     422             : 
     423        2684 :          diis_step = .FALSE.
     424             : 
     425             :       END IF
     426             : 
     427             :       ! Perform DIIS step
     428             : 
     429       70615 :       IF (diis_step) THEN
     430             : 
     431       49713 :          nb1 = nb + 1
     432             : 
     433      198852 :          ALLOCATE (a(nb1, nb1))
     434      149139 :          ALLOCATE (b(nb1, nb1))
     435      149139 :          ALLOCATE (ev(nb1))
     436             : 
     437             :          ! Set up the linear DIIS equation system
     438             : 
     439     1729633 :          b(1:nb, 1:nb) = diis_buffer%b_matrix(1:nb, 1:nb)
     440             : 
     441      227533 :          b(1:nb, nb1) = -1.0_dp
     442      227533 :          b(nb1, 1:nb) = -1.0_dp
     443       49713 :          b(nb1, nb1) = 0.0_dp
     444             : 
     445             :          ! Solve the linear DIIS equation system
     446             : 
     447      277246 :          ev(1:nb1) = 0.0_dp
     448       49713 :          CALL diamat_all(b(1:nb1, 1:nb1), ev(1:nb1))
     449             : 
     450     2639765 :          a(1:nb1, 1:nb1) = b(1:nb1, 1:nb1)
     451             : 
     452       49713 :          eigenvectors_discarded = .FALSE.
     453             : 
     454      277246 :          DO jb = 1, nb1
     455      277246 :             IF (ABS(ev(jb)) < eigenvalue_threshold) THEN
     456       25186 :                IF (output_unit > 0) THEN
     457          96 :                   IF (.NOT. eigenvectors_discarded) THEN
     458             :                      WRITE (UNIT=output_unit, FMT="(T9,A)") &
     459          46 :                         "DIIS | Checking eigenvalues of the DIIS error matrix"
     460             :                   END IF
     461             :                   WRITE (UNIT=message, FMT="(T9,A,I6,A,ES10.1,A,ES10.1)") &
     462          96 :                      "DIIS | Eigenvalue ", jb, " = ", ev(jb), " is smaller than "// &
     463         192 :                      "threshold ", eigenvalue_threshold
     464          96 :                   CALL compress(message)
     465          96 :                   WRITE (UNIT=output_unit, FMT="(T9,A)") TRIM(message)
     466          96 :                   eigenvectors_discarded = .TRUE.
     467             :                END IF
     468      146848 :                a(1:nb1, jb) = 0.0_dp
     469             :             ELSE
     470     1148178 :                a(1:nb1, jb) = a(1:nb1, jb)/ev(jb)
     471             :             END IF
     472             :          END DO
     473             : 
     474       49713 :          IF ((output_unit > 0) .AND. eigenvectors_discarded) THEN
     475             :             WRITE (UNIT=output_unit, FMT="(T9,A,/)") &
     476          46 :                "DIIS | The corresponding eigenvectors were discarded"
     477             :          END IF
     478             : 
     479     1295026 :          ev(1:nb) = MATMUL(a(1:nb, 1:nb1), b(nb1, 1:nb1))
     480             : 
     481             :          ! Update Kohn-Sham matrix
     482             : 
     483      105676 :          DO ispin = 1, nspin
     484       55963 :             CALL cp_fm_set_all(kc(ispin), 0.0_dp)
     485      306880 :             DO jb = 1, nb
     486      201204 :                parameters => diis_buffer%param(jb, ispin)
     487      257167 :                CALL cp_fm_scale_and_add(1.0_dp, kc(ispin), -ev(jb), parameters)
     488             :             END DO
     489             :          END DO
     490             : 
     491       49713 :          DEALLOCATE (a)
     492       49713 :          DEALLOCATE (b)
     493       49713 :          DEALLOCATE (ev)
     494             : 
     495             :       ELSE
     496             : 
     497       44442 :          DO ispin = 1, nspin
     498       23540 :             parameters => diis_buffer%param(ib, ispin)
     499       44442 :             CALL cp_fm_to_fm(parameters, kc(ispin))
     500             :          END DO
     501             : 
     502             :       END IF
     503             : 
     504             :       CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
     505       70615 :                                         "PRINT%DIIS_INFO")
     506             : 
     507       70615 :       CALL timestop(handle)
     508             : 
     509      141230 :    END SUBROUTINE qs_diis_b_step
     510             : 
     511             : ! **************************************************************************************************
     512             : !> \brief clears the buffer
     513             : !> \param diis_buffer the buffer to clear
     514             : !> \par History
     515             : !>      02.2003 created [fawzi]
     516             : !> \author fawzi
     517             : ! **************************************************************************************************
     518       12886 :    PURE SUBROUTINE qs_diis_b_clear(diis_buffer)
     519             : 
     520             :       TYPE(qs_diis_buffer_type), INTENT(INOUT)           :: diis_buffer
     521             : 
     522       12886 :       diis_buffer%ncall = 0
     523             : 
     524       12886 :    END SUBROUTINE qs_diis_b_clear
     525             : 
     526             : ! **************************************************************************************************
     527             : !> \brief Update the SCF DIIS buffer in linear scaling SCF (LS-SCF),
     528             : !>        and if appropriate does a diis step.
     529             : !> \param diis_buffer ...
     530             : !> \param qs_env ...
     531             : !> \param ls_scf_env ...
     532             : !> \param unit_nr ...
     533             : !> \param iscf ...
     534             : !> \param diis_step ...
     535             : !> \param eps_diis ...
     536             : !> \param nmixing ...
     537             : !> \param s_matrix ...
     538             : !> \param threshold ...
     539             : !> \par History
     540             : !>      - Adapted for LS-SCF (10-11-14) from qs_diis_b_step
     541             : !> \author Fredy W. Aquino
     542             : ! **************************************************************************************************
     543             : 
     544          18 :    SUBROUTINE qs_diis_b_step_4lscf(diis_buffer, qs_env, ls_scf_env, unit_nr, iscf, &
     545             :                                    diis_step, eps_diis, nmixing, s_matrix, threshold)
     546             : ! Note.- Input: ls_scf_env%matrix_p(ispin) , Density Matrix
     547             : !               matrix_ks (from qs_env)    , Kohn-Sham Matrix  (IN/OUT)
     548             : 
     549             :       TYPE(qs_diis_buffer_type_sparse), POINTER          :: diis_buffer
     550             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     551             :       TYPE(ls_scf_env_type)                              :: ls_scf_env
     552             :       INTEGER, INTENT(IN)                                :: unit_nr, iscf
     553             :       LOGICAL, INTENT(OUT)                               :: diis_step
     554             :       REAL(KIND=dp), INTENT(IN)                          :: eps_diis
     555             :       INTEGER, INTENT(IN), OPTIONAL                      :: nmixing
     556             :       TYPE(dbcsr_type), OPTIONAL                         :: s_matrix
     557             :       REAL(KIND=dp), INTENT(IN)                          :: threshold
     558             : 
     559             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_diis_b_step_4lscf'
     560             :       REAL(KIND=dp), PARAMETER :: eigenvalue_threshold = 1.0E-12_dp
     561             : 
     562             :       INTEGER                                            :: handle, ib, ispin, jb, my_nmixing, nb, &
     563             :                                                             nb1, nspin
     564             :       REAL(KIND=dp)                                      :: error_max, tmp
     565          18 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: ev
     566          18 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: a, b
     567             :       TYPE(cp_logger_type), POINTER                      :: logger
     568          18 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks
     569             :       TYPE(dbcsr_type)                                   :: matrix_KSerr_t, matrix_tmp
     570             :       TYPE(dbcsr_type), POINTER                          :: new_errors, old_errors, parameters
     571             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     572             : 
     573          18 :       CALL timeset(routineN, handle)
     574          18 :       nspin = ls_scf_env%nspins
     575          18 :       diis_step = .FALSE.
     576          18 :       my_nmixing = 2
     577          18 :       IF (PRESENT(nmixing)) my_nmixing = nmixing
     578          18 :       NULLIFY (new_errors, old_errors, parameters, a, b)
     579          18 :       logger => cp_get_default_logger()
     580             :       ! Quick return, if no DIIS is requested
     581          18 :       IF (diis_buffer%nbuffer < 1) THEN
     582           0 :          CALL timestop(handle)
     583             :          RETURN
     584             :       END IF
     585             : 
     586             : ! Getting current Kohn-Sham matrix from qs_env
     587             :       CALL get_qs_env(qs_env, &
     588             :                       para_env=para_env, &
     589          18 :                       matrix_ks=matrix_ks)
     590             :       CALL qs_diis_b_check_i_alloc_sparse( &
     591             :          diis_buffer, &
     592             :          ls_scf_env, &
     593          18 :          nspin)
     594          18 :       error_max = 0.0_dp
     595             : 
     596          18 :       ib = MODULO(diis_buffer%ncall, diis_buffer%nbuffer) + 1
     597          18 :       diis_buffer%ncall = diis_buffer%ncall + 1
     598          18 :       nb = MIN(diis_buffer%ncall, diis_buffer%nbuffer)
     599             : ! Create scratch arrays
     600             :       CALL dbcsr_create(matrix_tmp, &
     601             :                         template=ls_scf_env%matrix_ks(1), &
     602          18 :                         matrix_type='N')
     603          18 :       CALL dbcsr_set(matrix_tmp, 0.0_dp) ! reset matrix
     604             :       CALL dbcsr_create(matrix_KSerr_t, &
     605             :                         template=ls_scf_env%matrix_ks(1), &
     606          18 :                         matrix_type='N')
     607          18 :       CALL dbcsr_set(matrix_KSerr_t, 0.0_dp) ! reset matrix
     608             : 
     609          46 :       DO ispin = 1, nspin ! ------ Loop-ispin----START
     610             : 
     611          28 :          new_errors => diis_buffer%error(ib, ispin)%matrix
     612          28 :          parameters => diis_buffer%param(ib, ispin)%matrix
     613             :          ! Copy the Kohn-Sham matrix K to the DIIS buffer
     614             :          CALL dbcsr_copy(parameters, & ! out
     615          28 :                          matrix_ks(ispin)%matrix) ! in
     616             : 
     617          28 :          IF (PRESENT(s_matrix)) THEN ! if-s_matrix ---------- START
     618             : ! Calculate Kohn-Sham error (non-orthogonal)= K*P*S-(K*P*S)^T
     619             : ! matrix_tmp = P*S
     620             :             CALL dbcsr_multiply("N", "N", &
     621             :                                 1.0_dp, ls_scf_env%matrix_p(ispin), &
     622             :                                 s_matrix, &
     623             :                                 0.0_dp, matrix_tmp, &
     624          28 :                                 filter_eps=threshold)
     625             : ! new_errors= K*P*S
     626             :             CALL dbcsr_multiply("N", "N", &
     627             :                                 1.0_dp, matrix_ks(ispin)%matrix, &
     628             :                                 matrix_tmp, &
     629             :                                 0.0_dp, new_errors, &
     630          28 :                                 filter_eps=threshold)
     631             : ! matrix_KSerr_t= transpose(K*P*S)
     632             :             CALL dbcsr_transposed(matrix_KSerr_t, &
     633          28 :                                   new_errors)
     634             : ! new_errors=K*P*S-transpose(K*P*S)
     635             :             CALL dbcsr_add(new_errors, &
     636             :                            matrix_KSerr_t, &
     637          28 :                            1.0_dp, -1.0_dp)
     638             :          ELSE ! if-s_matrix ---------- MID
     639             : ! Calculate Kohn-Sham error (orthogonal)= K*P - P*K
     640             : ! new_errors=K*P
     641             :             CALL dbcsr_multiply("N", "N", &
     642             :                                 1.0_dp, matrix_ks(ispin)%matrix, &
     643             :                                 ls_scf_env%matrix_p(ispin), &
     644             :                                 0.0_dp, new_errors, &
     645           0 :                                 filter_eps=threshold)
     646             : ! matrix_KSerr_t= transpose(K*P)
     647             :             CALL dbcsr_transposed(matrix_KSerr_t, &
     648           0 :                                   new_errors)
     649             : ! new_errors=K*P-transpose(K*P)
     650             :             CALL dbcsr_add(new_errors, &
     651             :                            matrix_KSerr_t, &
     652           0 :                            1.0_dp, -1.0_dp)
     653             :          END IF ! if-s_matrix ---------- END
     654             : 
     655          28 :          tmp = dbcsr_maxabs(new_errors)
     656          46 :          error_max = MAX(error_max, tmp)
     657             : 
     658             :       END DO ! ------ Loop-ispin----END
     659             : 
     660             :       ! Check, if a DIIS step is appropriate
     661             : 
     662          18 :       diis_step = (diis_buffer%ncall >= my_nmixing)
     663             : 
     664          18 :       IF (unit_nr > 0) THEN
     665             :          WRITE (unit_nr, '(A29,I3,A3,4(I3,A1))') &
     666           9 :             "DIIS: (ncall,nbuffer,ib,nb)=(", iscf, ")=(", &
     667          18 :             diis_buffer%ncall, ",", diis_buffer%nbuffer, ",", ib, ",", nb, ")"
     668             :          WRITE (unit_nr, '(A57,I3,A3,L1,A1,F10.8,A1,F4.2,A1,L1,A1)') &
     669           9 :             "DIIS: (diis_step,error_max,eps_diis,error_max<eps_diis)=(", &
     670           9 :             iscf, ")=(", diis_step, ",", error_max, ",", eps_diis, ",", &
     671          18 :             (error_max < eps_diis), ")"
     672             :          WRITE (unit_nr, '(A75)') &
     673           9 :             "DIIS: diis_step=T : Perform DIIS  error_max<eps_diis=T : Update DIIS buffer"
     674             :       END IF
     675             : 
     676             :       ! Update the SCF DIIS buffer
     677          18 :       IF (error_max < eps_diis) THEN
     678          18 :          b => diis_buffer%b_matrix
     679          66 :          DO jb = 1, nb
     680          48 :             b(jb, ib) = 0.0_dp
     681         124 :             DO ispin = 1, nspin
     682          76 :                old_errors => diis_buffer%error(jb, ispin)%matrix
     683          76 :                new_errors => diis_buffer%error(ib, ispin)%matrix
     684             :                CALL dbcsr_dot(old_errors, &
     685             :                               new_errors, &
     686          76 :                               tmp) ! out : < f_i | f_j >
     687         124 :                b(jb, ib) = b(jb, ib) + tmp
     688             :             END DO ! end-loop-ispin
     689          66 :             b(ib, jb) = b(jb, ib)
     690             :          END DO ! end-loop-jb
     691             :       ELSE
     692           0 :          diis_step = .FALSE.
     693             :       END IF
     694             : 
     695             :       ! Perform DIIS step
     696          18 :       IF (diis_step) THEN
     697          14 :          nb1 = nb + 1
     698          56 :          ALLOCATE (a(nb1, nb1))
     699          42 :          ALLOCATE (b(nb1, nb1))
     700          42 :          ALLOCATE (ev(nb1))
     701             :          ! Set up the linear DIIS equation system
     702         398 :          b(1:nb, 1:nb) = diis_buffer%b_matrix(1:nb, 1:nb)
     703          58 :          b(1:nb, nb1) = -1.0_dp
     704          58 :          b(nb1, 1:nb) = -1.0_dp
     705          14 :          b(nb1, nb1) = 0.0_dp
     706             :          ! Solve the linear DIIS equation system
     707          14 :          CALL diamat_all(b(1:nb1, 1:nb1), ev(1:nb1))
     708         630 :          a(1:nb1, 1:nb1) = b(1:nb1, 1:nb1)
     709          72 :          DO jb = 1, nb1
     710          72 :             IF (ABS(ev(jb)) < eigenvalue_threshold) THEN
     711           0 :                a(1:nb1, jb) = 0.0_dp
     712             :             ELSE
     713         308 :                a(1:nb1, jb) = a(1:nb1, jb)/ev(jb)
     714             :             END IF
     715             :          END DO ! end-loop-jb
     716             : 
     717         308 :          ev(1:nb) = MATMUL(a(1:nb, 1:nb1), b(nb1, 1:nb1))
     718             : 
     719             :          ! Update Kohn-Sham matrix
     720          14 :          IF (iscf .GE. ls_scf_env%iter_ini_diis) THEN ! if-iscf-to-updateKS------ START
     721             : 
     722          14 :             IF (unit_nr > 0) THEN
     723           7 :                WRITE (unit_nr, '(A40,I3)') 'DIIS: Updating Kohn-Sham matrix at iscf=', iscf
     724             :             END IF
     725             : 
     726          36 :             DO ispin = 1, nspin
     727             :                CALL dbcsr_set(matrix_ks(ispin)%matrix, & ! reset matrix
     728          22 :                               0.0_dp)
     729         106 :                DO jb = 1, nb
     730          70 :                   parameters => diis_buffer%param(jb, ispin)%matrix
     731             :                   CALL dbcsr_add(matrix_ks(ispin)%matrix, parameters, &
     732          92 :                                  1.0_dp, -ev(jb))
     733             :                END DO ! end-loop-jb
     734             :             END DO ! end-loop-ispin
     735             :          END IF ! if-iscf-to-updateKS------ END
     736             : 
     737          14 :          DEALLOCATE (a)
     738          14 :          DEALLOCATE (b)
     739          14 :          DEALLOCATE (ev)
     740             : 
     741             :       ELSE
     742          10 :          DO ispin = 1, nspin
     743           6 :             parameters => diis_buffer%param(ib, ispin)%matrix
     744             :             CALL dbcsr_copy(parameters, & ! out
     745          10 :                             matrix_ks(ispin)%matrix) ! in
     746             :          END DO ! end-loop-ispin
     747             :       END IF
     748          18 :       CALL dbcsr_release(matrix_tmp)
     749          18 :       CALL dbcsr_release(matrix_KSerr_t)
     750          18 :       CALL timestop(handle)
     751             : 
     752          18 :    END SUBROUTINE qs_diis_b_step_4lscf
     753             : 
     754             : ! **************************************************************************************************
     755             : !> \brief Allocate and initialize a DIIS buffer with a buffer size of nbuffer.
     756             : !> \param diis_buffer the buffer to initialize
     757             : !> \param ls_scf_env ...
     758             : !> \param nspin ...
     759             : !> \par History
     760             : !>      - Adapted from qs_diis_b_check_i_alloc for sparse matrices and
     761             : !>        used in LS-SCF module (ls_scf_main) (10-11-14)
     762             : !> \author Fredy W. Aquino
     763             : !> \note
     764             : !>      check to allocate matrices only when needed
     765             : ! **************************************************************************************************
     766             : 
     767          18 :    SUBROUTINE qs_diis_b_check_i_alloc_sparse(diis_buffer, ls_scf_env, &
     768             :                                              nspin)
     769             : 
     770             :       TYPE(qs_diis_buffer_type_sparse), INTENT(INOUT)    :: diis_buffer
     771             :       TYPE(ls_scf_env_type)                              :: ls_scf_env
     772             :       INTEGER, INTENT(IN)                                :: nspin
     773             : 
     774             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_diis_b_check_i_alloc_sparse'
     775             : 
     776             :       INTEGER                                            :: handle, ibuffer, ispin, nbuffer
     777             :       TYPE(cp_logger_type), POINTER                      :: logger
     778             : 
     779             : ! -------------------------------------------------------------------------
     780             : 
     781          18 :       CALL timeset(routineN, handle)
     782             : 
     783          18 :       logger => cp_get_default_logger()
     784             : 
     785          18 :       nbuffer = diis_buffer%nbuffer
     786             : 
     787          18 :       IF (.NOT. ASSOCIATED(diis_buffer%error)) THEN
     788          46 :          ALLOCATE (diis_buffer%error(nbuffer, nspin))
     789             : 
     790          10 :          DO ispin = 1, nspin
     791          34 :             DO ibuffer = 1, nbuffer
     792          24 :                ALLOCATE (diis_buffer%error(ibuffer, ispin)%matrix)
     793             : 
     794             :                CALL dbcsr_create(diis_buffer%error(ibuffer, ispin)%matrix, &
     795             :                                  template=ls_scf_env%matrix_ks(1), &
     796          30 :                                  matrix_type='N')
     797             :             END DO
     798             :          END DO
     799             :       END IF
     800             : 
     801          18 :       IF (.NOT. ASSOCIATED(diis_buffer%param)) THEN
     802          46 :          ALLOCATE (diis_buffer%param(nbuffer, nspin))
     803             : 
     804          10 :          DO ispin = 1, nspin
     805          34 :             DO ibuffer = 1, nbuffer
     806          24 :                ALLOCATE (diis_buffer%param(ibuffer, ispin)%matrix)
     807             :                CALL dbcsr_create(diis_buffer%param(ibuffer, ispin)%matrix, &
     808             :                                  template=ls_scf_env%matrix_ks(1), &
     809          30 :                                  matrix_type='N')
     810             :             END DO
     811             :          END DO
     812             :       END IF
     813             : 
     814          18 :       IF (.NOT. ASSOCIATED(diis_buffer%b_matrix)) THEN
     815          16 :          ALLOCATE (diis_buffer%b_matrix(nbuffer + 1, nbuffer + 1))
     816             : 
     817         124 :          diis_buffer%b_matrix = 0.0_dp
     818             :       END IF
     819             : 
     820          18 :       CALL timestop(handle)
     821             : 
     822          18 :    END SUBROUTINE qs_diis_b_check_i_alloc_sparse
     823             : 
     824             : ! **************************************************************************************************
     825             : !> \brief clears the DIIS buffer in LS-SCF calculation
     826             : !> \param diis_buffer the buffer to clear
     827             : !> \par History
     828             : !>      10-11-14 created [FA] modified from qs_diis_b_clear
     829             : !> \author Fredy W. Aquino
     830             : ! **************************************************************************************************
     831             : 
     832           4 :    PURE SUBROUTINE qs_diis_b_clear_sparse(diis_buffer)
     833             : 
     834             :       TYPE(qs_diis_buffer_type_sparse), INTENT(INOUT)    :: diis_buffer
     835             : 
     836           4 :       diis_buffer%ncall = 0
     837             : 
     838           4 :    END SUBROUTINE qs_diis_b_clear_sparse
     839             : 
     840             : ! **************************************************************************************************
     841             : !> \brief Allocates an SCF DIIS buffer for LS-SCF calculation
     842             : !> \param diis_buffer the buffer to create
     843             : !> \param nbuffer ...
     844             : !> \par History
     845             : !>      10-11-14 created [FA] modified from qs_diis_b_create
     846             : !> \author Fredy W. Aquino
     847             : ! **************************************************************************************************
     848           4 :    PURE SUBROUTINE qs_diis_b_create_sparse(diis_buffer, nbuffer)
     849             : 
     850             :       TYPE(qs_diis_buffer_type_sparse), INTENT(OUT)      :: diis_buffer
     851             :       INTEGER, INTENT(in)                                :: nbuffer
     852             : 
     853             :       NULLIFY (diis_buffer%b_matrix)
     854             :       NULLIFY (diis_buffer%error)
     855             :       NULLIFY (diis_buffer%param)
     856           4 :       diis_buffer%nbuffer = nbuffer
     857           4 :       diis_buffer%ncall = 0
     858             : 
     859           4 :    END SUBROUTINE qs_diis_b_create_sparse
     860             : 
     861             : ! **************************************************************************************************
     862             : !> \brief Allocates an SCF DIIS buffer for k-points
     863             : !> \param diis_buffer the buffer to create
     864             : !> \param nbuffer ...
     865             : ! **************************************************************************************************
     866         134 :    SUBROUTINE qs_diis_b_create_kp(diis_buffer, nbuffer)
     867             : 
     868             :       TYPE(qs_diis_buffer_type_kp), INTENT(OUT)          :: diis_buffer
     869             :       INTEGER, INTENT(in)                                :: nbuffer
     870             : 
     871             :       NULLIFY (diis_buffer%b_matrix)
     872             :       NULLIFY (diis_buffer%error)
     873             :       NULLIFY (diis_buffer%param)
     874             :       NULLIFY (diis_buffer%smat)
     875         134 :       diis_buffer%nbuffer = nbuffer
     876         134 :       diis_buffer%ncall = 0
     877             : 
     878         134 :    END SUBROUTINE qs_diis_b_create_kp
     879             : 
     880             : ! **************************************************************************************************
     881             : !> \brief Allocate and initialize a DIIS buffer for nao*nao parameter
     882             : !>      variables and with a buffer size of nbuffer, in the k-point case
     883             : !> \param diis_buffer the buffer to initialize
     884             : !> \param matrix_struct the structure for the matrix of the buffer note: this is in the kp subgroup
     885             : !> \param nspin ...
     886             : !> \param nkp ...
     887             : !> \param scf_section ...
     888             : ! **************************************************************************************************
     889        9508 :    SUBROUTINE qs_diis_b_check_i_alloc_kp(diis_buffer, matrix_struct, nspin, nkp, scf_section)
     890             : 
     891             :       TYPE(qs_diis_buffer_type_kp), INTENT(INOUT)        :: diis_buffer
     892             :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     893             :       INTEGER, INTENT(IN)                                :: nspin, nkp
     894             :       TYPE(section_vals_type), POINTER                   :: scf_section
     895             : 
     896             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_diis_b_check_i_alloc_kp'
     897             : 
     898             :       INTEGER                                            :: handle, ibuffer, ikp, ispin, nbuffer, &
     899             :                                                             output_unit
     900             :       TYPE(cp_logger_type), POINTER                      :: logger
     901             : 
     902             : ! -------------------------------------------------------------------------
     903             : 
     904        9508 :       CALL timeset(routineN, handle)
     905             : 
     906        9508 :       logger => cp_get_default_logger()
     907             : 
     908        9508 :       nbuffer = diis_buffer%nbuffer
     909             : 
     910        9508 :       IF (.NOT. ASSOCIATED(diis_buffer%error)) THEN
     911        4070 :          ALLOCATE (diis_buffer%error(nbuffer, nspin, nkp))
     912             : 
     913         586 :          DO ikp = 1, nkp
     914        1206 :             DO ispin = 1, nspin
     915        3590 :                DO ibuffer = 1, nbuffer
     916             :                   CALL cp_cfm_create(diis_buffer%error(ibuffer, ispin, ikp), &
     917             :                                      name="qs_diis_b%error("// &
     918             :                                      TRIM(ADJUSTL(cp_to_string(ibuffer)))//","// &
     919             :                                      TRIM(ADJUSTL(cp_to_string(ibuffer)))//")", &
     920        3100 :                                      matrix_struct=matrix_struct)
     921             :                END DO
     922             :             END DO
     923             :          END DO
     924             :       END IF
     925             : 
     926        9508 :       IF (.NOT. ASSOCIATED(diis_buffer%param)) THEN
     927        4070 :          ALLOCATE (diis_buffer%param(nbuffer, nspin, nkp))
     928             : 
     929         586 :          DO ikp = 1, nkp
     930        1206 :             DO ispin = 1, nspin
     931        3590 :                DO ibuffer = 1, nbuffer
     932             :                   CALL cp_cfm_create(diis_buffer%param(ibuffer, ispin, ikp), &
     933             :                                      name="qs_diis_b%param("// &
     934             :                                      TRIM(ADJUSTL(cp_to_string(ibuffer)))//","// &
     935             :                                      TRIM(ADJUSTL(cp_to_string(ibuffer)))//")", &
     936        3100 :                                      matrix_struct=matrix_struct)
     937             :                END DO
     938             :             END DO
     939             :          END DO
     940             :       END IF
     941             : 
     942        9508 :       IF (.NOT. ASSOCIATED(diis_buffer%smat)) THEN
     943         778 :          ALLOCATE (diis_buffer%smat(nkp))
     944         586 :          DO ikp = 1, nkp
     945             :             CALL cp_cfm_create(diis_buffer%smat(ikp), &
     946             :                                name="kp_cfm_smat("// &
     947             :                                TRIM(ADJUSTL(cp_to_string(ibuffer)))//","// &
     948             :                                TRIM(ADJUSTL(cp_to_string(ibuffer)))//")", &
     949         586 :                                matrix_struct=matrix_struct)
     950             :          END DO
     951             :       END IF
     952             : 
     953        9508 :       IF (.NOT. ASSOCIATED(diis_buffer%b_matrix)) THEN
     954         480 :          ALLOCATE (diis_buffer%b_matrix(nbuffer + 1, nbuffer + 1))
     955        2976 :          diis_buffer%b_matrix = 0.0_dp
     956             :          output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DIIS_INFO", &
     957          96 :                                             extension=".scfLog")
     958          96 :          IF (output_unit > 0) THEN
     959             :             WRITE (UNIT=output_unit, FMT="(/,T9,A)") &
     960           0 :                "DIIS | The SCF DIIS buffer was allocated and initialized"
     961             :          END IF
     962             :          CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
     963          96 :                                            "PRINT%DIIS_INFO")
     964             :       END IF
     965             : 
     966        9508 :       CALL timestop(handle)
     967             : 
     968        9508 :    END SUBROUTINE qs_diis_b_check_i_alloc_kp
     969             : 
     970             : ! **************************************************************************************************
     971             : !> \brief clears the buffer
     972             : !> \param diis_buffer the buffer to clear
     973             : ! **************************************************************************************************
     974         862 :    PURE SUBROUTINE qs_diis_b_clear_kp(diis_buffer)
     975             : 
     976             :       TYPE(qs_diis_buffer_type_kp), INTENT(INOUT)        :: diis_buffer
     977             : 
     978         862 :       diis_buffer%ncall = 0
     979             : 
     980         862 :    END SUBROUTINE qs_diis_b_clear_kp
     981             : 
     982             : ! **************************************************************************************************
     983             : !> \brief Update info about the current buffer step ib and the current number of buffers nb
     984             : !> \param diis_buffer ...
     985             : !> \param ib ...
     986             : !> \param nb ...
     987             : ! **************************************************************************************************
     988        3946 :    SUBROUTINE qs_diis_b_info_kp(diis_buffer, ib, nb)
     989             :       TYPE(qs_diis_buffer_type_kp), POINTER              :: diis_buffer
     990             :       INTEGER, INTENT(OUT)                               :: ib, nb
     991             : 
     992        3946 :       ib = MODULO(diis_buffer%ncall, diis_buffer%nbuffer) + 1
     993        3946 :       diis_buffer%ncall = diis_buffer%ncall + 1
     994        3946 :       nb = MIN(diis_buffer%ncall, diis_buffer%nbuffer)
     995             : 
     996        3946 :    END SUBROUTINE qs_diis_b_info_kp
     997             : 
     998             : ! **************************************************************************************************
     999             : !> \brief Calculate and store the error for a given k-point
    1000             : !> \param diis_buffer ...
    1001             : !> \param ib ...
    1002             : !> \param mos ...
    1003             : !> \param kc ...
    1004             : !> \param sc ...
    1005             : !> \param ispin ...
    1006             : !> \param ikp ...
    1007             : !> \param nkp_local ...
    1008             : !> \param scf_section ...
    1009             : !> \note We assume that we always have an overlap matrix and complex matrices
    1010             : !> TODO: do we need to pass the kp weight for the back Fourier transform?
    1011             : ! **************************************************************************************************
    1012       28524 :    SUBROUTINE qs_diis_b_calc_err_kp(diis_buffer, ib, mos, kc, sc, ispin, ikp, nkp_local, scf_section)
    1013             :       TYPE(qs_diis_buffer_type_kp), POINTER              :: diis_buffer
    1014             :       INTEGER, INTENT(IN)                                :: ib
    1015             :       TYPE(mo_set_type), DIMENSION(:, :), POINTER        :: mos
    1016             :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: kc, sc
    1017             :       INTEGER, INTENT(IN)                                :: ispin, ikp, nkp_local
    1018             :       TYPE(section_vals_type), POINTER                   :: scf_section
    1019             : 
    1020             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_diis_b_calc_err_kp'
    1021             : 
    1022             :       INTEGER                                            :: handle, homo, nao, nmo, nspin
    1023             :       REAL(dp)                                           :: maxocc
    1024             :       TYPE(cp_cfm_type)                                  :: cmos
    1025             :       TYPE(cp_cfm_type), POINTER                         :: new_errors, parameters, smat
    1026             :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    1027             :       TYPE(cp_fm_type), POINTER                          :: imos, rmos
    1028             : 
    1029        9508 :       NULLIFY (matrix_struct, imos, rmos, parameters, new_errors, smat)
    1030             : 
    1031        9508 :       CALL timeset(routineN, handle)
    1032             : 
    1033             :       !Calculate the error for this given k-point, store the KS matrix as well as the ovlp matrix
    1034             :       !All of this happens within the kp subgroups
    1035             : 
    1036             :       ! Quick return, if no DIIS is requested
    1037        9508 :       IF (diis_buffer%nbuffer < 1) THEN
    1038           0 :          CALL timestop(handle)
    1039           0 :          RETURN
    1040             :       END IF
    1041        9508 :       nspin = SIZE(mos, 2)
    1042             : 
    1043        9508 :       CALL cp_cfm_get_info(kc, matrix_struct=matrix_struct)
    1044             :       CALL qs_diis_b_check_i_alloc_kp(diis_buffer, &
    1045             :                                       matrix_struct=matrix_struct, &
    1046             :                                       nspin=nspin, nkp=nkp_local, &
    1047        9508 :                                       scf_section=scf_section)
    1048             : 
    1049             :       !We calculate: e(ikp) = F(ikp)*P(ikp)*S(ikp) - S(ikp)*P(ikp)*F(ikp)
    1050        9508 :       CALL get_mo_set(mos(1, ispin), nao=nao, nmo=nmo, homo=homo, mo_coeff=rmos, maxocc=maxocc)
    1051        9508 :       CALL get_mo_set(mos(2, ispin), mo_coeff=imos)
    1052        9508 :       NULLIFY (matrix_struct)
    1053        9508 :       CALL cp_fm_get_info(rmos, matrix_struct=matrix_struct)
    1054        9508 :       CALL cp_cfm_create(cmos, matrix_struct)
    1055        9508 :       CALL cp_fm_to_cfm(rmos, imos, cmos)
    1056             : 
    1057        9508 :       new_errors => diis_buffer%error(ib, ispin, ikp)
    1058        9508 :       parameters => diis_buffer%param(ib, ispin, ikp)
    1059        9508 :       smat => diis_buffer%smat(ikp)
    1060             : 
    1061             :       !copy the KS and overlap matrices to the DIIS buffer
    1062        9508 :       CALL cp_cfm_to_cfm(kc, parameters)
    1063        9508 :       CALL cp_cfm_to_cfm(sc, smat)
    1064             : 
    1065             :       ! KC <- K*C
    1066        9508 :       CALL parallel_gemm("N", "N", nao, homo, nao, CMPLX(maxocc, KIND=dp), parameters, cmos, (0.0_dp, 0.0_dp), kc)
    1067             :       ! SC <- S*C
    1068        9508 :       CALL parallel_gemm("N", "N", nao, homo, nao, (2.0_dp, 0.0_dp), smat, cmos, (0.0_dp, 0.0_dp), sc)
    1069             : 
    1070             :       ! new_errors <- KC*(SC)^T - (SC)*(KC)^T = K*P*S - S*P*K
    1071        9508 :       CALL parallel_gemm("N", "T", nao, nao, homo, (1.0_dp, 0.0_dp), sc, kc, (0.0_dp, 0.0_dp), new_errors)
    1072        9508 :       CALL parallel_gemm("N", "T", nao, nao, homo, (1.0_dp, 0.0_dp), kc, sc, (-1.0_dp, 0.0_dp), new_errors)
    1073             : 
    1074             :       !clean-up
    1075        9508 :       CALL cp_cfm_release(cmos)
    1076             : 
    1077        9508 :       CALL timestop(handle)
    1078             : 
    1079        9508 :    END SUBROUTINE qs_diis_b_calc_err_kp
    1080             : 
    1081             : ! **************************************************************************************************
    1082             : !> \brief Update the SCF DIIS buffer, and if appropriate does a diis step, for k-points
    1083             : !> \param diis_buffer ...
    1084             : !> \param coeffs ...
    1085             : !> \param ib ...
    1086             : !> \param nb ...
    1087             : !> \param delta ...
    1088             : !> \param error_max ...
    1089             : !> \param diis_step ...
    1090             : !> \param eps_diis ...
    1091             : !> \param nspin ...
    1092             : !> \param nkp ...
    1093             : !> \param nkp_local ...
    1094             : !> \param nmixing ...
    1095             : !> \param scf_section ...
    1096             : !> \param para_env ...
    1097             : ! **************************************************************************************************
    1098        3946 :    SUBROUTINE qs_diis_b_step_kp(diis_buffer, coeffs, ib, nb, delta, error_max, diis_step, eps_diis, &
    1099             :                                 nspin, nkp, nkp_local, nmixing, scf_section, para_env)
    1100             : 
    1101             :       TYPE(qs_diis_buffer_type_kp), POINTER              :: diis_buffer
    1102             :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(INOUT)      :: coeffs
    1103             :       INTEGER, INTENT(IN)                                :: ib, nb
    1104             :       REAL(KIND=dp), INTENT(IN)                          :: delta
    1105             :       REAL(KIND=dp), INTENT(OUT)                         :: error_max
    1106             :       LOGICAL, INTENT(OUT)                               :: diis_step
    1107             :       REAL(KIND=dp), INTENT(IN)                          :: eps_diis
    1108             :       INTEGER, INTENT(IN)                                :: nspin, nkp, nkp_local
    1109             :       INTEGER, INTENT(IN), OPTIONAL                      :: nmixing
    1110             :       TYPE(section_vals_type), POINTER                   :: scf_section
    1111             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1112             : 
    1113             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_diis_b_step_kp'
    1114             :       REAL(KIND=dp), PARAMETER :: eigenvalue_threshold = 1.0E-12_dp
    1115             : 
    1116             :       CHARACTER(LEN=2*default_string_length)             :: message
    1117             :       COMPLEX(KIND=dp)                                   :: tmp
    1118        3946 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :)     :: a, b
    1119             :       INTEGER                                            :: handle, ikp, ispin, jb, my_nmixing, nb1, &
    1120             :                                                             output_unit
    1121             :       LOGICAL                                            :: eigenvectors_discarded
    1122        3946 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: ev
    1123             :       TYPE(cp_cfm_type)                                  :: old_errors
    1124             :       TYPE(cp_cfm_type), POINTER                         :: new_errors
    1125             :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    1126             :       TYPE(cp_fm_type)                                   :: ierr, rerr
    1127             :       TYPE(cp_logger_type), POINTER                      :: logger
    1128             : 
    1129        3946 :       NULLIFY (matrix_struct, new_errors, logger)
    1130             : 
    1131        3946 :       CALL timeset(routineN, handle)
    1132             : 
    1133        3946 :       diis_step = .FALSE.
    1134             : 
    1135        3946 :       my_nmixing = 2
    1136        3946 :       IF (PRESENT(nmixing)) my_nmixing = nmixing
    1137             : 
    1138        3946 :       logger => cp_get_default_logger()
    1139             : 
    1140             :       ! Quick return, if no DIIS is requested
    1141        3946 :       IF (diis_buffer%nbuffer < 1) THEN
    1142           0 :          CALL timestop(handle)
    1143           0 :          RETURN
    1144             :       END IF
    1145             : 
    1146             :       ! Check, if a DIIS step is appropriate
    1147        3946 :       diis_step = ((diis_buffer%ncall >= my_nmixing) .AND. (delta < eps_diis))
    1148             : 
    1149             :       ! Calculate the DIIS buffer, and update it if max_error < eps_diis
    1150        3946 :       CALL cp_cfm_get_info(diis_buffer%error(ib, 1, 1), matrix_struct=matrix_struct)
    1151        3946 :       CALL cp_fm_create(ierr, matrix_struct)
    1152        3946 :       CALL cp_fm_create(rerr, matrix_struct)
    1153        3946 :       CALL cp_cfm_create(old_errors, matrix_struct)
    1154       15784 :       ALLOCATE (b(nb, nb))
    1155       60570 :       b = 0.0_dp
    1156       16372 :       DO jb = 1, nb
    1157       36522 :          DO ikp = 1, nkp_local
    1158       63810 :             DO ispin = 1, nspin
    1159       27288 :                new_errors => diis_buffer%error(ib, ispin, ikp)
    1160       27288 :                CALL cp_cfm_to_fm(diis_buffer%error(jb, ispin, ikp), rerr, ierr)
    1161       27288 :                CALL cp_fm_scale(-1.0_dp, ierr)
    1162       27288 :                CALL cp_fm_to_cfm(rerr, ierr, old_errors)
    1163       27288 :                CALL cp_cfm_trace(old_errors, new_errors, tmp)
    1164       51384 :                b(jb, ib) = b(jb, ib) + 1.0_dp/REAL(nkp, dp)*tmp
    1165             :             END DO
    1166             :          END DO
    1167       16372 :          b(ib, jb) = CONJG(b(jb, ib))
    1168             :       END DO
    1169        3946 :       CALL cp_fm_release(ierr)
    1170        3946 :       CALL cp_fm_release(rerr)
    1171        3946 :       CALL cp_cfm_release(old_errors)
    1172        3946 :       CALL para_env%sum(b)
    1173             : 
    1174        3946 :       error_max = SQRT(REAL(b(ib, ib))**2 + AIMAG(b(ib, ib))**2)
    1175             : 
    1176             :       output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DIIS_INFO", &
    1177        3946 :                                          extension=".scfLog")
    1178        3946 :       IF (output_unit > 0) THEN
    1179             :          WRITE (UNIT=output_unit, FMT="(/,T9,A,I4,/,(T9,A,ES12.3))") &
    1180           0 :             "DIIS | Current SCF DIIS buffer size:         ", nb, &
    1181           0 :             "DIIS | Maximum SCF DIIS error at last step:  ", error_max, &
    1182           0 :             "DIIS | Current SCF convergence:              ", delta, &
    1183           0 :             "DIIS | Threshold value for a DIIS step:      ", eps_diis
    1184           0 :          IF (error_max < eps_diis) THEN
    1185             :             WRITE (UNIT=output_unit, FMT="(T9,A)") &
    1186           0 :                "DIIS | => The SCF DIIS buffer will be updated"
    1187             :          ELSE
    1188             :             WRITE (UNIT=output_unit, FMT="(T9,A)") &
    1189           0 :                "DIIS | => No update of the SCF DIIS buffer"
    1190             :          END IF
    1191           0 :          IF (diis_step .AND. (error_max < eps_diis)) THEN
    1192             :             WRITE (UNIT=output_unit, FMT="(T9,A,/)") &
    1193           0 :                "DIIS | => A SCF DIIS step will be performed"
    1194             :          ELSE
    1195             :             WRITE (UNIT=output_unit, FMT="(T9,A,/)") &
    1196           0 :                "DIIS | => No SCF DIIS step will be performed"
    1197             :          END IF
    1198             :       END IF
    1199             : 
    1200             :       ! Update the SCF DIIS buffer
    1201        3946 :       IF (error_max < eps_diis) THEN
    1202       16102 :          DO jb = 1, nb
    1203       12280 :             diis_buffer%b_matrix(ib, jb) = b(ib, jb)
    1204       16102 :             diis_buffer%b_matrix(jb, ib) = b(jb, ib)
    1205             :          END DO
    1206             :       ELSE
    1207             : 
    1208         124 :          diis_step = .FALSE.
    1209             :       END IF
    1210        3946 :       DEALLOCATE (b)
    1211             : 
    1212             :       ! Perform DIIS step
    1213        3946 :       IF (diis_step) THEN
    1214             : 
    1215        2422 :          nb1 = nb + 1
    1216             : 
    1217        9688 :          ALLOCATE (a(nb1, nb1))
    1218        7266 :          ALLOCATE (b(nb1, nb1))
    1219        7266 :          ALLOCATE (ev(nb1))
    1220             : 
    1221             :          ! Set up the linear DIIS equation system
    1222       44686 :          b(1:nb, 1:nb) = diis_buffer%b_matrix(1:nb, 1:nb)
    1223             : 
    1224       11268 :          b(1:nb, nb1) = -1.0_dp
    1225       11268 :          b(nb1, 1:nb) = -1.0_dp
    1226        2422 :          b(nb1, nb1) = 0.0_dp
    1227             : 
    1228             :          ! Solve the linear DIIS equation system
    1229       13690 :          ev(1:nb1) = 0.0_dp !eigenvalues
    1230       67222 :          a(1:nb1, 1:nb1) = 0.0_dp !eigenvectors
    1231        2422 :          CALL diag_complex(b(1:nb1, 1:nb1), a(1:nb1, 1:nb1), ev(1:nb1))
    1232       67222 :          b(1:nb1, 1:nb1) = a(1:nb1, 1:nb1)
    1233             : 
    1234        2422 :          eigenvectors_discarded = .FALSE.
    1235             : 
    1236       13690 :          DO jb = 1, nb1
    1237       13690 :             IF (ABS(ev(jb)) < eigenvalue_threshold) THEN
    1238        1542 :                IF (output_unit > 0) THEN
    1239           0 :                   IF (.NOT. eigenvectors_discarded) THEN
    1240             :                      WRITE (UNIT=output_unit, FMT="(T9,A)") &
    1241           0 :                         "DIIS | Checking eigenvalues of the DIIS error matrix"
    1242             :                   END IF
    1243             :                   WRITE (UNIT=message, FMT="(T9,A,I6,A,ES10.1,A,ES10.1)") &
    1244           0 :                      "DIIS | Eigenvalue ", jb, " = ", ev(jb), " is smaller than "// &
    1245           0 :                      "threshold ", eigenvalue_threshold
    1246           0 :                   CALL compress(message)
    1247           0 :                   WRITE (UNIT=output_unit, FMT="(T9,A)") TRIM(message)
    1248           0 :                   eigenvectors_discarded = .TRUE.
    1249             :                END IF
    1250        9066 :                a(1:nb1, jb) = 0.0_dp
    1251             :             ELSE
    1252       55734 :                a(1:nb1, jb) = a(1:nb1, jb)/ev(jb)
    1253             :             END IF
    1254             :          END DO
    1255             : 
    1256        2422 :          IF ((output_unit > 0) .AND. eigenvectors_discarded) THEN
    1257             :             WRITE (UNIT=output_unit, FMT="(T9,A,/)") &
    1258           0 :                "DIIS | The corresponding eigenvectors were discarded"
    1259             :          END IF
    1260             : 
    1261       78490 :          coeffs(1:nb) = -MATMUL(a(1:nb, 1:nb1), CONJG(b(nb1, 1:nb1)))
    1262             :       ELSE
    1263             : 
    1264        5104 :          coeffs(:) = 0.0_dp
    1265        1524 :          coeffs(ib) = 1.0_dp
    1266             :       END IF
    1267             : 
    1268             :       CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
    1269        3946 :                                         "PRINT%DIIS_INFO")
    1270             : 
    1271        3946 :       CALL timestop(handle)
    1272             : 
    1273       11838 :    END SUBROUTINE qs_diis_b_step_kp
    1274        2422 : END MODULE qs_diis

Generated by: LCOV version 1.15