LCOV - code coverage report
Current view: top level - src - qs_scf_block_davidson.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:42dac4a) Lines: 96.5 % 514 496
Test Date: 2025-07-25 12:55:17 Functions: 100.0 % 3 3

            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 module that contains the algorithms to perform an itrative
      10              : !>         diagonalization by the block-Davidson approach
      11              : !>         P. Blaha, et al J. Comp. Physics, 229, (2010), 453-460
      12              : !>         Iterative diagonalization in augmented plane wave based
      13              : !>         methods in electronic structure calculations
      14              : !> \par History
      15              : !>      05.2011 created [MI]
      16              : !> \author MI
      17              : ! **************************************************************************************************
      18              : MODULE qs_scf_block_davidson
      19              : 
      20              :    USE cp_dbcsr_api,                    ONLY: &
      21              :         dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_get_info, dbcsr_init_p, &
      22              :         dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_start, &
      23              :         dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_multiply, dbcsr_release_p, dbcsr_type, &
      24              :         dbcsr_type_no_symmetry, dbcsr_type_symmetric
      25              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_get_diag,&
      26              :                                               dbcsr_scale_by_vector
      27              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      28              :                                               copy_fm_to_dbcsr,&
      29              :                                               cp_dbcsr_m_by_n_from_row_template,&
      30              :                                               cp_dbcsr_m_by_n_from_template,&
      31              :                                               cp_dbcsr_sm_fm_multiply
      32              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      33              :                                               cp_fm_scale_and_add,&
      34              :                                               cp_fm_symm,&
      35              :                                               cp_fm_transpose,&
      36              :                                               cp_fm_triangular_invert,&
      37              :                                               cp_fm_uplo_to_full
      38              :    USE cp_fm_cholesky,                  ONLY: cp_fm_cholesky_decompose,&
      39              :                                               cp_fm_cholesky_restore
      40              :    USE cp_fm_diag,                      ONLY: choose_eigv_solver,&
      41              :                                               cp_fm_power
      42              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      43              :                                               cp_fm_struct_release,&
      44              :                                               cp_fm_struct_type
      45              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      46              :                                               cp_fm_get_diag,&
      47              :                                               cp_fm_release,&
      48              :                                               cp_fm_set_all,&
      49              :                                               cp_fm_to_fm,&
      50              :                                               cp_fm_to_fm_submat,&
      51              :                                               cp_fm_type,&
      52              :                                               cp_fm_vectorsnorm
      53              :    USE kinds,                           ONLY: dp
      54              :    USE machine,                         ONLY: m_walltime
      55              :    USE message_passing,                 ONLY: mp_comm_type
      56              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      57              :    USE preconditioner,                  ONLY: apply_preconditioner
      58              :    USE preconditioner_types,            ONLY: preconditioner_type
      59              :    USE qs_block_davidson_types,         ONLY: davidson_type
      60              :    USE qs_mo_types,                     ONLY: get_mo_set,&
      61              :                                               mo_set_type
      62              : #include "./base/base_uses.f90"
      63              : 
      64              :    IMPLICIT NONE
      65              :    PRIVATE
      66              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_block_davidson'
      67              : 
      68              :    PUBLIC :: generate_extended_space, generate_extended_space_sparse
      69              : 
      70              : CONTAINS
      71              : 
      72              : ! **************************************************************************************************
      73              : !> \brief ...
      74              : !> \param bdav_env ...
      75              : !> \param mo_set ...
      76              : !> \param matrix_h ...
      77              : !> \param matrix_s ...
      78              : !> \param output_unit ...
      79              : !> \param preconditioner ...
      80              : ! **************************************************************************************************
      81           30 :    SUBROUTINE generate_extended_space(bdav_env, mo_set, matrix_h, matrix_s, output_unit, &
      82              :                                       preconditioner)
      83              : 
      84              :       TYPE(davidson_type)                                :: bdav_env
      85              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
      86              :       TYPE(dbcsr_type), POINTER                          :: matrix_h, matrix_s
      87              :       INTEGER, INTENT(IN)                                :: output_unit
      88              :       TYPE(preconditioner_type), OPTIONAL, POINTER       :: preconditioner
      89              : 
      90              :       CHARACTER(len=*), PARAMETER :: routineN = 'generate_extended_space'
      91              : 
      92              :       INTEGER :: handle, homo, i_first, i_last, imo, iter, j, jj, max_iter, n, nao, nmat, nmat2, &
      93              :          nmo, nmo_converged, nmo_not_converged, nset, nset_conv, nset_not_conv
      94           30 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iconv, inotconv
      95           30 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: iconv_set, inotconv_set
      96              :       LOGICAL                                            :: converged, do_apply_preconditioner
      97              :       REAL(dp)                                           :: lambda, max_norm, min_norm, t1, t2
      98           30 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: ritz_coeff, vnorm
      99           30 :       REAL(dp), DIMENSION(:), POINTER                    :: eig_not_conv, eigenvalues, evals
     100              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
     101              :       TYPE(cp_fm_type)                                   :: c_conv, c_notconv, c_out, h_block, h_fm, &
     102              :                                                             m_hc, m_sc, m_tmp, mt_tmp, s_block, &
     103              :                                                             s_fm, v_block, w_block
     104              :       TYPE(cp_fm_type), POINTER                          :: c_pz, c_z, mo_coeff
     105              :       TYPE(dbcsr_type), POINTER                          :: mo_coeff_b
     106              : 
     107           30 :       CALL timeset(routineN, handle)
     108              : 
     109           30 :       NULLIFY (mo_coeff, mo_coeff_b, eigenvalues)
     110              : 
     111           30 :       do_apply_preconditioner = .FALSE.
     112           30 :       IF (PRESENT(preconditioner)) do_apply_preconditioner = .TRUE.
     113              :       CALL get_mo_set(mo_set=mo_set, mo_coeff=mo_coeff, mo_coeff_b=mo_coeff_b, eigenvalues=eigenvalues, &
     114           30 :                       nao=nao, nmo=nmo, homo=homo)
     115           30 :       IF (do_apply_preconditioner) THEN
     116           28 :          max_iter = bdav_env%max_iter
     117              :       ELSE
     118              :          max_iter = 1
     119              :       END IF
     120              : 
     121           30 :       NULLIFY (c_z, c_pz)
     122           30 :       NULLIFY (evals, eig_not_conv)
     123           30 :       t1 = m_walltime()
     124           30 :       IF (output_unit > 0) THEN
     125              :          WRITE (output_unit, "(T15,A,T23,A,T36,A,T49,A,T60,A,/,T8,A)") &
     126            0 :             " Cycle ", " conv. MOS ", " B2MAX ", " B2MIN ", " Time", REPEAT("-", 60)
     127              :       END IF
     128              : 
     129           90 :       ALLOCATE (iconv(nmo))
     130           60 :       ALLOCATE (inotconv(nmo))
     131           90 :       ALLOCATE (ritz_coeff(nmo))
     132           60 :       ALLOCATE (vnorm(nmo))
     133              : 
     134           30 :       converged = .FALSE.
     135           82 :       DO iter = 1, max_iter
     136              : 
     137              :          ! compute Ritz values
     138         1998 :          ritz_coeff = 0.0_dp
     139           54 :          CALL cp_fm_create(m_hc, mo_coeff%matrix_struct, name="hc")
     140           54 :          CALL cp_dbcsr_sm_fm_multiply(matrix_h, mo_coeff, m_hc, nmo)
     141           54 :          CALL cp_fm_create(m_sc, mo_coeff%matrix_struct, name="sc")
     142           54 :          CALL cp_dbcsr_sm_fm_multiply(matrix_s, mo_coeff, m_sc, nmo)
     143              : 
     144              :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nmo, ncol_global=nmo, &
     145              :                                   context=mo_coeff%matrix_struct%context, &
     146           54 :                                   para_env=mo_coeff%matrix_struct%para_env)
     147           54 :          CALL cp_fm_create(m_tmp, fm_struct_tmp, name="matrix_tmp")
     148           54 :          CALL cp_fm_struct_release(fm_struct_tmp)
     149              : 
     150           54 :          CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, mo_coeff, m_hc, 0.0_dp, m_tmp)
     151           54 :          CALL cp_fm_get_diag(m_tmp, ritz_coeff)
     152           54 :          CALL cp_fm_release(m_tmp)
     153              : 
     154              :          ! Check for converged eigenvectors
     155           54 :          c_z => bdav_env%matrix_z
     156           54 :          c_pz => bdav_env%matrix_pz
     157           54 :          CALL cp_fm_to_fm(m_sc, c_z)
     158           54 :          CALL cp_fm_column_scale(c_z, ritz_coeff)
     159           54 :          CALL cp_fm_scale_and_add(-1.0_dp, c_z, 1.0_dp, m_hc)
     160           54 :          CALL cp_fm_vectorsnorm(c_z, vnorm)
     161              : 
     162           54 :          nmo_converged = 0
     163           54 :          nmo_not_converged = 0
     164           54 :          max_norm = 0.0_dp
     165           54 :          min_norm = 1.e10_dp
     166         1998 :          DO imo = 1, nmo
     167         1944 :             max_norm = MAX(max_norm, vnorm(imo))
     168         1998 :             min_norm = MIN(min_norm, vnorm(imo))
     169              :          END DO
     170         1998 :          iconv = 0
     171         1998 :          inotconv = 0
     172         1998 :          DO imo = 1, nmo
     173         1998 :             IF (vnorm(imo) <= bdav_env%eps_iter) THEN
     174           76 :                nmo_converged = nmo_converged + 1
     175           76 :                iconv(nmo_converged) = imo
     176              :             ELSE
     177         1868 :                nmo_not_converged = nmo_not_converged + 1
     178         1868 :                inotconv(nmo_not_converged) = imo
     179              :             END IF
     180              :          END DO
     181              : 
     182           54 :          IF (nmo_converged > 0) THEN
     183           24 :             ALLOCATE (iconv_set(nmo_converged, 2))
     184           24 :             ALLOCATE (inotconv_set(nmo_not_converged, 2))
     185            8 :             i_last = iconv(1)
     186            8 :             nset = 0
     187           84 :             DO j = 1, nmo_converged
     188           76 :                imo = iconv(j)
     189              : 
     190           84 :                IF (imo == i_last + 1) THEN
     191           60 :                   i_last = imo
     192           60 :                   iconv_set(nset, 2) = imo
     193              :                ELSE
     194           16 :                   i_last = imo
     195           16 :                   nset = nset + 1
     196           16 :                   iconv_set(nset, 1) = imo
     197           16 :                   iconv_set(nset, 2) = imo
     198              :                END IF
     199              :             END DO
     200            8 :             nset_conv = nset
     201              : 
     202            8 :             i_last = inotconv(1)
     203            8 :             nset = 0
     204          220 :             DO j = 1, nmo_not_converged
     205          212 :                imo = inotconv(j)
     206              : 
     207          220 :                IF (imo == i_last + 1) THEN
     208          192 :                   i_last = imo
     209          192 :                   inotconv_set(nset, 2) = imo
     210              :                ELSE
     211           20 :                   i_last = imo
     212           20 :                   nset = nset + 1
     213           20 :                   inotconv_set(nset, 1) = imo
     214           20 :                   inotconv_set(nset, 2) = imo
     215              :                END IF
     216              :             END DO
     217            8 :             nset_not_conv = nset
     218            8 :             CALL cp_fm_release(m_sc)
     219            8 :             CALL cp_fm_release(m_hc)
     220            8 :             NULLIFY (c_z, c_pz)
     221              :          END IF
     222              : 
     223           54 :          IF (REAL(nmo_converged, dp)/REAL(nmo, dp) > bdav_env%conv_percent) THEN
     224            2 :             converged = .TRUE.
     225            2 :             DEALLOCATE (iconv_set)
     226            2 :             DEALLOCATE (inotconv_set)
     227            2 :             t2 = m_walltime()
     228            2 :             IF (output_unit > 0) THEN
     229              :                WRITE (output_unit, '(T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
     230            0 :                   iter, nmo_converged, max_norm, min_norm, t2 - t1
     231              : 
     232            0 :                WRITE (output_unit, *) " Reached convergence in ", iter, &
     233            0 :                   " Davidson iterations"
     234              :             END IF
     235              : 
     236              :             EXIT
     237              :          END IF
     238              : 
     239           52 :          IF (nmo_converged > 0) THEN
     240              :             CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nao, ncol_global=nao, &
     241              :                                      context=mo_coeff%matrix_struct%context, &
     242            6 :                                      para_env=mo_coeff%matrix_struct%para_env)
     243              :             !allocate h_fm
     244            6 :             CALL cp_fm_create(h_fm, fm_struct_tmp, name="matrix_tmp")
     245              :             !allocate s_fm
     246            6 :             CALL cp_fm_create(s_fm, fm_struct_tmp, name="matrix_tmp")
     247              :             !copy matrix_h in h_fm
     248            6 :             CALL copy_dbcsr_to_fm(matrix_h, h_fm)
     249            6 :             CALL cp_fm_uplo_to_full(h_fm, s_fm)
     250              : 
     251              :             !copy matrix_s in s_fm
     252              : !        CALL cp_fm_set_all(s_fm,0.0_dp)
     253            6 :             CALL copy_dbcsr_to_fm(matrix_s, s_fm)
     254              : 
     255              :             !allocate c_out
     256            6 :             CALL cp_fm_create(c_out, fm_struct_tmp, name="matrix_tmp")
     257              :             ! set c_out to zero
     258            6 :             CALL cp_fm_set_all(c_out, 0.0_dp)
     259            6 :             CALL cp_fm_struct_release(fm_struct_tmp)
     260              : 
     261              :             !allocate c_conv
     262              :             CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nao, ncol_global=nmo_converged, &
     263              :                                      context=mo_coeff%matrix_struct%context, &
     264            6 :                                      para_env=mo_coeff%matrix_struct%para_env)
     265            6 :             CALL cp_fm_create(c_conv, fm_struct_tmp, name="c_conv")
     266            6 :             CALL cp_fm_set_all(c_conv, 0.0_dp)
     267              :             !allocate m_tmp
     268            6 :             CALL cp_fm_create(m_tmp, fm_struct_tmp, name="m_tmp_nxmc")
     269            6 :             CALL cp_fm_struct_release(fm_struct_tmp)
     270              :          END IF
     271              : 
     272              :          !allocate c_notconv
     273              :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nao, ncol_global=nmo_not_converged, &
     274              :                                   context=mo_coeff%matrix_struct%context, &
     275           52 :                                   para_env=mo_coeff%matrix_struct%para_env)
     276           52 :          CALL cp_fm_create(c_notconv, fm_struct_tmp, name="c_notconv")
     277           52 :          CALL cp_fm_set_all(c_notconv, 0.0_dp)
     278           52 :          IF (nmo_converged > 0) THEN
     279            6 :             CALL cp_fm_create(m_hc, fm_struct_tmp, name="m_hc")
     280            6 :             CALL cp_fm_create(m_sc, fm_struct_tmp, name="m_sc")
     281              :             !allocate c_z
     282            6 :             ALLOCATE (c_z, c_pz)
     283            6 :             CALL cp_fm_create(c_z, fm_struct_tmp, name="c_z")
     284            6 :             CALL cp_fm_create(c_pz, fm_struct_tmp, name="c_pz")
     285            6 :             CALL cp_fm_set_all(c_z, 0.0_dp)
     286              : 
     287              :             ! sum contributions to c_out
     288            6 :             jj = 1
     289           16 :             DO j = 1, nset_conv
     290           10 :                i_first = iconv_set(j, 1)
     291           10 :                i_last = iconv_set(j, 2)
     292           10 :                n = i_last - i_first + 1
     293           10 :                CALL cp_fm_to_fm_submat(mo_coeff, c_conv, nao, n, 1, i_first, 1, jj)
     294           16 :                jj = jj + n
     295              :             END DO
     296            6 :             CALL cp_fm_symm('L', 'U', nao, nmo_converged, 1.0_dp, s_fm, c_conv, 0.0_dp, m_tmp)
     297            6 :             CALL parallel_gemm('N', 'T', nao, nao, nmo_converged, 1.0_dp, m_tmp, m_tmp, 0.0_dp, c_out)
     298              : 
     299              :             ! project c_out out of H
     300            6 :             lambda = 100.0_dp*ABS(eigenvalues(homo))
     301            6 :             CALL cp_fm_scale_and_add(lambda, c_out, 1.0_dp, h_fm)
     302            6 :             CALL cp_fm_release(m_tmp)
     303            6 :             CALL cp_fm_release(h_fm)
     304              : 
     305              :          END IF
     306              : 
     307              :          !allocate m_tmp
     308           52 :          CALL cp_fm_create(m_tmp, fm_struct_tmp, name="m_tmp_nxm")
     309           52 :          CALL cp_fm_struct_release(fm_struct_tmp)
     310           52 :          IF (nmo_converged > 0) THEN
     311           18 :             ALLOCATE (eig_not_conv(nmo_not_converged))
     312            6 :             jj = 1
     313           20 :             DO j = 1, nset_not_conv
     314           14 :                i_first = inotconv_set(j, 1)
     315           14 :                i_last = inotconv_set(j, 2)
     316           14 :                n = i_last - i_first + 1
     317           14 :                CALL cp_fm_to_fm_submat(mo_coeff, c_notconv, nao, n, 1, i_first, 1, jj)
     318          194 :                eig_not_conv(jj:jj + n - 1) = ritz_coeff(i_first:i_last)
     319           20 :                jj = jj + n
     320              :             END DO
     321            6 :             CALL parallel_gemm('N', 'N', nao, nmo_not_converged, nao, 1.0_dp, c_out, c_notconv, 0.0_dp, m_hc)
     322            6 :             CALL cp_fm_symm('L', 'U', nao, nmo_not_converged, 1.0_dp, s_fm, c_notconv, 0.0_dp, m_sc)
     323              :             ! extend suspace using only the not converged vectors
     324            6 :             CALL cp_fm_to_fm(m_sc, m_tmp)
     325            6 :             CALL cp_fm_column_scale(m_tmp, eig_not_conv)
     326            6 :             CALL cp_fm_scale_and_add(-1.0_dp, m_tmp, 1.0_dp, m_hc)
     327            6 :             DEALLOCATE (eig_not_conv)
     328            6 :             CALL cp_fm_to_fm(m_tmp, c_z)
     329              :          ELSE
     330           46 :             CALL cp_fm_to_fm(mo_coeff, c_notconv)
     331              :          END IF
     332              : 
     333              :          !preconditioner
     334           52 :          IF (do_apply_preconditioner) THEN
     335           50 :             IF (preconditioner%in_use /= 0) THEN
     336           50 :                CALL apply_preconditioner(preconditioner, c_z, c_pz)
     337              :             ELSE
     338            0 :                CALL cp_fm_to_fm(c_z, c_pz)
     339              :             END IF
     340              :          ELSE
     341            2 :             CALL cp_fm_to_fm(c_z, c_pz)
     342              :          END IF
     343           52 :          CALL cp_fm_release(m_tmp)
     344              : 
     345              :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nmo_not_converged, ncol_global=nmo_not_converged, &
     346              :                                   context=mo_coeff%matrix_struct%context, &
     347           52 :                                   para_env=mo_coeff%matrix_struct%para_env)
     348              : 
     349           52 :          CALL cp_fm_create(m_tmp, fm_struct_tmp, name="m_tmp_mxm")
     350           52 :          CALL cp_fm_create(mt_tmp, fm_struct_tmp, name="mt_tmp_mxm")
     351           52 :          CALL cp_fm_struct_release(fm_struct_tmp)
     352              : 
     353           52 :          nmat = nmo_not_converged
     354           52 :          nmat2 = 2*nmo_not_converged
     355              :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nmat2, ncol_global=nmat2, &
     356              :                                   context=mo_coeff%matrix_struct%context, &
     357           52 :                                   para_env=mo_coeff%matrix_struct%para_env)
     358              : 
     359           52 :          CALL cp_fm_create(s_block, fm_struct_tmp, name="sb")
     360           52 :          CALL cp_fm_create(h_block, fm_struct_tmp, name="hb")
     361           52 :          CALL cp_fm_create(v_block, fm_struct_tmp, name="vb")
     362           52 :          CALL cp_fm_create(w_block, fm_struct_tmp, name="wb")
     363          156 :          ALLOCATE (evals(nmat2))
     364              : 
     365           52 :          CALL cp_fm_struct_release(fm_struct_tmp)
     366              : 
     367              :          ! compute CSC
     368           52 :          CALL cp_fm_set_all(s_block, 0.0_dp, 1.0_dp)
     369              : 
     370              :          ! compute CHC
     371           52 :          CALL parallel_gemm('T', 'N', nmat, nmat, nao, 1.0_dp, c_notconv, m_hc, 0.0_dp, m_tmp)
     372           52 :          CALL cp_fm_to_fm_submat(m_tmp, h_block, nmat, nmat, 1, 1, 1, 1)
     373              : 
     374              :          ! compute ZSC
     375           52 :          CALL parallel_gemm('T', 'N', nmat, nmat, nao, 1.0_dp, c_pz, m_sc, 0.0_dp, m_tmp)
     376           52 :          CALL cp_fm_to_fm_submat(m_tmp, s_block, nmat, nmat, 1, 1, 1 + nmat, 1)
     377           52 :          CALL cp_fm_transpose(m_tmp, mt_tmp)
     378           52 :          CALL cp_fm_to_fm_submat(mt_tmp, s_block, nmat, nmat, 1, 1, 1, 1 + nmat)
     379              :          ! compute ZHC
     380           52 :          CALL parallel_gemm('T', 'N', nmat, nmat, nao, 1.0_dp, c_pz, m_hc, 0.0_dp, m_tmp)
     381           52 :          CALL cp_fm_to_fm_submat(m_tmp, h_block, nmat, nmat, 1, 1, 1 + nmat, 1)
     382           52 :          CALL cp_fm_transpose(m_tmp, mt_tmp)
     383           52 :          CALL cp_fm_to_fm_submat(mt_tmp, h_block, nmat, nmat, 1, 1, 1, 1 + nmat)
     384              : 
     385           52 :          CALL cp_fm_release(mt_tmp)
     386              : 
     387              :          ! reuse m_sc and m_hc to computr HZ and SZ
     388           52 :          IF (nmo_converged > 0) THEN
     389            6 :             CALL parallel_gemm('N', 'N', nao, nmat, nao, 1.0_dp, c_out, c_pz, 0.0_dp, m_hc)
     390            6 :             CALL cp_fm_symm('L', 'U', nao, nmo_not_converged, 1.0_dp, s_fm, c_pz, 0.0_dp, m_sc)
     391              : 
     392            6 :             CALL cp_fm_release(c_out)
     393            6 :             CALL cp_fm_release(c_conv)
     394            6 :             CALL cp_fm_release(s_fm)
     395              :          ELSE
     396           46 :             CALL cp_dbcsr_sm_fm_multiply(matrix_h, c_pz, m_hc, nmo)
     397           46 :             CALL cp_dbcsr_sm_fm_multiply(matrix_s, c_pz, m_sc, nmo)
     398              :          END IF
     399              : 
     400              :          ! compute ZSZ
     401           52 :          CALL parallel_gemm('T', 'N', nmat, nmat, nao, 1.0_dp, c_pz, m_sc, 0.0_dp, m_tmp)
     402           52 :          CALL cp_fm_to_fm_submat(m_tmp, s_block, nmat, nmat, 1, 1, 1 + nmat, 1 + nmat)
     403              :          ! compute ZHZ
     404           52 :          CALL parallel_gemm('T', 'N', nmat, nmat, nao, 1.0_dp, c_pz, m_hc, 0.0_dp, m_tmp)
     405           52 :          CALL cp_fm_to_fm_submat(m_tmp, h_block, nmat, nmat, 1, 1, 1 + nmat, 1 + nmat)
     406              : 
     407           52 :          CALL cp_fm_release(m_sc)
     408              : 
     409              :          ! solution of the reduced eigenvalues problem
     410           52 :          CALL reduce_extended_space(s_block, h_block, v_block, w_block, evals, nmat2)
     411              : 
     412              :          ! extract egenvectors
     413           52 :          CALL cp_fm_to_fm_submat(v_block, m_tmp, nmat, nmat, 1, 1, 1, 1)
     414           52 :          CALL parallel_gemm('N', 'N', nao, nmat, nmat, 1.0_dp, c_notconv, m_tmp, 0.0_dp, m_hc)
     415           52 :          CALL cp_fm_to_fm_submat(v_block, m_tmp, nmat, nmat, 1 + nmat, 1, 1, 1)
     416           52 :          CALL parallel_gemm('N', 'N', nao, nmat, nmat, 1.0_dp, c_pz, m_tmp, 1.0_dp, m_hc)
     417              : 
     418           52 :          CALL cp_fm_release(m_tmp)
     419              : 
     420           52 :          CALL cp_fm_release(c_notconv)
     421           52 :          CALL cp_fm_release(s_block)
     422           52 :          CALL cp_fm_release(h_block)
     423           52 :          CALL cp_fm_release(w_block)
     424           52 :          CALL cp_fm_release(v_block)
     425              : 
     426           52 :          IF (nmo_converged > 0) THEN
     427            6 :             CALL cp_fm_release(c_z)
     428            6 :             CALL cp_fm_release(c_pz)
     429            6 :             DEALLOCATE (c_z, c_pz)
     430            6 :             jj = 1
     431           20 :             DO j = 1, nset_not_conv
     432           14 :                i_first = inotconv_set(j, 1)
     433           14 :                i_last = inotconv_set(j, 2)
     434           14 :                n = i_last - i_first + 1
     435           14 :                CALL cp_fm_to_fm_submat(m_hc, mo_coeff, nao, n, 1, jj, 1, i_first)
     436          388 :                eigenvalues(i_first:i_last) = evals(jj:jj + n - 1)
     437           20 :                jj = jj + n
     438              :             END DO
     439            6 :             DEALLOCATE (iconv_set)
     440            6 :             DEALLOCATE (inotconv_set)
     441              :          ELSE
     442           46 :             CALL cp_fm_to_fm(m_hc, mo_coeff)
     443         3404 :             eigenvalues(1:nmo) = evals(1:nmo)
     444              :          END IF
     445           52 :          DEALLOCATE (evals)
     446              : 
     447           52 :          CALL cp_fm_release(m_hc)
     448              : 
     449           52 :          CALL copy_fm_to_dbcsr(mo_coeff, mo_coeff_b) !fm->dbcsr
     450              : 
     451           52 :          t2 = m_walltime()
     452           52 :          IF (output_unit > 0) THEN
     453              :             WRITE (output_unit, '(T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
     454            0 :                iter, nmo_converged, max_norm, min_norm, t2 - t1
     455              :          END IF
     456          450 :          t1 = m_walltime()
     457              : 
     458              :       END DO ! iter
     459              : 
     460           30 :       DEALLOCATE (iconv)
     461           30 :       DEALLOCATE (inotconv)
     462           30 :       DEALLOCATE (ritz_coeff)
     463           30 :       DEALLOCATE (vnorm)
     464              : 
     465           30 :       CALL timestop(handle)
     466           90 :    END SUBROUTINE generate_extended_space
     467              : 
     468              : ! **************************************************************************************************
     469              : !> \brief ...
     470              : !> \param bdav_env ...
     471              : !> \param mo_set ...
     472              : !> \param matrix_h ...
     473              : !> \param matrix_s ...
     474              : !> \param output_unit ...
     475              : !> \param preconditioner ...
     476              : ! **************************************************************************************************
     477           64 :    SUBROUTINE generate_extended_space_sparse(bdav_env, mo_set, matrix_h, matrix_s, output_unit, &
     478              :                                              preconditioner)
     479              : 
     480              :       TYPE(davidson_type)                                :: bdav_env
     481              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
     482              :       TYPE(dbcsr_type), POINTER                          :: matrix_h, matrix_s
     483              :       INTEGER, INTENT(IN)                                :: output_unit
     484              :       TYPE(preconditioner_type), OPTIONAL, POINTER       :: preconditioner
     485              : 
     486              :       CHARACTER(len=*), PARAMETER :: routineN = 'generate_extended_space_sparse'
     487              : 
     488              :       INTEGER :: col_offset, handle, homo, i_first, i_last, imo, iteration, j, jj, k, max_iter, n, &
     489              :          nao, nmat, nmat2, nmo, nmo_converged, nmo_not_converged, nset, nset_conv, nset_not_conv
     490           64 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iconv, inotconv
     491           64 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: iconv_set, inotconv_set
     492              :       LOGICAL                                            :: converged, do_apply_preconditioner
     493              :       REAL(dp)                                           :: lambda, max_norm, min_norm, t1, t2
     494           64 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: eig_not_conv, evals, ritz_coeff, vnorm
     495           64 :       REAL(dp), DIMENSION(:), POINTER                    :: eigenvalues
     496           64 :       REAL(dp), DIMENSION(:, :), POINTER                 :: block
     497              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
     498              :       TYPE(cp_fm_type)                                   :: h_block, matrix_mm_fm, matrix_mmt_fm, &
     499              :                                                             matrix_nm_fm, matrix_z_fm, mo_conv_fm, &
     500              :                                                             s_block, v_block, w_block
     501              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff, mo_notconv_fm
     502              :       TYPE(dbcsr_iterator_type)                          :: iter
     503              :       TYPE(dbcsr_type), POINTER                          :: c_out, matrix_hc, matrix_mm, matrix_pz, &
     504              :                                                             matrix_sc, matrix_z, mo_coeff_b, &
     505              :                                                             mo_conv, mo_notconv, smo_conv
     506              :       TYPE(mp_comm_type)                                 :: group
     507              : 
     508           64 :       CALL timeset(routineN, handle)
     509              : 
     510           64 :       do_apply_preconditioner = .FALSE.
     511           64 :       IF (PRESENT(preconditioner)) do_apply_preconditioner = .TRUE.
     512              : 
     513           64 :       NULLIFY (mo_coeff, mo_coeff_b, matrix_hc, matrix_sc, matrix_z, matrix_pz, matrix_mm)
     514           64 :       NULLIFY (mo_notconv_fm, mo_conv, mo_notconv, smo_conv, c_out)
     515           64 :       NULLIFY (fm_struct_tmp)
     516              :       CALL get_mo_set(mo_set=mo_set, mo_coeff=mo_coeff, mo_coeff_b=mo_coeff_b, &
     517           64 :                       eigenvalues=eigenvalues, homo=homo, nao=nao, nmo=nmo)
     518           64 :       IF (do_apply_preconditioner) THEN
     519           56 :          max_iter = bdav_env%max_iter
     520              :       ELSE
     521              :          max_iter = 1
     522              :       END IF
     523              : 
     524           64 :       t1 = m_walltime()
     525           64 :       IF (output_unit > 0) THEN
     526              :          WRITE (output_unit, "(T15,A,T23,A,T36,A,T49,A,T60,A,/,T8,A)") &
     527            0 :             " Cycle ", " conv. MOS ", " B2MAX ", " B2MIN ", " Time", REPEAT("-", 60)
     528              :       END IF
     529              : 
     530              :       ! Allocate array for Ritz values
     531          192 :       ALLOCATE (ritz_coeff(nmo))
     532          192 :       ALLOCATE (iconv(nmo))
     533          128 :       ALLOCATE (inotconv(nmo))
     534          128 :       ALLOCATE (vnorm(nmo))
     535              : 
     536           64 :       converged = .FALSE.
     537          128 :       DO iteration = 1, max_iter
     538           88 :          NULLIFY (c_out, mo_conv, mo_notconv_fm, mo_notconv)
     539              :          ! Prepare HC and SC, using mo_coeff_b (sparse), these are still sparse
     540           88 :          CALL dbcsr_init_p(matrix_hc)
     541              :          CALL dbcsr_create(matrix_hc, template=mo_coeff_b, &
     542              :                            name="matrix_hc", &
     543           88 :                            matrix_type=dbcsr_type_no_symmetry)
     544           88 :          CALL dbcsr_init_p(matrix_sc)
     545              :          CALL dbcsr_create(matrix_sc, template=mo_coeff_b, &
     546              :                            name="matrix_sc", &
     547           88 :                            matrix_type=dbcsr_type_no_symmetry)
     548              : 
     549           88 :          CALL dbcsr_get_info(mo_coeff_b, nfullrows_total=n, nfullcols_total=k, group=group)
     550           88 :          CALL dbcsr_multiply('n', 'n', 1.0_dp, matrix_h, mo_coeff_b, 0.0_dp, matrix_hc, last_column=k)
     551           88 :          CALL dbcsr_multiply('n', 'n', 1.0_dp, matrix_s, mo_coeff_b, 0.0_dp, matrix_sc, last_column=k)
     552              : 
     553              :          ! compute Ritz values
     554         3256 :          ritz_coeff = 0.0_dp
     555              :          ! Allocate Sparse matrices: nmoxnmo
     556              :          ! matrix_mm
     557              : 
     558           88 :          CALL dbcsr_init_p(matrix_mm)
     559              :          CALL cp_dbcsr_m_by_n_from_template(matrix_mm, template=matrix_s, m=nmo, n=nmo, &
     560           88 :                                             sym=dbcsr_type_no_symmetry)
     561              : 
     562           88 :          CALL dbcsr_multiply('t', 'n', 1.0_dp, mo_coeff_b, matrix_hc, 0.0_dp, matrix_mm, last_column=k)
     563           88 :          CALL dbcsr_get_diag(matrix_mm, ritz_coeff)
     564           88 :          CALL mo_coeff%matrix_struct%para_env%sum(ritz_coeff)
     565              : 
     566              :          ! extended subspace P Z = P [H - theta S]C  this ia another matrix of type and size as mo_coeff_b
     567           88 :          CALL dbcsr_init_p(matrix_z)
     568              :          CALL dbcsr_create(matrix_z, template=mo_coeff_b, &
     569              :                            name="matrix_z", &
     570           88 :                            matrix_type=dbcsr_type_no_symmetry)
     571           88 :          CALL dbcsr_copy(matrix_z, matrix_sc)
     572           88 :          CALL dbcsr_scale_by_vector(matrix_z, ritz_coeff, side='right')
     573           88 :          CALL dbcsr_add(matrix_z, matrix_hc, -1.0_dp, 1.0_dp)
     574              : 
     575              :          ! Compute the column norms of matrix_z.
     576         3256 :          vnorm = 0.0_dp
     577           88 :          CALL dbcsr_iterator_start(iter, matrix_z)
     578          792 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
     579          704 :             CALL dbcsr_iterator_next_block(iter, block=block, col_offset=col_offset)
     580        13464 :             DO j = 1, SIZE(block, 2)
     581       178112 :                vnorm(col_offset + j - 1) = vnorm(col_offset + j - 1) + SUM(block(:, j)**2)
     582              :             END DO
     583              :          END DO
     584           88 :          CALL dbcsr_iterator_stop(iter)
     585           88 :          CALL group%sum(vnorm)
     586         3256 :          vnorm = SQRT(vnorm)
     587              : 
     588              :          ! Check for converged eigenvectors
     589           88 :          nmo_converged = 0
     590           88 :          nmo_not_converged = 0
     591           88 :          max_norm = 0.0_dp
     592           88 :          min_norm = 1.e10_dp
     593         3256 :          DO imo = 1, nmo
     594         3168 :             max_norm = MAX(max_norm, vnorm(imo))
     595         3256 :             min_norm = MIN(min_norm, vnorm(imo))
     596              :          END DO
     597         3256 :          iconv = 0
     598         3256 :          inotconv = 0
     599              : 
     600         3256 :          DO imo = 1, nmo
     601         3256 :             IF (vnorm(imo) <= bdav_env%eps_iter) THEN
     602          836 :                nmo_converged = nmo_converged + 1
     603          836 :                iconv(nmo_converged) = imo
     604              :             ELSE
     605         2332 :                nmo_not_converged = nmo_not_converged + 1
     606         2332 :                inotconv(nmo_not_converged) = imo
     607              :             END IF
     608              :          END DO
     609              : 
     610           88 :          IF (nmo_converged > 0) THEN
     611           90 :             ALLOCATE (iconv_set(nmo_converged, 2))
     612           88 :             ALLOCATE (inotconv_set(nmo_not_converged, 2))
     613           30 :             i_last = iconv(1)
     614           30 :             nset = 0
     615          866 :             DO j = 1, nmo_converged
     616          836 :                imo = iconv(j)
     617              : 
     618          866 :                IF (imo == i_last + 1) THEN
     619          772 :                   i_last = imo
     620          772 :                   iconv_set(nset, 2) = imo
     621              :                ELSE
     622           64 :                   i_last = imo
     623           64 :                   nset = nset + 1
     624           64 :                   iconv_set(nset, 1) = imo
     625           64 :                   iconv_set(nset, 2) = imo
     626              :                END IF
     627              :             END DO
     628           30 :             nset_conv = nset
     629              : 
     630           30 :             i_last = inotconv(1)
     631           30 :             nset = 0
     632          274 :             DO j = 1, nmo_not_converged
     633          244 :                imo = inotconv(j)
     634              : 
     635          274 :                IF (imo == i_last + 1) THEN
     636          184 :                   i_last = imo
     637          184 :                   inotconv_set(nset, 2) = imo
     638              :                ELSE
     639           60 :                   i_last = imo
     640           60 :                   nset = nset + 1
     641           60 :                   inotconv_set(nset, 1) = imo
     642           60 :                   inotconv_set(nset, 2) = imo
     643              :                END IF
     644              :             END DO
     645           30 :             nset_not_conv = nset
     646              : 
     647           30 :             CALL dbcsr_release_p(matrix_hc)
     648           30 :             CALL dbcsr_release_p(matrix_sc)
     649           30 :             CALL dbcsr_release_p(matrix_z)
     650           30 :             CALL dbcsr_release_p(matrix_mm)
     651              :          END IF
     652              : 
     653           88 :          IF (REAL(nmo_converged, dp)/REAL(nmo, dp) > bdav_env%conv_percent) THEN
     654           24 :             DEALLOCATE (iconv_set)
     655              : 
     656           24 :             DEALLOCATE (inotconv_set)
     657              : 
     658           24 :             converged = .TRUE.
     659           24 :             t2 = m_walltime()
     660           24 :             IF (output_unit > 0) THEN
     661              :                WRITE (output_unit, '(T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
     662            0 :                   iteration, nmo_converged, max_norm, min_norm, t2 - t1
     663              : 
     664            0 :                WRITE (output_unit, *) " Reached convergence in ", iteration, &
     665            0 :                   " Davidson iterations"
     666              :             END IF
     667              : 
     668              :             EXIT
     669              :          END IF
     670              : 
     671           64 :          IF (nmo_converged > 0) THEN
     672              : 
     673              :             !allocate mo_conv_fm
     674              :             CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nao, ncol_global=nmo_converged, &
     675              :                                      context=mo_coeff%matrix_struct%context, &
     676            6 :                                      para_env=mo_coeff%matrix_struct%para_env)
     677            6 :             CALL cp_fm_create(mo_conv_fm, fm_struct_tmp, name="mo_conv_fm")
     678              : 
     679            6 :             CALL cp_fm_struct_release(fm_struct_tmp)
     680              : 
     681              :             ! extract mo_conv from mo_coeff full matrix
     682            6 :             jj = 1
     683           22 :             DO j = 1, nset_conv
     684           16 :                i_first = iconv_set(j, 1)
     685           16 :                i_last = iconv_set(j, 2)
     686           16 :                n = i_last - i_first + 1
     687           16 :                CALL cp_fm_to_fm_submat(mo_coeff, mo_conv_fm, nao, n, 1, i_first, 1, jj)
     688           22 :                jj = jj + n
     689              :             END DO
     690              : 
     691              :             ! allocate c_out sparse matrix, to project out the converged MOS
     692            6 :             CALL dbcsr_init_p(c_out)
     693              :             CALL dbcsr_create(c_out, template=matrix_s, &
     694              :                               name="c_out", &
     695            6 :                               matrix_type=dbcsr_type_symmetric)
     696              : 
     697              :             ! allocate mo_conv sparse
     698            6 :             CALL dbcsr_init_p(mo_conv)
     699              :             CALL cp_dbcsr_m_by_n_from_row_template(mo_conv, template=matrix_s, n=nmo_converged, &
     700            6 :                                                    sym=dbcsr_type_no_symmetry)
     701              : 
     702            6 :             CALL dbcsr_init_p(smo_conv)
     703              :             CALL cp_dbcsr_m_by_n_from_row_template(smo_conv, template=matrix_s, n=nmo_converged, &
     704            6 :                                                    sym=dbcsr_type_no_symmetry)
     705              : 
     706            6 :             CALL copy_fm_to_dbcsr(mo_conv_fm, mo_conv) !fm->dbcsr
     707              : 
     708            6 :             CALL dbcsr_multiply('n', 'n', 1.0_dp, matrix_s, mo_conv, 0.0_dp, smo_conv, last_column=nmo_converged)
     709            6 :             CALL dbcsr_multiply('n', 't', 1.0_dp, smo_conv, smo_conv, 0.0_dp, c_out, last_column=nao)
     710              :             ! project c_out out of H
     711            6 :             lambda = 100.0_dp*ABS(eigenvalues(homo))
     712            6 :             CALL dbcsr_add(c_out, matrix_h, lambda, 1.0_dp)
     713              : 
     714            6 :             CALL dbcsr_release_p(mo_conv)
     715            6 :             CALL dbcsr_release_p(smo_conv)
     716            6 :             CALL cp_fm_release(mo_conv_fm)
     717              : 
     718              :             !allocate c_notconv_fm
     719              :             CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nao, ncol_global=nmo_not_converged, &
     720              :                                      context=mo_coeff%matrix_struct%context, &
     721            6 :                                      para_env=mo_coeff%matrix_struct%para_env)
     722            6 :             ALLOCATE (mo_notconv_fm)
     723            6 :             CALL cp_fm_create(mo_notconv_fm, fm_struct_tmp, name="mo_notconv_fm")
     724            6 :             CALL cp_fm_struct_release(fm_struct_tmp)
     725              : 
     726              :             ! extract mo_notconv from mo_coeff full matrix
     727           18 :             ALLOCATE (eig_not_conv(nmo_not_converged))
     728              : 
     729            6 :             jj = 1
     730           24 :             DO j = 1, nset_not_conv
     731           18 :                i_first = inotconv_set(j, 1)
     732           18 :                i_last = inotconv_set(j, 2)
     733           18 :                n = i_last - i_first + 1
     734           18 :                CALL cp_fm_to_fm_submat(mo_coeff, mo_notconv_fm, nao, n, 1, i_first, 1, jj)
     735          186 :                eig_not_conv(jj:jj + n - 1) = ritz_coeff(i_first:i_last)
     736           24 :                jj = jj + n
     737              :             END DO
     738              : 
     739              :             ! allocate mo_conv sparse
     740            6 :             CALL dbcsr_init_p(mo_notconv)
     741              :             CALL cp_dbcsr_m_by_n_from_row_template(mo_notconv, template=matrix_s, n=nmo_not_converged, &
     742            6 :                                                    sym=dbcsr_type_no_symmetry)
     743              : 
     744            6 :             CALL dbcsr_init_p(matrix_hc)
     745              :             CALL cp_dbcsr_m_by_n_from_row_template(matrix_hc, template=matrix_s, n=nmo_not_converged, &
     746            6 :                                                    sym=dbcsr_type_no_symmetry)
     747              : 
     748            6 :             CALL dbcsr_init_p(matrix_sc)
     749              :             CALL cp_dbcsr_m_by_n_from_row_template(matrix_sc, template=matrix_s, n=nmo_not_converged, &
     750            6 :                                                    sym=dbcsr_type_no_symmetry)
     751              : 
     752            6 :             CALL dbcsr_init_p(matrix_z)
     753              :             CALL cp_dbcsr_m_by_n_from_row_template(matrix_z, template=matrix_s, n=nmo_not_converged, &
     754            6 :                                                    sym=dbcsr_type_no_symmetry)
     755              : 
     756            6 :             CALL copy_fm_to_dbcsr(mo_notconv_fm, mo_notconv) !fm->dbcsr
     757              : 
     758              :             CALL dbcsr_multiply('n', 'n', 1.0_dp, c_out, mo_notconv, 0.0_dp, matrix_hc, &
     759            6 :                                 last_column=nmo_not_converged)
     760              :             CALL dbcsr_multiply('n', 'n', 1.0_dp, matrix_s, mo_notconv, 0.0_dp, matrix_sc, &
     761            6 :                                 last_column=nmo_not_converged)
     762              : 
     763            6 :             CALL dbcsr_copy(matrix_z, matrix_sc)
     764            6 :             CALL dbcsr_scale_by_vector(matrix_z, eig_not_conv, side='right')
     765            6 :             CALL dbcsr_add(matrix_z, matrix_hc, -1.0_dp, 1.0_dp)
     766              : 
     767            6 :             DEALLOCATE (eig_not_conv)
     768              : 
     769              :             ! matrix_mm
     770            6 :             CALL dbcsr_init_p(matrix_mm)
     771              :             CALL cp_dbcsr_m_by_n_from_template(matrix_mm, template=matrix_s, m=nmo_not_converged, n=nmo_not_converged, &
     772            6 :                                                sym=dbcsr_type_no_symmetry)
     773              : 
     774              :             CALL dbcsr_multiply('t', 'n', 1.0_dp, mo_notconv, matrix_hc, 0.0_dp, matrix_mm, &
     775           18 :                                 last_column=nmo_not_converged)
     776              : 
     777              :          ELSE
     778           58 :             mo_notconv => mo_coeff_b
     779           58 :             mo_notconv_fm => mo_coeff
     780           58 :             c_out => matrix_h
     781              :          END IF
     782              : 
     783              :          ! allocate matrix_pz using as template matrix_z
     784           64 :          CALL dbcsr_init_p(matrix_pz)
     785              :          CALL dbcsr_create(matrix_pz, template=matrix_z, &
     786              :                            name="matrix_pz", &
     787           64 :                            matrix_type=dbcsr_type_no_symmetry)
     788              : 
     789           64 :          IF (do_apply_preconditioner) THEN
     790           56 :             IF (preconditioner%in_use /= 0) THEN
     791           56 :                CALL apply_preconditioner(preconditioner, matrix_z, matrix_pz)
     792              :             ELSE
     793            0 :                CALL dbcsr_copy(matrix_pz, matrix_z)
     794              :             END IF
     795              :          ELSE
     796            8 :             CALL dbcsr_copy(matrix_pz, matrix_z)
     797              :          END IF
     798              : 
     799              :          !allocate NMOxNMO  full matrices
     800           64 :          nmat = nmo_not_converged
     801              :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nmat, ncol_global=nmat, &
     802              :                                   context=mo_coeff%matrix_struct%context, &
     803           64 :                                   para_env=mo_coeff%matrix_struct%para_env)
     804           64 :          CALL cp_fm_create(matrix_mm_fm, fm_struct_tmp, name="m_tmp_mxm")
     805           64 :          CALL cp_fm_create(matrix_mmt_fm, fm_struct_tmp, name="mt_tmp_mxm")
     806           64 :          CALL cp_fm_struct_release(fm_struct_tmp)
     807              : 
     808              :          !allocate 2NMOx2NMO full matrices
     809           64 :          nmat2 = 2*nmo_not_converged
     810              :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nmat2, ncol_global=nmat2, &
     811              :                                   context=mo_coeff%matrix_struct%context, &
     812           64 :                                   para_env=mo_coeff%matrix_struct%para_env)
     813              : 
     814           64 :          CALL cp_fm_create(s_block, fm_struct_tmp, name="sb")
     815           64 :          CALL cp_fm_create(h_block, fm_struct_tmp, name="hb")
     816           64 :          CALL cp_fm_create(v_block, fm_struct_tmp, name="vb")
     817           64 :          CALL cp_fm_create(w_block, fm_struct_tmp, name="wb")
     818          192 :          ALLOCATE (evals(nmat2))
     819           64 :          CALL cp_fm_struct_release(fm_struct_tmp)
     820              : 
     821              :          ! compute CSC
     822           64 :          CALL cp_fm_set_all(s_block, 0.0_dp, 1.0_dp)
     823              :          ! compute CHC
     824           64 :          CALL copy_dbcsr_to_fm(matrix_mm, matrix_mm_fm)
     825           64 :          CALL cp_fm_to_fm_submat(matrix_mm_fm, h_block, nmat, nmat, 1, 1, 1, 1)
     826              : 
     827              :          ! compute the bottom left  ZSC (top right is transpose)
     828           64 :          CALL dbcsr_multiply('t', 'n', 1.0_dp, matrix_pz, matrix_sc, 0.0_dp, matrix_mm, last_column=nmat)
     829              :          !  set the bottom left part of S[C,Z] block matrix  ZSC
     830              :          !copy sparse to full
     831           64 :          CALL copy_dbcsr_to_fm(matrix_mm, matrix_mm_fm)
     832           64 :          CALL cp_fm_to_fm_submat(matrix_mm_fm, s_block, nmat, nmat, 1, 1, 1 + nmat, 1)
     833           64 :          CALL cp_fm_transpose(matrix_mm_fm, matrix_mmt_fm)
     834           64 :          CALL cp_fm_to_fm_submat(matrix_mmt_fm, s_block, nmat, nmat, 1, 1, 1, 1 + nmat)
     835              : 
     836              :          ! compute the bottom left  ZHC (top right is transpose)
     837           64 :          CALL dbcsr_multiply('t', 'n', 1.0_dp, matrix_pz, matrix_hc, 0.0_dp, matrix_mm, last_column=nmat)
     838              :          ! set the bottom left part of S[C,Z] block matrix  ZHC
     839           64 :          CALL copy_dbcsr_to_fm(matrix_mm, matrix_mm_fm)
     840           64 :          CALL cp_fm_to_fm_submat(matrix_mm_fm, h_block, nmat, nmat, 1, 1, 1 + nmat, 1)
     841           64 :          CALL cp_fm_transpose(matrix_mm_fm, matrix_mmt_fm)
     842           64 :          CALL cp_fm_to_fm_submat(matrix_mmt_fm, h_block, nmat, nmat, 1, 1, 1, 1 + nmat)
     843              : 
     844           64 :          CALL cp_fm_release(matrix_mmt_fm)
     845              : 
     846              :          ! (reuse matrix_sc and matrix_hc to computr HZ and SZ)
     847           64 :          CALL dbcsr_get_info(matrix_pz, nfullrows_total=n, nfullcols_total=k)
     848           64 :          CALL dbcsr_multiply('n', 'n', 1.0_dp, c_out, matrix_pz, 0.0_dp, matrix_hc, last_column=k)
     849           64 :          CALL dbcsr_multiply('n', 'n', 1.0_dp, matrix_s, matrix_pz, 0.0_dp, matrix_sc, last_column=k)
     850              : 
     851              :          ! compute the bottom right  ZSZ
     852           64 :          CALL dbcsr_multiply('t', 'n', 1.0_dp, matrix_pz, matrix_sc, 0.0_dp, matrix_mm, last_column=k)
     853              :          ! set the bottom right part of S[C,Z] block matrix  ZSZ
     854           64 :          CALL copy_dbcsr_to_fm(matrix_mm, matrix_mm_fm)
     855           64 :          CALL cp_fm_to_fm_submat(matrix_mm_fm, s_block, nmat, nmat, 1, 1, 1 + nmat, 1 + nmat)
     856              : 
     857              :          ! compute the bottom right  ZHZ
     858           64 :          CALL dbcsr_multiply('t', 'n', 1.0_dp, matrix_pz, matrix_hc, 0.0_dp, matrix_mm, last_column=k)
     859              :          ! set the bottom right part of H[C,Z] block matrix  ZHZ
     860           64 :          CALL copy_dbcsr_to_fm(matrix_mm, matrix_mm_fm)
     861           64 :          CALL cp_fm_to_fm_submat(matrix_mm_fm, h_block, nmat, nmat, 1, 1, 1 + nmat, 1 + nmat)
     862              : 
     863           64 :          CALL dbcsr_release_p(matrix_mm)
     864           64 :          CALL dbcsr_release_p(matrix_sc)
     865           64 :          CALL dbcsr_release_p(matrix_hc)
     866              : 
     867           64 :          CALL reduce_extended_space(s_block, h_block, v_block, w_block, evals, nmat2)
     868              : 
     869              :          ! allocate two (nao x nmat) full matrix
     870              :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nao, ncol_global=nmat, &
     871              :                                   context=mo_coeff%matrix_struct%context, &
     872           64 :                                   para_env=mo_coeff%matrix_struct%para_env)
     873           64 :          CALL cp_fm_create(matrix_nm_fm, fm_struct_tmp, name="m_nxm")
     874           64 :          CALL cp_fm_create(matrix_z_fm, fm_struct_tmp, name="m_nxm")
     875           64 :          CALL cp_fm_struct_release(fm_struct_tmp)
     876              : 
     877           64 :          CALL copy_dbcsr_to_fm(matrix_pz, matrix_z_fm)
     878              :          ! extract egenvectors
     879           64 :          CALL cp_fm_to_fm_submat(v_block, matrix_mm_fm, nmat, nmat, 1, 1, 1, 1)
     880           64 :          CALL parallel_gemm('N', 'N', nao, nmat, nmat, 1.0_dp, mo_notconv_fm, matrix_mm_fm, 0.0_dp, matrix_nm_fm)
     881           64 :          CALL cp_fm_to_fm_submat(v_block, matrix_mm_fm, nmat, nmat, 1 + nmat, 1, 1, 1)
     882           64 :          CALL parallel_gemm('N', 'N', nao, nmat, nmat, 1.0_dp, matrix_z_fm, matrix_mm_fm, 1.0_dp, matrix_nm_fm)
     883              : 
     884           64 :          CALL dbcsr_release_p(matrix_z)
     885           64 :          CALL dbcsr_release_p(matrix_pz)
     886           64 :          CALL cp_fm_release(matrix_z_fm)
     887           64 :          CALL cp_fm_release(s_block)
     888           64 :          CALL cp_fm_release(h_block)
     889           64 :          CALL cp_fm_release(w_block)
     890           64 :          CALL cp_fm_release(v_block)
     891           64 :          CALL cp_fm_release(matrix_mm_fm)
     892              : 
     893              :          ! in case some vector are already converged only a subset of vectors are copied in the MOS
     894           64 :          IF (nmo_converged > 0) THEN
     895            6 :             jj = 1
     896           24 :             DO j = 1, nset_not_conv
     897           18 :                i_first = inotconv_set(j, 1)
     898           18 :                i_last = inotconv_set(j, 2)
     899           18 :                n = i_last - i_first + 1
     900           18 :                CALL cp_fm_to_fm_submat(matrix_nm_fm, mo_coeff, nao, n, 1, jj, 1, i_first)
     901          186 :                eigenvalues(i_first:i_last) = evals(jj:jj + n - 1)
     902           24 :                jj = jj + n
     903              :             END DO
     904            6 :             DEALLOCATE (iconv_set)
     905            6 :             DEALLOCATE (inotconv_set)
     906              : 
     907            6 :             CALL dbcsr_release_p(mo_notconv)
     908            6 :             CALL dbcsr_release_p(c_out)
     909            6 :             CALL cp_fm_release(mo_notconv_fm)
     910            6 :             DEALLOCATE (mo_notconv_fm)
     911              :          ELSE
     912           58 :             CALL cp_fm_to_fm(matrix_nm_fm, mo_coeff)
     913         2146 :             eigenvalues(1:nmo) = evals(1:nmo)
     914              :          END IF
     915           64 :          DEALLOCATE (evals)
     916              : 
     917           64 :          CALL cp_fm_release(matrix_nm_fm)
     918           64 :          CALL copy_fm_to_dbcsr(mo_coeff, mo_coeff_b) !fm->dbcsr
     919              : 
     920           64 :          t2 = m_walltime()
     921           64 :          IF (output_unit > 0) THEN
     922              :             WRITE (output_unit, '(T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
     923            0 :                iteration, nmo_converged, max_norm, min_norm, t2 - t1
     924              :          END IF
     925          536 :          t1 = m_walltime()
     926              : 
     927              :       END DO ! iteration
     928              : 
     929           64 :       DEALLOCATE (ritz_coeff)
     930           64 :       DEALLOCATE (iconv)
     931           64 :       DEALLOCATE (inotconv)
     932           64 :       DEALLOCATE (vnorm)
     933              : 
     934           64 :       CALL timestop(handle)
     935              : 
     936          192 :    END SUBROUTINE generate_extended_space_sparse
     937              : 
     938              : ! **************************************************************************************************
     939              : 
     940              : ! **************************************************************************************************
     941              : !> \brief ...
     942              : !> \param s_block ...
     943              : !> \param h_block ...
     944              : !> \param v_block ...
     945              : !> \param w_block ...
     946              : !> \param evals ...
     947              : !> \param ndim ...
     948              : ! **************************************************************************************************
     949          116 :    SUBROUTINE reduce_extended_space(s_block, h_block, v_block, w_block, evals, ndim)
     950              : 
     951              :       TYPE(cp_fm_type), INTENT(IN)                       :: s_block, h_block, v_block, w_block
     952              :       REAL(dp), DIMENSION(:)                             :: evals
     953              :       INTEGER                                            :: ndim
     954              : 
     955              :       CHARACTER(len=*), PARAMETER :: routineN = 'reduce_extended_space'
     956              : 
     957              :       INTEGER                                            :: handle, info
     958              : 
     959          116 :       CALL timeset(routineN, handle)
     960              : 
     961          116 :       CALL cp_fm_to_fm(s_block, w_block)
     962          116 :       CALL cp_fm_cholesky_decompose(s_block, info_out=info)
     963          116 :       IF (info == 0) THEN
     964          116 :          CALL cp_fm_triangular_invert(s_block)
     965          116 :          CALL cp_fm_cholesky_restore(H_block, ndim, S_block, w_block, "MULTIPLY", pos="RIGHT")
     966          116 :          CALL cp_fm_cholesky_restore(w_block, ndim, S_block, H_block, "MULTIPLY", pos="LEFT", transa="T")
     967          116 :          CALL choose_eigv_solver(H_block, w_block, evals)
     968          116 :          CALL cp_fm_cholesky_restore(w_block, ndim, S_block, v_block, "MULTIPLY")
     969              :       ELSE
     970              : ! S^(-1/2)
     971            0 :          CALL cp_fm_power(w_block, s_block, -0.5_dp, 1.0E-5_dp, info)
     972            0 :          CALL cp_fm_to_fm(w_block, s_block)
     973            0 :          CALL parallel_gemm('N', 'N', ndim, ndim, ndim, 1.0_dp, H_block, s_block, 0.0_dp, w_block)
     974            0 :          CALL parallel_gemm('N', 'N', ndim, ndim, ndim, 1.0_dp, s_block, w_block, 0.0_dp, H_block)
     975            0 :          CALL choose_eigv_solver(H_block, w_block, evals)
     976            0 :          CALL parallel_gemm('N', 'N', ndim, ndim, ndim, 1.0_dp, s_block, w_block, 0.0_dp, v_block)
     977              :       END IF
     978              : 
     979          116 :       CALL timestop(handle)
     980              : 
     981          116 :    END SUBROUTINE reduce_extended_space
     982              : 
     983              : END MODULE qs_scf_block_davidson
        

Generated by: LCOV version 2.0-1