LCOV - code coverage report
Current view: top level - src - qs_density_matrices.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:ccc2433) Lines: 150 155 96.8 %
Date: 2024-04-25 07:09:54 Functions: 8 8 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief collects routines that calculate density matrices
      10             : !> \note
      11             : !>      first version : most routines imported
      12             : !> \author JGH (2020-01)
      13             : ! **************************************************************************************************
      14             : MODULE qs_density_matrices
      15             :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      16             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      17             :                                               copy_fm_to_dbcsr,&
      18             :                                               cp_dbcsr_plus_fm_fm_t,&
      19             :                                               cp_dbcsr_sm_fm_multiply
      20             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      21             :                                               cp_fm_scale_and_add,&
      22             :                                               cp_fm_symm,&
      23             :                                               cp_fm_transpose,&
      24             :                                               cp_fm_upper_to_full
      25             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      26             :                                               cp_fm_struct_release,&
      27             :                                               cp_fm_struct_type
      28             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      29             :                                               cp_fm_get_info,&
      30             :                                               cp_fm_release,&
      31             :                                               cp_fm_to_fm,&
      32             :                                               cp_fm_type
      33             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      34             :                                               cp_logger_get_default_unit_nr,&
      35             :                                               cp_logger_type
      36             :    USE dbcsr_api,                       ONLY: dbcsr_copy,&
      37             :                                               dbcsr_multiply,&
      38             :                                               dbcsr_release,&
      39             :                                               dbcsr_scale_by_vector,&
      40             :                                               dbcsr_set,&
      41             :                                               dbcsr_type
      42             :    USE kinds,                           ONLY: dp
      43             :    USE message_passing,                 ONLY: mp_para_env_type
      44             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      45             :    USE qs_mo_types,                     ONLY: get_mo_set,&
      46             :                                               mo_set_type
      47             : #include "./base/base_uses.f90"
      48             : 
      49             :    IMPLICIT NONE
      50             :    PRIVATE
      51             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_density_matrices'
      52             : 
      53             :    PUBLIC :: calculate_density_matrix
      54             :    PUBLIC :: calculate_w_matrix, calculate_w_matrix_ot
      55             :    PUBLIC :: calculate_wz_matrix, calculate_whz_matrix
      56             :    PUBLIC :: calculate_wx_matrix, calculate_xwx_matrix
      57             : 
      58             :    INTERFACE calculate_density_matrix
      59             :       MODULE PROCEDURE calculate_dm_sparse
      60             :    END INTERFACE
      61             : 
      62             :    INTERFACE calculate_w_matrix
      63             :       MODULE PROCEDURE calculate_w_matrix_1, calculate_w_matrix_roks
      64             :    END INTERFACE
      65             : 
      66             : CONTAINS
      67             : 
      68             : ! **************************************************************************************************
      69             : !> \brief   Calculate the density matrix
      70             : !> \param mo_set ...
      71             : !> \param density_matrix ...
      72             : !> \param use_dbcsr ...
      73             : !> \param retain_sparsity ...
      74             : !> \date    06.2002
      75             : !> \par History
      76             : !>       - Fractional occupied orbitals (MK)
      77             : !> \author  Joost VandeVondele
      78             : !> \version 1.0
      79             : ! **************************************************************************************************
      80      183687 :    SUBROUTINE calculate_dm_sparse(mo_set, density_matrix, use_dbcsr, retain_sparsity)
      81             : 
      82             :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
      83             :       TYPE(dbcsr_type), POINTER                          :: density_matrix
      84             :       LOGICAL, INTENT(IN), OPTIONAL                      :: use_dbcsr, retain_sparsity
      85             : 
      86             :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_dm_sparse'
      87             : 
      88             :       INTEGER                                            :: handle
      89             :       LOGICAL                                            :: my_retain_sparsity, my_use_dbcsr
      90             :       REAL(KIND=dp)                                      :: alpha
      91             :       TYPE(cp_fm_type)                                   :: fm_tmp
      92             :       TYPE(dbcsr_type)                                   :: dbcsr_tmp
      93             : 
      94      183687 :       CALL timeset(routineN, handle)
      95             : 
      96      183687 :       my_use_dbcsr = .FALSE.
      97      183687 :       IF (PRESENT(use_dbcsr)) my_use_dbcsr = use_dbcsr
      98      183687 :       my_retain_sparsity = .TRUE.
      99      183687 :       IF (PRESENT(retain_sparsity)) my_retain_sparsity = retain_sparsity
     100      183687 :       IF (my_use_dbcsr) THEN
     101       74466 :          IF (.NOT. ASSOCIATED(mo_set%mo_coeff_b)) THEN
     102           0 :             CPABORT("mo_coeff_b NOT ASSOCIATED")
     103             :          END IF
     104             :       END IF
     105             : 
     106      183687 :       CALL dbcsr_set(density_matrix, 0.0_dp)
     107             : 
     108      183687 :       IF (.NOT. mo_set%uniform_occupation) THEN ! not all orbitals 1..homo are equally occupied
     109       13020 :          IF (my_use_dbcsr) THEN
     110           0 :             CALL dbcsr_copy(dbcsr_tmp, mo_set%mo_coeff_b)
     111             :             CALL dbcsr_scale_by_vector(dbcsr_tmp, mo_set%occupation_numbers(1:mo_set%homo), &
     112           0 :                                        side='right')
     113             :             CALL dbcsr_multiply("N", "T", 1.0_dp, mo_set%mo_coeff_b, dbcsr_tmp, &
     114             :                                 1.0_dp, density_matrix, retain_sparsity=my_retain_sparsity, &
     115           0 :                                 last_k=mo_set%homo)
     116           0 :             CALL dbcsr_release(dbcsr_tmp)
     117             :          ELSE
     118       13020 :             CALL cp_fm_create(fm_tmp, mo_set%mo_coeff%matrix_struct)
     119       13020 :             CALL cp_fm_to_fm(mo_set%mo_coeff, fm_tmp)
     120       13020 :             CALL cp_fm_column_scale(fm_tmp, mo_set%occupation_numbers(1:mo_set%homo))
     121       13020 :             alpha = 1.0_dp
     122             :             CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=density_matrix, &
     123             :                                        matrix_v=mo_set%mo_coeff, &
     124             :                                        matrix_g=fm_tmp, &
     125             :                                        ncol=mo_set%homo, &
     126       13020 :                                        alpha=alpha)
     127       13020 :             CALL cp_fm_release(fm_tmp)
     128             :          END IF
     129             :       ELSE
     130      170667 :          IF (my_use_dbcsr) THEN
     131             :             CALL dbcsr_multiply("N", "T", mo_set%maxocc, mo_set%mo_coeff_b, mo_set%mo_coeff_b, &
     132             :                                 1.0_dp, density_matrix, retain_sparsity=my_retain_sparsity, &
     133       74466 :                                 last_k=mo_set%homo)
     134             :          ELSE
     135       96201 :             alpha = mo_set%maxocc
     136             :             CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=density_matrix, &
     137             :                                        matrix_v=mo_set%mo_coeff, &
     138             :                                        ncol=mo_set%homo, &
     139       96201 :                                        alpha=alpha)
     140             :          END IF
     141             :       END IF
     142             : 
     143      183687 :       CALL timestop(handle)
     144             : 
     145      183687 :    END SUBROUTINE calculate_dm_sparse
     146             : 
     147             : ! **************************************************************************************************
     148             : !> \brief Calculate the W matrix from the MO eigenvectors, MO eigenvalues,
     149             : !>       and the MO occupation numbers. Only works if they are eigenstates
     150             : !> \param mo_set type containing the full matrix of the MO and the eigenvalues
     151             : !> \param w_matrix sparse matrix
     152             : !>        error
     153             : !> \par History
     154             : !>         Creation (03.03.03,MK)
     155             : !>         Modification that computes it as a full block, several times (e.g. 20)
     156             : !>               faster at the cost of some additional memory
     157             : !> \author MK
     158             : ! **************************************************************************************************
     159        3466 :    SUBROUTINE calculate_w_matrix_1(mo_set, w_matrix)
     160             : 
     161             :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
     162             :       TYPE(dbcsr_type), POINTER                          :: w_matrix
     163             : 
     164             :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_w_matrix_1'
     165             : 
     166             :       INTEGER                                            :: handle, imo
     167             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigocc
     168             :       TYPE(cp_fm_type)                                   :: weighted_vectors
     169             : 
     170        3466 :       CALL timeset(routineN, handle)
     171             : 
     172        3466 :       CALL dbcsr_set(w_matrix, 0.0_dp)
     173        3466 :       CALL cp_fm_create(weighted_vectors, mo_set%mo_coeff%matrix_struct, "weighted_vectors")
     174        3466 :       CALL cp_fm_to_fm(mo_set%mo_coeff, weighted_vectors)
     175             : 
     176             :       ! scale every column with the occupation
     177       10348 :       ALLOCATE (eigocc(mo_set%homo))
     178             : 
     179       41842 :       DO imo = 1, mo_set%homo
     180       41842 :          eigocc(imo) = mo_set%eigenvalues(imo)*mo_set%occupation_numbers(imo)
     181             :       END DO
     182        3466 :       CALL cp_fm_column_scale(weighted_vectors, eigocc)
     183        3466 :       DEALLOCATE (eigocc)
     184             : 
     185             :       CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=w_matrix, &
     186             :                                  matrix_v=mo_set%mo_coeff, &
     187             :                                  matrix_g=weighted_vectors, &
     188        3466 :                                  ncol=mo_set%homo)
     189             : 
     190        3466 :       CALL cp_fm_release(weighted_vectors)
     191             : 
     192        3466 :       CALL timestop(handle)
     193             : 
     194        3466 :    END SUBROUTINE calculate_w_matrix_1
     195             : 
     196             : ! **************************************************************************************************
     197             : !> \brief Calculate the W matrix from the MO coefs, MO derivs
     198             : !>        could overwrite the mo_derivs for increased memory efficiency
     199             : !> \param mo_set type containing the full matrix of the MO coefs
     200             : !>        mo_deriv:
     201             : !> \param mo_deriv ...
     202             : !> \param w_matrix sparse matrix
     203             : !> \param s_matrix sparse matrix for the overlap
     204             : !>        error
     205             : !> \par History
     206             : !>         Creation (JV)
     207             : !> \author MK
     208             : ! **************************************************************************************************
     209        2457 :    SUBROUTINE calculate_w_matrix_ot(mo_set, mo_deriv, w_matrix, s_matrix)
     210             : 
     211             :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
     212             :       TYPE(dbcsr_type), POINTER                          :: mo_deriv, w_matrix, s_matrix
     213             : 
     214             :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_w_matrix_ot'
     215             :       LOGICAL, PARAMETER                                 :: check_gradient = .FALSE., &
     216             :                                                             do_symm = .FALSE.
     217             : 
     218             :       INTEGER                                            :: handle, iounit, ncol_block, ncol_global, &
     219             :                                                             nrow_block, nrow_global
     220        2457 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: occupation_numbers, scaling_factor
     221             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
     222             :       TYPE(cp_fm_type)                                   :: gradient, h_block, h_block_t, &
     223             :                                                             weighted_vectors
     224             :       TYPE(cp_logger_type), POINTER                      :: logger
     225             : 
     226        2457 :       CALL timeset(routineN, handle)
     227        2457 :       NULLIFY (fm_struct_tmp)
     228             : 
     229             :       CALL cp_fm_get_info(matrix=mo_set%mo_coeff, &
     230             :                           ncol_global=ncol_global, &
     231             :                           nrow_global=nrow_global, &
     232             :                           nrow_block=nrow_block, &
     233        2457 :                           ncol_block=ncol_block)
     234             : 
     235        2457 :       CALL cp_fm_create(weighted_vectors, mo_set%mo_coeff%matrix_struct, "weighted_vectors")
     236             :       CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol_global, ncol_global=ncol_global, &
     237             :                                para_env=mo_set%mo_coeff%matrix_struct%para_env, &
     238        2457 :                                context=mo_set%mo_coeff%matrix_struct%context)
     239        2457 :       CALL cp_fm_create(h_block, fm_struct_tmp, name="h block")
     240             :       IF (do_symm) CALL cp_fm_create(h_block_t, fm_struct_tmp, name="h block t")
     241        2457 :       CALL cp_fm_struct_release(fm_struct_tmp)
     242             : 
     243        2457 :       CALL get_mo_set(mo_set=mo_set, occupation_numbers=occupation_numbers)
     244        7335 :       ALLOCATE (scaling_factor(SIZE(occupation_numbers)))
     245       37530 :       scaling_factor = 2.0_dp*occupation_numbers
     246        2457 :       CALL copy_dbcsr_to_fm(mo_deriv, weighted_vectors)
     247        2457 :       CALL cp_fm_column_scale(weighted_vectors, scaling_factor)
     248        2457 :       DEALLOCATE (scaling_factor)
     249             : 
     250             :       ! the convention seems to require the half here, the factor of two is presumably taken care of
     251             :       ! internally in qs_core_hamiltonian
     252             :       CALL parallel_gemm('T', 'N', ncol_global, ncol_global, nrow_global, 0.5_dp, &
     253        2457 :                          mo_set%mo_coeff, weighted_vectors, 0.0_dp, h_block)
     254             : 
     255             :       IF (do_symm) THEN
     256             :          ! at the minimum things are anyway symmetric, but numerically it might not be the case
     257             :          ! needs some investigation to find out if using this is better
     258             :          CALL cp_fm_transpose(h_block, h_block_t)
     259             :          CALL cp_fm_scale_and_add(0.5_dp, h_block, 0.5_dp, h_block_t)
     260             :       END IF
     261             : 
     262             :       ! this could overwrite the mo_derivs to save the weighted_vectors
     263             :       CALL parallel_gemm('N', 'N', nrow_global, ncol_global, ncol_global, 1.0_dp, &
     264        2457 :                          mo_set%mo_coeff, h_block, 0.0_dp, weighted_vectors)
     265             : 
     266        2457 :       CALL dbcsr_set(w_matrix, 0.0_dp)
     267             :       CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=w_matrix, &
     268             :                                  matrix_v=mo_set%mo_coeff, &
     269             :                                  matrix_g=weighted_vectors, &
     270        2457 :                                  ncol=mo_set%homo)
     271             : 
     272             :       IF (check_gradient) THEN
     273             :          CALL cp_fm_create(gradient, mo_set%mo_coeff%matrix_struct, "gradient")
     274             :          CALL cp_dbcsr_sm_fm_multiply(s_matrix, weighted_vectors, &
     275             :                                       gradient, ncol_global)
     276             : 
     277             :          ALLOCATE (scaling_factor(SIZE(occupation_numbers)))
     278             :          scaling_factor = 2.0_dp*occupation_numbers
     279             :          CALL copy_dbcsr_to_fm(mo_deriv, weighted_vectors)
     280             :          CALL cp_fm_column_scale(weighted_vectors, scaling_factor)
     281             :          DEALLOCATE (scaling_factor)
     282             : 
     283             :          logger => cp_get_default_logger()
     284             :          IF (logger%para_env%is_source()) THEN
     285             :             iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     286             :             WRITE (iounit, *) " maxabs difference ", &
     287             :                MAXVAL(ABS(weighted_vectors%local_data - 2.0_dp*gradient%local_data))
     288             :          END IF
     289             :          CALL cp_fm_release(gradient)
     290             :       END IF
     291             : 
     292             :       IF (do_symm) CALL cp_fm_release(h_block_t)
     293        2457 :       CALL cp_fm_release(weighted_vectors)
     294        2457 :       CALL cp_fm_release(h_block)
     295             : 
     296        2457 :       CALL timestop(handle)
     297             : 
     298        2457 :    END SUBROUTINE calculate_w_matrix_ot
     299             : 
     300             : ! **************************************************************************************************
     301             : !> \brief Calculate the energy-weighted density matrix W if ROKS is active.
     302             : !>        The W matrix is returned in matrix_w.
     303             : !> \param mo_set ...
     304             : !> \param matrix_ks ...
     305             : !> \param matrix_p ...
     306             : !> \param matrix_w ...
     307             : !> \author 04.05.06,MK
     308             : ! **************************************************************************************************
     309         104 :    SUBROUTINE calculate_w_matrix_roks(mo_set, matrix_ks, matrix_p, matrix_w)
     310             :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
     311             :       TYPE(dbcsr_type), POINTER                          :: matrix_ks, matrix_p, matrix_w
     312             : 
     313             :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_w_matrix_roks'
     314             : 
     315             :       INTEGER                                            :: handle, nao
     316             :       TYPE(cp_blacs_env_type), POINTER                   :: context
     317             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     318             :       TYPE(cp_fm_type)                                   :: ks, p, work
     319             :       TYPE(cp_fm_type), POINTER                          :: c
     320             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     321             : 
     322          52 :       CALL timeset(routineN, handle)
     323             : 
     324          52 :       NULLIFY (context)
     325          52 :       NULLIFY (fm_struct)
     326          52 :       NULLIFY (para_env)
     327             : 
     328          52 :       CALL get_mo_set(mo_set=mo_set, mo_coeff=c)
     329          52 :       CALL cp_fm_get_info(c, context=context, nrow_global=nao, para_env=para_env)
     330             :       CALL cp_fm_struct_create(fm_struct, context=context, nrow_global=nao, &
     331          52 :                                ncol_global=nao, para_env=para_env)
     332          52 :       CALL cp_fm_create(ks, fm_struct, name="Kohn-Sham matrix")
     333          52 :       CALL cp_fm_create(p, fm_struct, name="Density matrix")
     334          52 :       CALL cp_fm_create(work, fm_struct, name="Work matrix")
     335          52 :       CALL cp_fm_struct_release(fm_struct)
     336          52 :       CALL copy_dbcsr_to_fm(matrix_ks, ks)
     337          52 :       CALL copy_dbcsr_to_fm(matrix_p, p)
     338          52 :       CALL cp_fm_upper_to_full(p, work)
     339          52 :       CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ks, p, 0.0_dp, work)
     340          52 :       CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, p, work, 0.0_dp, ks)
     341          52 :       CALL dbcsr_set(matrix_w, 0.0_dp)
     342          52 :       CALL copy_fm_to_dbcsr(ks, matrix_w, keep_sparsity=.TRUE.)
     343             : 
     344          52 :       CALL cp_fm_release(work)
     345          52 :       CALL cp_fm_release(p)
     346          52 :       CALL cp_fm_release(ks)
     347             : 
     348          52 :       CALL timestop(handle)
     349             : 
     350          52 :    END SUBROUTINE calculate_w_matrix_roks
     351             : 
     352             : ! **************************************************************************************************
     353             : !> \brief Calculate the response W matrix from the MO eigenvectors, MO eigenvalues,
     354             : !>       and the MO occupation numbers. Only works if they are eigenstates
     355             : !> \param mo_set type containing the full matrix of the MO and the eigenvalues
     356             : !> \param psi1 response orbitals
     357             : !> \param ks_matrix Kohn-Sham sparse matrix
     358             : !> \param w_matrix sparse matrix
     359             : !> \par History
     360             : !>               adapted from calculate_w_matrix_1
     361             : !> \author JGH
     362             : ! **************************************************************************************************
     363        2048 :    SUBROUTINE calculate_wz_matrix(mo_set, psi1, ks_matrix, w_matrix)
     364             : 
     365             :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
     366             :       TYPE(cp_fm_type), INTENT(IN)                       :: psi1
     367             :       TYPE(dbcsr_type), POINTER                          :: ks_matrix, w_matrix
     368             : 
     369             :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_wz_matrix'
     370             : 
     371             :       INTEGER                                            :: handle, ncol, nocc, nrow
     372             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
     373             :       TYPE(cp_fm_type)                                   :: ksmat, scrv
     374             : 
     375        1024 :       CALL timeset(routineN, handle)
     376             : 
     377             : !     CALL cp_fm_get_info(matrix=mo_set%mo_coeff, ncol_global=ncol, nrow_global=nrow)
     378             : !     CALL cp_fm_create(scrv, mo_set%mo_coeff%matrix_struct, "scr vectors")
     379             : !     CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol, ncol_global=ncol, &
     380             : !                              para_env=mo_set%mo_coeff%matrix_struct%para_env, &
     381             : !                              context=mo_set%mo_coeff%matrix_struct%context)
     382             : !     CALL cp_fm_create(ksmat, fm_struct_tmp, name="KS")
     383             : !     CALL cp_fm_struct_release(fm_struct_tmp)
     384             : !     CALL cp_dbcsr_sm_fm_multiply(ks_matrix, mo_set%mo_coeff, scrv, ncol)
     385             : !     CALL parallel_gemm("T", "N", ncol, ncol, nrow, 1.0_dp, mo_set%mo_coeff, scrv, 0.0_dp, ksmat)
     386             : !     CALL parallel_gemm("N", "N", nrow, ncol, ncol, 1.0_dp, mo_set%mo_coeff, ksmat, 0.0_dp, scrv)
     387             : !     CALL dbcsr_set(w_matrix, 0.0_dp)
     388             : !     CALL cp_dbcsr_plus_fm_fm_t(w_matrix, matrix_v=scrv, matrix_g=psi1, &
     389             : !                                ncol=mo_set%homo, symmetry_mode=1)
     390             : !     CALL cp_fm_release(scrv)
     391             : !     CALL cp_fm_release(ksmat)
     392        1024 :       CALL cp_fm_get_info(matrix=mo_set%mo_coeff, ncol_global=ncol, nrow_global=nrow)
     393        1024 :       nocc = mo_set%homo
     394        1024 :       CALL cp_fm_create(scrv, mo_set%mo_coeff%matrix_struct, "scr vectors")
     395             :       CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nocc, ncol_global=nocc, &
     396             :                                para_env=mo_set%mo_coeff%matrix_struct%para_env, &
     397        1024 :                                context=mo_set%mo_coeff%matrix_struct%context)
     398        1024 :       CALL cp_fm_create(ksmat, fm_struct_tmp, name="KS")
     399        1024 :       CALL cp_fm_struct_release(fm_struct_tmp)
     400        1024 :       CALL cp_dbcsr_sm_fm_multiply(ks_matrix, mo_set%mo_coeff, scrv, nocc)
     401        1024 :       CALL parallel_gemm("T", "N", nocc, nocc, nrow, 1.0_dp, mo_set%mo_coeff, scrv, 0.0_dp, ksmat)
     402        1024 :       CALL parallel_gemm("N", "N", nrow, nocc, nocc, 1.0_dp, mo_set%mo_coeff, ksmat, 0.0_dp, scrv)
     403        1024 :       CALL dbcsr_set(w_matrix, 0.0_dp)
     404        1024 :       CALL cp_dbcsr_plus_fm_fm_t(w_matrix, matrix_v=scrv, matrix_g=psi1, ncol=nocc, symmetry_mode=1)
     405        1024 :       CALL cp_fm_release(scrv)
     406        1024 :       CALL cp_fm_release(ksmat)
     407             : 
     408        1024 :       CALL timestop(handle)
     409             : 
     410        1024 :    END SUBROUTINE calculate_wz_matrix
     411             : 
     412             : ! **************************************************************************************************
     413             : !> \brief Calculate the Wz matrix from the MO eigenvectors, MO eigenvalues,
     414             : !>       and the MO occupation numbers. Only works if they are eigenstates
     415             : !> \param c0vec ...
     416             : !> \param hzm ...
     417             : !> \param w_matrix sparse matrix
     418             : !> \param focc ...
     419             : !> \param nocc ...
     420             : !> \par History
     421             : !>               adapted from calculate_w_matrix_1
     422             : !> \author JGH
     423             : ! **************************************************************************************************
     424        2980 :    SUBROUTINE calculate_whz_matrix(c0vec, hzm, w_matrix, focc, nocc)
     425             : 
     426             :       TYPE(cp_fm_type), INTENT(IN)                       :: c0vec
     427             :       TYPE(dbcsr_type), POINTER                          :: hzm, w_matrix
     428             :       REAL(KIND=dp), INTENT(IN)                          :: focc
     429             :       INTEGER, INTENT(IN)                                :: nocc
     430             : 
     431             :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_whz_matrix'
     432             : 
     433             :       INTEGER                                            :: handle, nao, norb
     434             :       REAL(KIND=dp)                                      :: falpha
     435             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct, fm_struct_mat
     436             :       TYPE(cp_fm_type)                                   :: chcmat, hcvec
     437             : 
     438        1490 :       CALL timeset(routineN, handle)
     439             : 
     440        1490 :       falpha = focc
     441             : 
     442        1490 :       CALL cp_fm_create(hcvec, c0vec%matrix_struct, "hcvec")
     443        1490 :       CALL cp_fm_get_info(hcvec, matrix_struct=fm_struct, nrow_global=nao, ncol_global=norb)
     444        1490 :       CPASSERT(nocc <= norb .AND. nocc > 0)
     445        1490 :       norb = nocc
     446             :       CALL cp_fm_struct_create(fm_struct_mat, context=fm_struct%context, nrow_global=norb, &
     447        1490 :                                ncol_global=norb, para_env=fm_struct%para_env)
     448        1490 :       CALL cp_fm_create(chcmat, fm_struct_mat)
     449        1490 :       CALL cp_fm_struct_release(fm_struct_mat)
     450             : 
     451        1490 :       CALL cp_dbcsr_sm_fm_multiply(hzm, c0vec, hcvec, norb)
     452        1490 :       CALL parallel_gemm("T", "N", norb, norb, nao, 1.0_dp, c0vec, hcvec, 0.0_dp, chcmat)
     453        1490 :       CALL parallel_gemm("N", "N", nao, norb, norb, 1.0_dp, c0vec, chcmat, 0.0_dp, hcvec)
     454             : 
     455        1490 :       CALL cp_dbcsr_plus_fm_fm_t(w_matrix, matrix_v=hcvec, matrix_g=c0vec, ncol=norb, alpha=falpha)
     456             : 
     457        1490 :       CALL cp_fm_release(hcvec)
     458        1490 :       CALL cp_fm_release(chcmat)
     459             : 
     460        1490 :       CALL timestop(handle)
     461             : 
     462        1490 :    END SUBROUTINE calculate_whz_matrix
     463             : 
     464             : ! **************************************************************************************************
     465             : !> \brief Calculate the excited state W matrix from the MO eigenvectors, KS matrix
     466             : !> \param mos_occ ...
     467             : !> \param xvec ...
     468             : !> \param ks_matrix ...
     469             : !> \param w_matrix ...
     470             : !> \par History
     471             : !>               adapted from calculate_wz_matrix
     472             : !> \author JGH
     473             : ! **************************************************************************************************
     474        1324 :    SUBROUTINE calculate_wx_matrix(mos_occ, xvec, ks_matrix, w_matrix)
     475             : 
     476             :       TYPE(cp_fm_type), INTENT(IN)                       :: mos_occ, xvec
     477             :       TYPE(dbcsr_type), POINTER                          :: ks_matrix, w_matrix
     478             : 
     479             :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_wx_matrix'
     480             : 
     481             :       INTEGER                                            :: handle, ncol, nrow
     482             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
     483             :       TYPE(cp_fm_type)                                   :: ksmat, scrv
     484             : 
     485         662 :       CALL timeset(routineN, handle)
     486             : 
     487         662 :       CALL cp_fm_get_info(matrix=mos_occ, ncol_global=ncol, nrow_global=nrow)
     488         662 :       CALL cp_fm_create(scrv, mos_occ%matrix_struct, "scr vectors")
     489             :       CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol, ncol_global=ncol, &
     490             :                                para_env=mos_occ%matrix_struct%para_env, &
     491         662 :                                context=mos_occ%matrix_struct%context)
     492         662 :       CALL cp_fm_create(ksmat, fm_struct_tmp, name="KS")
     493         662 :       CALL cp_fm_struct_release(fm_struct_tmp)
     494         662 :       CALL cp_dbcsr_sm_fm_multiply(ks_matrix, mos_occ, scrv, ncol)
     495         662 :       CALL parallel_gemm("T", "N", ncol, ncol, nrow, 1.0_dp, mos_occ, scrv, 0.0_dp, ksmat)
     496         662 :       CALL parallel_gemm("N", "N", nrow, ncol, ncol, 1.0_dp, xvec, ksmat, 0.0_dp, scrv)
     497         662 :       CALL cp_dbcsr_plus_fm_fm_t(w_matrix, matrix_v=scrv, matrix_g=xvec, ncol=ncol, symmetry_mode=1)
     498         662 :       CALL cp_fm_release(scrv)
     499         662 :       CALL cp_fm_release(ksmat)
     500             : 
     501         662 :       CALL timestop(handle)
     502             : 
     503         662 :    END SUBROUTINE calculate_wx_matrix
     504             : 
     505             : ! **************************************************************************************************
     506             : !> \brief Calculate the excited state W matrix from the MO eigenvectors, KS matrix
     507             : !> \param mos_occ ...
     508             : !> \param xvec ...
     509             : !> \param s_matrix ...
     510             : !> \param ks_matrix ...
     511             : !> \param w_matrix ...
     512             : !> \param eval ...
     513             : !> \par History
     514             : !>               adapted from calculate_wz_matrix
     515             : !> \author JGH
     516             : ! **************************************************************************************************
     517        1324 :    SUBROUTINE calculate_xwx_matrix(mos_occ, xvec, s_matrix, ks_matrix, w_matrix, eval)
     518             : 
     519             :       TYPE(cp_fm_type), INTENT(IN)                       :: mos_occ, xvec
     520             :       TYPE(dbcsr_type), POINTER                          :: s_matrix, ks_matrix, w_matrix
     521             :       REAL(KIND=dp), INTENT(IN)                          :: eval
     522             : 
     523             :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_xwx_matrix'
     524             : 
     525             :       INTEGER                                            :: handle, ncol, nrow
     526             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
     527             :       TYPE(cp_fm_type)                                   :: scrv, xsxmat
     528             : 
     529         662 :       CALL timeset(routineN, handle)
     530             : 
     531         662 :       CALL cp_fm_get_info(matrix=mos_occ, ncol_global=ncol, nrow_global=nrow)
     532         662 :       CALL cp_fm_create(scrv, mos_occ%matrix_struct, "scr vectors")
     533             :       CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol, ncol_global=ncol, &
     534             :                                para_env=mos_occ%matrix_struct%para_env, &
     535         662 :                                context=mos_occ%matrix_struct%context)
     536         662 :       CALL cp_fm_create(xsxmat, fm_struct_tmp, name="XSX")
     537         662 :       CALL cp_fm_struct_release(fm_struct_tmp)
     538             : 
     539         662 :       CALL cp_dbcsr_sm_fm_multiply(ks_matrix, xvec, scrv, ncol, 1.0_dp, 0.0_dp)
     540         662 :       CALL cp_dbcsr_sm_fm_multiply(s_matrix, xvec, scrv, ncol, eval, -1.0_dp)
     541         662 :       CALL parallel_gemm("T", "N", ncol, ncol, nrow, 1.0_dp, xvec, scrv, 0.0_dp, xsxmat)
     542             : 
     543         662 :       CALL parallel_gemm("N", "N", nrow, ncol, ncol, 1.0_dp, mos_occ, xsxmat, 0.0_dp, scrv)
     544         662 :       CALL cp_dbcsr_plus_fm_fm_t(w_matrix, matrix_v=scrv, matrix_g=mos_occ, ncol=ncol, symmetry_mode=1)
     545             : 
     546         662 :       CALL cp_fm_release(scrv)
     547         662 :       CALL cp_fm_release(xsxmat)
     548             : 
     549         662 :       CALL timestop(handle)
     550             : 
     551         662 :    END SUBROUTINE calculate_xwx_matrix
     552             : 
     553             : END MODULE qs_density_matrices

Generated by: LCOV version 1.15