LCOV - code coverage report
Current view: top level - src - qs_scf_block_davidson.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b4bd748) Lines: 496 514 96.5 %
Date: 2025-03-09 07:56:22 Functions: 3 3 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 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 1.15