LCOV - code coverage report
Current view: top level - src - qs_tddfpt2_stda_utils.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b8e0b09) Lines: 289 307 94.1 %
Date: 2024-08-31 06:31:37 Functions: 5 5 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             : !> \brief Simplified Tamm Dancoff approach (sTDA).
       9             : ! **************************************************************************************************
      10             : MODULE qs_tddfpt2_stda_utils
      11             : 
      12             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      13             :                                               get_atomic_kind_set
      14             :    USE cell_types,                      ONLY: cell_type,&
      15             :                                               pbc
      16             :    USE cp_control_types,                ONLY: stda_control_type,&
      17             :                                               tddfpt2_control_type
      18             :    USE cp_dbcsr_api,                    ONLY: &
      19             :         dbcsr_add_on_diag, dbcsr_create, dbcsr_distribution_type, dbcsr_filter, dbcsr_finalize, &
      20             :         dbcsr_get_block_p, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
      21             :         dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, &
      22             :         dbcsr_release, dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, &
      23             :         dbcsr_type_symmetric
      24             :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      25             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      26             :                                               copy_fm_to_dbcsr,&
      27             :                                               cp_dbcsr_plus_fm_fm_t,&
      28             :                                               cp_dbcsr_sm_fm_multiply,&
      29             :                                               dbcsr_allocate_matrix_set
      30             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_row_scale,&
      31             :                                               cp_fm_schur_product
      32             :    USE cp_fm_diag,                      ONLY: choose_eigv_solver,&
      33             :                                               cp_fm_power
      34             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      35             :                                               cp_fm_struct_release,&
      36             :                                               cp_fm_struct_type
      37             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      38             :                                               cp_fm_get_info,&
      39             :                                               cp_fm_release,&
      40             :                                               cp_fm_set_all,&
      41             :                                               cp_fm_set_submatrix,&
      42             :                                               cp_fm_to_fm,&
      43             :                                               cp_fm_type,&
      44             :                                               cp_fm_vectorssum
      45             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      46             :                                               cp_logger_get_default_io_unit,&
      47             :                                               cp_logger_type
      48             :    USE ewald_environment_types,         ONLY: ewald_env_create,&
      49             :                                               ewald_env_get,&
      50             :                                               ewald_env_set,&
      51             :                                               ewald_environment_type,&
      52             :                                               read_ewald_section_tb
      53             :    USE ewald_methods_tb,                ONLY: tb_ewald_overlap,&
      54             :                                               tb_spme_evaluate
      55             :    USE ewald_pw_types,                  ONLY: ewald_pw_create,&
      56             :                                               ewald_pw_type
      57             :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      58             :                                               section_vals_type
      59             :    USE iterate_matrix,                  ONLY: matrix_sqrt_Newton_Schulz
      60             :    USE kinds,                           ONLY: dp
      61             :    USE mathconstants,                   ONLY: oorootpi
      62             :    USE message_passing,                 ONLY: mp_para_env_type
      63             :    USE particle_methods,                ONLY: get_particle_set
      64             :    USE particle_types,                  ONLY: particle_type
      65             :    USE qs_environment_types,            ONLY: get_qs_env,&
      66             :                                               qs_environment_type
      67             :    USE qs_kind_types,                   ONLY: get_qs_kind_set,&
      68             :                                               qs_kind_type
      69             :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      70             :                                               neighbor_list_iterate,&
      71             :                                               neighbor_list_iterator_create,&
      72             :                                               neighbor_list_iterator_p_type,&
      73             :                                               neighbor_list_iterator_release,&
      74             :                                               neighbor_list_set_p_type
      75             :    USE qs_tddfpt2_stda_types,           ONLY: stda_env_type
      76             :    USE qs_tddfpt2_subgroups,            ONLY: tddfpt_subgroup_env_type
      77             :    USE qs_tddfpt2_types,                ONLY: tddfpt_work_matrices
      78             :    USE scf_control_types,               ONLY: scf_control_type
      79             :    USE util,                            ONLY: get_limit
      80             :    USE virial_types,                    ONLY: virial_type
      81             : #include "./base/base_uses.f90"
      82             : 
      83             :    IMPLICIT NONE
      84             : 
      85             :    PRIVATE
      86             : 
      87             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_stda_utils'
      88             : 
      89             :    PUBLIC:: stda_init_matrices, stda_calculate_kernel, get_lowdin_x, get_lowdin_mo_coefficients, &
      90             :             setup_gamma
      91             : 
      92             : CONTAINS
      93             : 
      94             : ! **************************************************************************************************
      95             : !> \brief Calculate sTDA matrices
      96             : !> \param qs_env ...
      97             : !> \param stda_kernel ...
      98             : !> \param sub_env ...
      99             : !> \param work ...
     100             : !> \param tddfpt_control ...
     101             : ! **************************************************************************************************
     102         402 :    SUBROUTINE stda_init_matrices(qs_env, stda_kernel, sub_env, work, tddfpt_control)
     103             : 
     104             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     105             :       TYPE(stda_env_type)                                :: stda_kernel
     106             :       TYPE(tddfpt_subgroup_env_type), INTENT(in)         :: sub_env
     107             :       TYPE(tddfpt_work_matrices)                         :: work
     108             :       TYPE(tddfpt2_control_type), POINTER                :: tddfpt_control
     109             : 
     110             :       CHARACTER(len=*), PARAMETER :: routineN = 'stda_init_matrices'
     111             : 
     112             :       INTEGER                                            :: handle
     113             :       LOGICAL                                            :: do_coulomb
     114             :       TYPE(cell_type), POINTER                           :: cell, cell_ref
     115             :       TYPE(ewald_environment_type), POINTER              :: ewald_env
     116             :       TYPE(ewald_pw_type), POINTER                       :: ewald_pw
     117             :       TYPE(section_vals_type), POINTER                   :: ewald_section, poisson_section, &
     118             :                                                             print_section
     119             : 
     120         402 :       CALL timeset(routineN, handle)
     121             : 
     122         402 :       do_coulomb = .NOT. tddfpt_control%rks_triplets
     123         402 :       IF (do_coulomb) THEN
     124             :          ! calculate exchange gamma matrix
     125         308 :          CALL setup_gamma(qs_env, stda_kernel, sub_env, work%gamma_exchange)
     126             :       END IF
     127             : 
     128             :       ! calculate S_half and Lowdin MO coefficients
     129         402 :       CALL get_lowdin_mo_coefficients(qs_env, sub_env, work)
     130             : 
     131             :       ! initialize Ewald for sTDA
     132         402 :       IF (tddfpt_control%stda_control%do_ewald) THEN
     133          94 :          NULLIFY (ewald_env, ewald_pw)
     134        1692 :          ALLOCATE (ewald_env)
     135          94 :          CALL ewald_env_create(ewald_env, sub_env%para_env)
     136          94 :          poisson_section => section_vals_get_subs_vals(qs_env%input, "DFT%POISSON")
     137          94 :          CALL ewald_env_set(ewald_env, poisson_section=poisson_section)
     138          94 :          ewald_section => section_vals_get_subs_vals(poisson_section, "EWALD")
     139          94 :          print_section => section_vals_get_subs_vals(qs_env%input, "PRINT%GRID_INFORMATION")
     140          94 :          CALL get_qs_env(qs_env, cell=cell, cell_ref=cell_ref)
     141          94 :          CALL read_ewald_section_tb(ewald_env, ewald_section, cell_ref%hmat)
     142          94 :          ALLOCATE (ewald_pw)
     143          94 :          CALL ewald_pw_create(ewald_pw, ewald_env, cell, cell_ref, print_section=print_section)
     144          94 :          work%ewald_env => ewald_env
     145          94 :          work%ewald_pw => ewald_pw
     146             :       END IF
     147             : 
     148         402 :       CALL timestop(handle)
     149             : 
     150         402 :    END SUBROUTINE stda_init_matrices
     151             : ! **************************************************************************************************
     152             : !> \brief Calculate sTDA exchange-type contributions
     153             : !> \param qs_env ...
     154             : !> \param stda_env ...
     155             : !> \param sub_env ...
     156             : !> \param gamma_matrix sTDA exchange-type contributions
     157             : !> \param ndim ...
     158             : !> \note  Note the specific sTDA notation exchange-type integrals (ia|jb) refer to Coulomb interaction
     159             : ! **************************************************************************************************
     160         476 :    SUBROUTINE setup_gamma(qs_env, stda_env, sub_env, gamma_matrix, ndim)
     161             : 
     162             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     163             :       TYPE(stda_env_type)                                :: stda_env
     164             :       TYPE(tddfpt_subgroup_env_type), INTENT(in)         :: sub_env
     165             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: gamma_matrix
     166             :       INTEGER, INTENT(IN), OPTIONAL                      :: ndim
     167             : 
     168             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'setup_gamma'
     169             :       REAL(KIND=dp), PARAMETER                           :: rsmooth = 1.0_dp
     170             : 
     171             :       INTEGER                                            :: handle, i, iatom, icol, ikind, imat, &
     172             :                                                             irow, jatom, jkind, natom, nmat
     173         476 :       INTEGER, DIMENSION(:), POINTER                     :: row_blk_sizes
     174             :       LOGICAL                                            :: found
     175             :       REAL(KIND=dp)                                      :: dfcut, dgb, dr, eta, fcut, r, rcut, &
     176             :                                                             rcuta, rcutb, x
     177             :       REAL(KIND=dp), DIMENSION(3)                        :: rij
     178         476 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: dgblock, gblock
     179             :       TYPE(dbcsr_distribution_type), POINTER             :: dbcsr_dist
     180             :       TYPE(neighbor_list_iterator_p_type), &
     181         476 :          DIMENSION(:), POINTER                           :: nl_iterator
     182             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     183         476 :          POINTER                                         :: n_list
     184             : 
     185         476 :       CALL timeset(routineN, handle)
     186             : 
     187         476 :       CALL get_qs_env(qs_env=qs_env, natom=natom)
     188         476 :       dbcsr_dist => sub_env%dbcsr_dist
     189             :       ! Using the overlap list here can have a considerable effect on the number of
     190             :       ! terms calculated. This makes gamma also dependent on EPS_DEFAULT -> Overlap
     191         476 :       n_list => sub_env%sab_orb
     192             : 
     193         476 :       IF (PRESENT(ndim)) THEN
     194         168 :          nmat = ndim
     195             :       ELSE
     196         308 :          nmat = 1
     197             :       END IF
     198         476 :       CPASSERT(nmat == 1 .OR. nmat == 4)
     199         476 :       CPASSERT(.NOT. ASSOCIATED(gamma_matrix))
     200         476 :       CALL dbcsr_allocate_matrix_set(gamma_matrix, nmat)
     201             : 
     202        1428 :       ALLOCATE (row_blk_sizes(natom))
     203        3088 :       row_blk_sizes(1:natom) = 1
     204        1456 :       DO imat = 1, nmat
     205        1456 :          ALLOCATE (gamma_matrix(imat)%matrix)
     206             :       END DO
     207             : 
     208             :       CALL dbcsr_create(gamma_matrix(1)%matrix, name="gamma", dist=dbcsr_dist, &
     209             :                         matrix_type=dbcsr_type_symmetric, row_blk_size=row_blk_sizes, &
     210         476 :                         col_blk_size=row_blk_sizes, nze=0)
     211         980 :       DO imat = 2, nmat
     212             :          CALL dbcsr_create(gamma_matrix(imat)%matrix, name="dgamma", dist=dbcsr_dist, &
     213             :                            matrix_type=dbcsr_type_antisymmetric, row_blk_size=row_blk_sizes, &
     214         980 :                            col_blk_size=row_blk_sizes, nze=0)
     215             :       END DO
     216             : 
     217         476 :       DEALLOCATE (row_blk_sizes)
     218             : 
     219             :       ! setup the matrices using the neighbor list
     220        1456 :       DO imat = 1, nmat
     221         980 :          CALL cp_dbcsr_alloc_block_from_nbl(gamma_matrix(imat)%matrix, n_list)
     222        1456 :          CALL dbcsr_set(gamma_matrix(imat)%matrix, 0.0_dp)
     223             :       END DO
     224             : 
     225         476 :       NULLIFY (nl_iterator)
     226         476 :       CALL neighbor_list_iterator_create(nl_iterator, n_list)
     227       85622 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     228             :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, &
     229       85146 :                                 iatom=iatom, jatom=jatom, r=rij)
     230             : 
     231      340584 :          dr = SQRT(SUM(rij(:)**2)) ! interatomic distance
     232             : 
     233             :          eta = (stda_env%kind_param_set(ikind)%kind_param%hardness_param + &
     234       85146 :                 stda_env%kind_param_set(jkind)%kind_param%hardness_param)/2.0_dp
     235             : 
     236       85146 :          icol = MAX(iatom, jatom)
     237       85146 :          irow = MIN(iatom, jatom)
     238             : 
     239       85146 :          NULLIFY (gblock)
     240             :          CALL dbcsr_get_block_p(matrix=gamma_matrix(1)%matrix, &
     241       85146 :                                 row=irow, col=icol, BLOCK=gblock, found=found)
     242       85146 :          CPASSERT(found)
     243             : 
     244             :          ! get rcuta and rcutb
     245       85146 :          rcuta = stda_env%kind_param_set(ikind)%kind_param%rcut
     246       85146 :          rcutb = stda_env%kind_param_set(jkind)%kind_param%rcut
     247       85146 :          rcut = rcuta + rcutb
     248             : 
     249             :          !>   Computes the short-range gamma parameter from
     250             :          !>   Nataga-Mishimoto-Ohno-Klopman formula equivalently as it is done for xTB
     251       85146 :          IF (dr < 1.e-6) THEN
     252             :             ! on site terms
     253        3918 :             gblock(:, :) = gblock(:, :) + eta
     254       83840 :          ELSEIF (dr > rcut) THEN
     255             :             ! do nothing
     256             :          ELSE
     257       40075 :             IF (dr < rcut - rsmooth) THEN
     258             :                fcut = 1.0_dp
     259             :             ELSE
     260        8759 :                r = dr - (rcut - rsmooth)
     261        8759 :                x = r/rsmooth
     262        8759 :                fcut = -6._dp*x**5 + 15._dp*x**4 - 10._dp*x**3 + 1._dp
     263             :             END IF
     264             :             gblock(:, :) = gblock(:, :) + &
     265             :                            fcut*(1._dp/(dr**(stda_env%alpha_param) + eta**(-stda_env%alpha_param))) &
     266      120225 :                            **(1._dp/stda_env%alpha_param) - fcut/dr
     267             :          END IF
     268             : 
     269       85622 :          IF (nmat > 1) THEN
     270             :             !>   Computes the short-range gamma parameter from
     271             :             !>   Nataga-Mishimoto-Ohno-Klopman formula equivalently as it is done for xTB
     272             :             !>   Derivatives
     273       16212 :             IF (dr < 1.e-6 .OR. dr > rcut) THEN
     274             :                ! on site terms or beyond cutoff
     275             :                dgb = 0.0_dp
     276             :             ELSE
     277        8254 :                IF (dr < rcut - rsmooth) THEN
     278             :                   fcut = 1.0_dp
     279             :                   dfcut = 0.0_dp
     280             :                ELSE
     281        1824 :                   r = dr - (rcut - rsmooth)
     282        1824 :                   x = r/rsmooth
     283        1824 :                   fcut = -6._dp*x**5 + 15._dp*x**4 - 10._dp*x**3 + 1._dp
     284        1824 :                   dfcut = -30._dp*x**4 + 60._dp*x**3 - 30._dp*x**2
     285        1824 :                   dfcut = dfcut/rsmooth
     286             :                END IF
     287             :                dgb = dfcut*(1._dp/(dr**(stda_env%alpha_param) + eta**(-stda_env%alpha_param))) &
     288        8254 :                      **(1._dp/stda_env%alpha_param)
     289        8254 :                dgb = dgb - dfcut/dr + fcut/dr**2
     290             :                dgb = dgb - fcut*(1._dp/(dr**(stda_env%alpha_param) + eta**(-stda_env%alpha_param))) &
     291        8254 :                      **(1._dp/stda_env%alpha_param + 1._dp)*dr**(stda_env%alpha_param - 1._dp)
     292             :             END IF
     293       64848 :             DO imat = 2, nmat
     294       48636 :                NULLIFY (dgblock)
     295             :                CALL dbcsr_get_block_p(matrix=gamma_matrix(imat)%matrix, &
     296       48636 :                                       row=irow, col=icol, BLOCK=dgblock, found=found)
     297       64848 :                IF (found) THEN
     298       48636 :                   IF (dr > 1.e-6) THEN
     299       47583 :                      i = imat - 1
     300       47583 :                      IF (irow == iatom) THEN
     301       75348 :                         dgblock(:, :) = dgblock(:, :) + dgb*rij(i)/dr
     302             :                      ELSE
     303       67401 :                         dgblock(:, :) = dgblock(:, :) - dgb*rij(i)/dr
     304             :                      END IF
     305             :                   END IF
     306             :                END IF
     307             :             END DO
     308             :          END IF
     309             : 
     310             :       END DO
     311             : 
     312         476 :       CALL neighbor_list_iterator_release(nl_iterator)
     313             : 
     314        1456 :       DO imat = 1, nmat
     315        1456 :          CALL dbcsr_finalize(gamma_matrix(imat)%matrix)
     316             :       END DO
     317             : 
     318         476 :       CALL timestop(handle)
     319             : 
     320         476 :    END SUBROUTINE setup_gamma
     321             : 
     322             : ! **************************************************************************************************
     323             : !> \brief Calculate Lowdin MO coefficients
     324             : !> \param qs_env ...
     325             : !> \param sub_env ...
     326             : !> \param work ...
     327             : ! **************************************************************************************************
     328         408 :    SUBROUTINE get_lowdin_mo_coefficients(qs_env, sub_env, work)
     329             : 
     330             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     331             :       TYPE(tddfpt_subgroup_env_type), INTENT(in)         :: sub_env
     332             :       TYPE(tddfpt_work_matrices)                         :: work
     333             : 
     334             :       CHARACTER(len=*), PARAMETER :: routineN = 'get_lowdin_mo_coefficients'
     335             : 
     336             :       INTEGER                                            :: handle, i, iounit, ispin, j, &
     337             :                                                             max_iter_lanczos, nactive, ndep, nsgf, &
     338             :                                                             nspins, order_lanczos
     339             :       LOGICAL                                            :: converged
     340             :       REAL(KIND=dp)                                      :: eps_lanczos, sij, threshold
     341         408 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: slam
     342             :       REAL(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
     343         408 :          POINTER                                         :: local_data
     344             :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct
     345             :       TYPE(cp_fm_type)                                   :: fm_s_half, fm_work1
     346             :       TYPE(cp_logger_type), POINTER                      :: logger
     347         408 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrixkp_s
     348             :       TYPE(dbcsr_type)                                   :: sm_hinv
     349             :       TYPE(dbcsr_type), POINTER                          :: sm_h, sm_s
     350         408 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     351             :       TYPE(scf_control_type), POINTER                    :: scf_control
     352             : 
     353         408 :       CALL timeset(routineN, handle)
     354             : 
     355         408 :       NULLIFY (logger) !get output_unit
     356         408 :       logger => cp_get_default_logger()
     357         408 :       iounit = cp_logger_get_default_io_unit(logger)
     358             : 
     359             :       ! Calculate S^1/2 matrix
     360         408 :       IF (iounit > 0) THEN
     361         204 :          WRITE (iounit, "(1X,A)") "", &
     362         204 :             "-------------------------------------------------------------------------------", &
     363         204 :             "-                             Create Matrix SQRT(S)                           -", &
     364         408 :             "-------------------------------------------------------------------------------"
     365             :       END IF
     366             : 
     367         408 :       IF (sub_env%is_split) THEN
     368           0 :          CPABORT('SPLIT')
     369             :       ELSE
     370         408 :          CALL get_qs_env(qs_env=qs_env, matrix_s_kp=matrixkp_s)
     371         408 :          CPASSERT(ASSOCIATED(matrixkp_s))
     372         408 :          IF (SIZE(matrixkp_s, 2) > 1) CPWARN("not implemented for k-points.")
     373         408 :          sm_s => matrixkp_s(1, 1)%matrix
     374             :       END IF
     375         408 :       sm_h => work%shalf
     376             : 
     377         408 :       CALL dbcsr_create(sm_hinv, template=sm_s)
     378         408 :       CALL dbcsr_add_on_diag(sm_h, 1.0_dp)
     379         408 :       threshold = 1.0e-8_dp
     380         408 :       order_lanczos = 3
     381         408 :       eps_lanczos = 1.0e-4_dp
     382         408 :       max_iter_lanczos = 40
     383             :       CALL matrix_sqrt_Newton_Schulz(sm_h, sm_hinv, sm_s, &
     384             :                                      threshold, order_lanczos, eps_lanczos, max_iter_lanczos, &
     385         408 :                                      converged=converged)
     386         408 :       CALL dbcsr_release(sm_hinv)
     387             :       !
     388         408 :       NULLIFY (qs_kind_set)
     389         408 :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set)
     390             :       ! Get the total number of contracted spherical Gaussian basis functions
     391         408 :       CALL get_qs_kind_set(qs_kind_set, nsgf=nsgf)
     392             :       !
     393         408 :       IF (.NOT. converged) THEN
     394           0 :          IF (iounit > 0) THEN
     395           0 :             WRITE (iounit, "(T3,A)") "STDA| Newton-Schulz iteration did not converge"
     396           0 :             WRITE (iounit, "(T3,A)") "STDA| Calculate SQRT(S) from diagonalization"
     397             :          END IF
     398           0 :          CALL get_qs_env(qs_env=qs_env, scf_control=scf_control)
     399             :          ! Provide full size work matrices
     400             :          CALL cp_fm_struct_create(fmstruct=fmstruct, &
     401             :                                   para_env=sub_env%para_env, &
     402             :                                   context=sub_env%blacs_env, &
     403             :                                   nrow_global=nsgf, &
     404           0 :                                   ncol_global=nsgf)
     405           0 :          CALL cp_fm_create(matrix=fm_s_half, matrix_struct=fmstruct, name="S^(1/2) MATRIX")
     406           0 :          CALL cp_fm_create(matrix=fm_work1, matrix_struct=fmstruct, name="TMP MATRIX")
     407           0 :          CALL cp_fm_struct_release(fmstruct=fmstruct)
     408           0 :          CALL copy_dbcsr_to_fm(sm_s, fm_s_half)
     409           0 :          CALL cp_fm_power(fm_s_half, fm_work1, 0.5_dp, scf_control%eps_eigval, ndep)
     410           0 :          IF (ndep /= 0) &
     411             :             CALL cp_warn(__LOCATION__, &
     412             :                          "Overlap matrix exhibits linear dependencies. At least some "// &
     413           0 :                          "eigenvalues have been quenched.")
     414           0 :          CALL copy_fm_to_dbcsr(fm_s_half, sm_h)
     415           0 :          CALL cp_fm_release(fm_s_half)
     416           0 :          CALL cp_fm_release(fm_work1)
     417           0 :          IF (iounit > 0) WRITE (iounit, *)
     418             :       END IF
     419             : 
     420         408 :       nspins = SIZE(sub_env%mos_occ)
     421             : 
     422         848 :       DO ispin = 1, nspins
     423         440 :          CALL cp_fm_get_info(work%ctransformed(ispin), ncol_global=nactive)
     424             :          CALL cp_dbcsr_sm_fm_multiply(work%shalf, sub_env%mos_occ(ispin), &
     425         848 :                                       work%ctransformed(ispin), nactive, alpha=1.0_dp, beta=0.0_dp)
     426             :       END DO
     427             : 
     428             :       ! for Lowdin forces
     429         408 :       CALL cp_fm_create(matrix=fm_work1, matrix_struct=work%S_eigenvectors%matrix_struct, name="TMP MATRIX")
     430         408 :       CALL copy_dbcsr_to_fm(sm_s, fm_work1)
     431         408 :       CALL choose_eigv_solver(fm_work1, work%S_eigenvectors, work%S_eigenvalues)
     432         408 :       CALL cp_fm_release(fm_work1)
     433             :       !
     434        1224 :       ALLOCATE (slam(nsgf, 1))
     435        9546 :       DO i = 1, nsgf
     436        9546 :          IF (work%S_eigenvalues(i) > 0._dp) THEN
     437        9138 :             slam(i, 1) = SQRT(work%S_eigenvalues(i))
     438             :          ELSE
     439           0 :             CPABORT("S matrix not positive definit")
     440             :          END IF
     441             :       END DO
     442        9546 :       DO i = 1, nsgf
     443        9546 :          CALL cp_fm_set_submatrix(work%slambda, slam, 1, i, nsgf, 1, 1.0_dp, 0.0_dp)
     444             :       END DO
     445        9546 :       DO i = 1, nsgf
     446        9546 :          CALL cp_fm_set_submatrix(work%slambda, slam, i, 1, 1, nsgf, 1.0_dp, 1.0_dp, .TRUE.)
     447             :       END DO
     448         408 :       CALL cp_fm_get_info(work%slambda, local_data=local_data)
     449        9546 :       DO i = 1, SIZE(local_data, 2)
     450      420781 :          DO j = 1, SIZE(local_data, 1)
     451      411235 :             sij = local_data(j, i)
     452      411235 :             IF (sij > 0.0_dp) sij = 1.0_dp/sij
     453      420373 :             local_data(j, i) = sij
     454             :          END DO
     455             :       END DO
     456         408 :       DEALLOCATE (slam)
     457             : 
     458         408 :       CALL timestop(handle)
     459             : 
     460        1224 :    END SUBROUTINE get_lowdin_mo_coefficients
     461             : 
     462             : ! **************************************************************************************************
     463             : !> \brief Calculate Lowdin transformed Davidson trial vector X
     464             : !>        shalf (dbcsr), xvec, xt (fm) are defined in the same sub_env
     465             : !> \param shalf ...
     466             : !> \param xvec ...
     467             : !> \param xt ...
     468             : ! **************************************************************************************************
     469        7330 :    SUBROUTINE get_lowdin_x(shalf, xvec, xt)
     470             : 
     471             :       TYPE(dbcsr_type)                                   :: shalf
     472             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: xvec, xt
     473             : 
     474             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'get_lowdin_x'
     475             : 
     476             :       INTEGER                                            :: handle, ispin, nactive, nspins
     477             : 
     478        7330 :       CALL timeset(routineN, handle)
     479             : 
     480        7330 :       nspins = SIZE(xvec)
     481             : 
     482             :       ! Build Lowdin transformed tilde(X)= S^1/2 X for each spin
     483       15490 :       DO ispin = 1, nspins
     484        8160 :          CALL cp_fm_get_info(xt(ispin), ncol_global=nactive)
     485             :          CALL cp_dbcsr_sm_fm_multiply(shalf, xvec(ispin), &
     486       15490 :                                       xt(ispin), nactive, alpha=1.0_dp, beta=0.0_dp)
     487             :       END DO
     488             : 
     489        7330 :       CALL timestop(handle)
     490             : 
     491        7330 :    END SUBROUTINE get_lowdin_x
     492             : 
     493             : ! **************************************************************************************************
     494             : !> \brief ...Calculate the sTDA kernel contribution by contracting the Lowdin MO coefficients --
     495             : !>           transition charges with the Coulomb-type or exchange-type integrals
     496             : !> \param qs_env ...
     497             : !> \param stda_control ...
     498             : !> \param stda_env ...
     499             : !> \param sub_env ...
     500             : !> \param work ...
     501             : !> \param is_rks_triplets ...
     502             : !> \param X ...
     503             : !> \param res ... vector AX with A being the sTDA matrix and X the Davidson trial vector of the
     504             : !>                eigenvalue problem A*X = omega*X
     505             : ! **************************************************************************************************
     506        7088 :    SUBROUTINE stda_calculate_kernel(qs_env, stda_control, stda_env, sub_env, &
     507        7088 :                                     work, is_rks_triplets, X, res)
     508             : 
     509             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     510             :       TYPE(stda_control_type)                            :: stda_control
     511             :       TYPE(stda_env_type)                                :: stda_env
     512             :       TYPE(tddfpt_subgroup_env_type)                     :: sub_env
     513             :       TYPE(tddfpt_work_matrices)                         :: work
     514             :       LOGICAL, INTENT(IN)                                :: is_rks_triplets
     515             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: X, res
     516             : 
     517             :       CHARACTER(len=*), PARAMETER :: routineN = 'stda_calculate_kernel'
     518             : 
     519             :       INTEGER                                            :: blk, ewald_type, handle, ia, iatom, &
     520             :                                                             ikind, is, ispin, jatom, jkind, jspin, &
     521             :                                                             natom, nsgf, nspins
     522        7088 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: first_sgf, kind_of, last_sgf
     523             :       INTEGER, DIMENSION(2)                              :: nactive, nlim
     524             :       LOGICAL                                            :: calculate_forces, do_coulomb, do_ewald, &
     525             :                                                             do_exchange, use_virial
     526             :       REAL(KIND=dp)                                      :: alpha, bp, dr, eta, gabr, hfx, rbeta, &
     527             :                                                             spinfac
     528        7088 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: tcharge, tv
     529        7088 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: gtcharge
     530             :       REAL(KIND=dp), DIMENSION(3)                        :: rij
     531        7088 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: gab, pblock
     532        7088 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     533             :       TYPE(cell_type), POINTER                           :: cell
     534             :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct, fmstructjspin
     535             :       TYPE(cp_fm_type)                                   :: cvec, cvecjspin
     536        7088 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: xtransformed
     537             :       TYPE(cp_fm_type), POINTER                          :: ct, ctjspin
     538             :       TYPE(dbcsr_iterator_type)                          :: iter
     539             :       TYPE(dbcsr_type)                                   :: pdens
     540             :       TYPE(dbcsr_type), POINTER                          :: tempmat
     541             :       TYPE(ewald_environment_type), POINTER              :: ewald_env
     542             :       TYPE(ewald_pw_type), POINTER                       :: ewald_pw
     543             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     544             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     545        7088 :          POINTER                                         :: n_list
     546        7088 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     547        7088 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     548             :       TYPE(virial_type), POINTER                         :: virial
     549             : 
     550        7088 :       CALL timeset(routineN, handle)
     551             : 
     552       21264 :       nactive(:) = stda_env%nactive(:)
     553        7088 :       nspins = SIZE(X)
     554        7088 :       spinfac = 2.0_dp
     555        7088 :       IF (nspins == 2) spinfac = 1.0_dp
     556             : 
     557        6284 :       IF (nspins == 1 .AND. is_rks_triplets) THEN
     558             :          do_coulomb = .FALSE.
     559             :       ELSE
     560             :          do_coulomb = .TRUE.
     561             :       END IF
     562        7088 :       do_ewald = stda_control%do_ewald
     563        7088 :       do_exchange = stda_control%do_exchange
     564             : 
     565        7088 :       para_env => sub_env%para_env
     566             : 
     567             :       CALL get_qs_env(qs_env, natom=natom, cell=cell, &
     568        7088 :                       particle_set=particle_set, qs_kind_set=qs_kind_set)
     569       21264 :       ALLOCATE (first_sgf(natom))
     570       14176 :       ALLOCATE (last_sgf(natom))
     571        7088 :       CALL get_particle_set(particle_set, qs_kind_set, first_sgf=first_sgf, last_sgf=last_sgf)
     572             : 
     573             :       ! calculate Loewdin transformed Davidson trial vector tilde(X)=S^1/2*X
     574             :       ! and tilde(tilde(X))=S^1/2_A*tilde(X)_A
     575       29156 :       ALLOCATE (xtransformed(nspins))
     576       14980 :       DO ispin = 1, nspins
     577        7892 :          NULLIFY (fmstruct)
     578        7892 :          ct => work%ctransformed(ispin)
     579        7892 :          CALL cp_fm_get_info(ct, matrix_struct=fmstruct)
     580       14980 :          CALL cp_fm_create(matrix=xtransformed(ispin), matrix_struct=fmstruct, name="XTRANSFORMED")
     581             :       END DO
     582        7088 :       CALL get_lowdin_x(work%shalf, X, xtransformed)
     583             : 
     584       28352 :       ALLOCATE (tcharge(natom), gtcharge(natom, 1))
     585             : 
     586       14980 :       DO ispin = 1, nspins
     587       14980 :          CALL cp_fm_set_all(res(ispin), 0.0_dp)
     588             :       END DO
     589             : 
     590       14980 :       DO ispin = 1, nspins
     591        7892 :          ct => work%ctransformed(ispin)
     592        7892 :          CALL cp_fm_get_info(ct, matrix_struct=fmstruct, nrow_global=nsgf)
     593       23676 :          ALLOCATE (tv(nsgf))
     594        7892 :          CALL cp_fm_create(cvec, fmstruct)
     595             :          !
     596             :          ! *** Coulomb contribution
     597             :          !
     598        7892 :          IF (do_coulomb) THEN
     599       59286 :             tcharge(:) = 0.0_dp
     600       13392 :             DO jspin = 1, nspins
     601        7500 :                ctjspin => work%ctransformed(jspin)
     602        7500 :                CALL cp_fm_get_info(ctjspin, matrix_struct=fmstructjspin)
     603        7500 :                CALL cp_fm_get_info(ctjspin, matrix_struct=fmstructjspin, nrow_global=nsgf)
     604        7500 :                CALL cp_fm_create(cvecjspin, fmstructjspin)
     605             :                ! CV(mu,j) = CT(mu,j)*XT(mu,j)
     606        7500 :                CALL cp_fm_schur_product(ctjspin, xtransformed(jspin), cvecjspin)
     607             :                ! TV(mu) = SUM_j CV(mu,j)
     608        7500 :                CALL cp_fm_vectorssum(cvecjspin, tv, "R")
     609             :                ! contract charges
     610             :                ! TC(a) = SUM_(mu of a) TV(mu)
     611       65766 :                DO ia = 1, natom
     612      293674 :                   DO is = first_sgf(ia), last_sgf(ia)
     613      286174 :                      tcharge(ia) = tcharge(ia) + tv(is)
     614             :                   END DO
     615             :                END DO
     616       20892 :                CALL cp_fm_release(cvecjspin)
     617             :             END DO !jspin
     618             :             ! Apply tcharge*gab -> gtcharge
     619             :             ! gT(b) = SUM_a g(a,b)*TC(a)
     620             :             ! gab = work%gamma_exchange(1)%matrix
     621       65178 :             gtcharge = 0.0_dp
     622             :             ! short range contribution
     623        5892 :             tempmat => work%gamma_exchange(1)%matrix
     624        5892 :             CALL dbcsr_iterator_start(iter, tempmat)
     625      903478 :             DO WHILE (dbcsr_iterator_blocks_left(iter))
     626      897586 :                CALL dbcsr_iterator_next_block(iter, iatom, jatom, gab, blk)
     627      897586 :                gtcharge(iatom, 1) = gtcharge(iatom, 1) + gab(1, 1)*tcharge(jatom)
     628      903478 :                IF (iatom /= jatom) THEN
     629      870889 :                   gtcharge(jatom, 1) = gtcharge(jatom, 1) + gab(1, 1)*tcharge(iatom)
     630             :                END IF
     631             :             END DO
     632        5892 :             CALL dbcsr_iterator_stop(iter)
     633             :             ! Ewald long range contribution
     634        5892 :             IF (do_ewald) THEN
     635         824 :                ewald_env => work%ewald_env
     636         824 :                ewald_pw => work%ewald_pw
     637         824 :                CALL ewald_env_get(ewald_env, alpha=alpha, ewald_type=ewald_type)
     638         824 :                CALL get_qs_env(qs_env=qs_env, virial=virial)
     639         824 :                use_virial = .FALSE.
     640         824 :                calculate_forces = .FALSE.
     641         824 :                n_list => sub_env%sab_orb
     642         824 :                CALL tb_ewald_overlap(gtcharge, tcharge, alpha, n_list, virial, use_virial)
     643             :                CALL tb_spme_evaluate(ewald_env, ewald_pw, particle_set, cell, &
     644         824 :                                      gtcharge, tcharge, calculate_forces, virial, use_virial)
     645             :                ! add self charge interaction contribution
     646         824 :                IF (para_env%is_source()) THEN
     647       19360 :                   gtcharge(:, 1) = gtcharge(:, 1) - 2._dp*alpha*oorootpi*tcharge(:)
     648             :                END IF
     649             :             ELSE
     650        5068 :                nlim = get_limit(natom, para_env%num_pe, para_env%mepos)
     651       12817 :                DO iatom = nlim(1), nlim(2)
     652       20860 :                   DO jatom = 1, iatom - 1
     653       32172 :                      rij = particle_set(iatom)%r - particle_set(jatom)%r
     654       32172 :                      rij = pbc(rij, cell)
     655       32172 :                      dr = SQRT(SUM(rij(:)**2))
     656       15792 :                      IF (dr > 1.e-6_dp) THEN
     657        8043 :                         gtcharge(iatom, 1) = gtcharge(iatom, 1) + tcharge(jatom)/dr
     658        8043 :                         gtcharge(jatom, 1) = gtcharge(jatom, 1) + tcharge(iatom)/dr
     659             :                      END IF
     660             :                   END DO
     661             :                END DO
     662             :             END IF
     663        5892 :             CALL para_env%sum(gtcharge)
     664             :             ! expand charges
     665             :             ! TV(mu) = TC(a of mu)
     666      199672 :             tv(1:nsgf) = 0.0_dp
     667       59286 :             DO ia = 1, natom
     668      253066 :                DO is = first_sgf(ia), last_sgf(ia)
     669      247174 :                   tv(is) = gtcharge(ia, 1)
     670             :                END DO
     671             :             END DO
     672             :             ! CV(mu,i) = TV(mu)*CV(mu,i)
     673        5892 :             ct => work%ctransformed(ispin)
     674        5892 :             CALL cp_fm_to_fm(ct, cvec)
     675        5892 :             CALL cp_fm_row_scale(cvec, tv)
     676             :             ! rho(nu,i) = rho(nu,i) + Shalf(nu,mu)*CV(mu,i)
     677        5892 :             CALL cp_dbcsr_sm_fm_multiply(work%shalf, cvec, res(ispin), nactive(ispin), spinfac, 1.0_dp)
     678             :          END IF
     679             :          !
     680             :          ! *** Exchange contribution
     681             :          !
     682        7892 :          IF (do_exchange) THEN ! option to explicitly switch off exchange
     683             :             ! (exchange contributes also if hfx_fraction=0)
     684        7294 :             CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set)
     685        7294 :             CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, kind_of=kind_of)
     686             :             !
     687        7294 :             tempmat => work%shalf
     688        7294 :             CALL dbcsr_create(pdens, template=tempmat, matrix_type=dbcsr_type_no_symmetry)
     689             :             ! P(nu,mu) = SUM_j XT(nu,j)*CT(mu,j)
     690        7294 :             ct => work%ctransformed(ispin)
     691        7294 :             CALL dbcsr_set(pdens, 0.0_dp)
     692             :             CALL cp_dbcsr_plus_fm_fm_t(pdens, xtransformed(ispin), ct, nactive(ispin), &
     693        7294 :                                        1.0_dp, keep_sparsity=.FALSE.)
     694        7294 :             CALL dbcsr_filter(pdens, stda_env%eps_td_filter)
     695             :             ! Apply PP*gab -> PP; gab = gamma_coulomb
     696             :             ! P(nu,mu) = P(nu,mu)*g(a of nu,b of mu)
     697        7294 :             bp = stda_env%beta_param
     698        7294 :             hfx = stda_env%hfx_fraction
     699        7294 :             CALL dbcsr_iterator_start(iter, pdens)
     700     1787011 :             DO WHILE (dbcsr_iterator_blocks_left(iter))
     701     1779717 :                CALL dbcsr_iterator_next_block(iter, iatom, jatom, pblock, blk)
     702     7118868 :                rij = particle_set(iatom)%r - particle_set(jatom)%r
     703     7118868 :                rij = pbc(rij, cell)
     704     7118868 :                dr = SQRT(SUM(rij(:)**2))
     705     1779717 :                ikind = kind_of(iatom)
     706     1779717 :                jkind = kind_of(jatom)
     707             :                eta = (stda_env%kind_param_set(ikind)%kind_param%hardness_param + &
     708     1779717 :                       stda_env%kind_param_set(jkind)%kind_param%hardness_param)/2.0_dp
     709     1779717 :                rbeta = dr**bp
     710     1779717 :                IF (hfx > 0.0_dp) THEN
     711     1777504 :                   gabr = (1._dp/(rbeta + (hfx*eta)**(-bp)))**(1._dp/bp)
     712             :                ELSE
     713        2213 :                   IF (dr < 1.e-6) THEN
     714             :                      gabr = 0.0_dp
     715             :                   ELSE
     716        1542 :                      gabr = 1._dp/dr
     717             :                   END IF
     718             :                END IF
     719    20067129 :                pblock = gabr*pblock
     720             :             END DO
     721        7294 :             CALL dbcsr_iterator_stop(iter)
     722             :             ! CV(mu,i) = P(nu,mu)*CT(mu,i)
     723        7294 :             CALL cp_dbcsr_sm_fm_multiply(pdens, ct, cvec, nactive(ispin), 1.0_dp, 0.0_dp)
     724             :             ! rho(nu,i) = rho(nu,i) + ShalfP(nu,mu)*CV(mu,i)
     725        7294 :             CALL cp_dbcsr_sm_fm_multiply(work%shalf, cvec, res(ispin), nactive(ispin), -1.0_dp, 1.0_dp)
     726             :             !
     727        7294 :             CALL dbcsr_release(pdens)
     728        7294 :             DEALLOCATE (kind_of)
     729             :          END IF
     730             :          !
     731        7892 :          CALL cp_fm_release(cvec)
     732       30764 :          DEALLOCATE (tv)
     733             :       END DO
     734             : 
     735        7088 :       CALL cp_fm_release(xtransformed)
     736        7088 :       DEALLOCATE (tcharge, gtcharge)
     737        7088 :       DEALLOCATE (first_sgf, last_sgf)
     738             : 
     739        7088 :       CALL timestop(handle)
     740             : 
     741       14176 :    END SUBROUTINE stda_calculate_kernel
     742             : 
     743             : ! **************************************************************************************************
     744             : 
     745             : END MODULE qs_tddfpt2_stda_utils

Generated by: LCOV version 1.15