LCOV - code coverage report
Current view: top level - src - lri_ks_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:42dac4a) Lines: 36.2 % 69 25
Test Date: 2025-07-25 12:55:17 Functions: 50.0 % 2 1

            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 routines that build the Kohn-Sham matrix for the LRIGPW
      10              : !>      and xc parts
      11              : !> \par History
      12              : !>      09.2013 created [Dorothea Golze]
      13              : !> \author Dorothea Golze
      14              : ! **************************************************************************************************
      15              : MODULE lri_ks_methods
      16              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      17              :                                               get_atomic_kind_set
      18              :    USE cp_dbcsr_api,                    ONLY: dbcsr_add,&
      19              :                                               dbcsr_finalize,&
      20              :                                               dbcsr_get_block_p,&
      21              :                                               dbcsr_p_type,&
      22              :                                               dbcsr_reserve_blocks,&
      23              :                                               dbcsr_type
      24              :    USE kinds,                           ONLY: dp
      25              :    USE lri_compression,                 ONLY: lri_decomp_i
      26              :    USE lri_environment_types,           ONLY: lri_environment_type,&
      27              :                                               lri_int_type,&
      28              :                                               lri_kind_type
      29              :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      30              :                                               neighbor_list_iterate,&
      31              :                                               neighbor_list_iterator_create,&
      32              :                                               neighbor_list_iterator_p_type,&
      33              :                                               neighbor_list_iterator_release,&
      34              :                                               neighbor_list_set_p_type
      35              :    USE qs_o3c_methods,                  ONLY: contract3_o3c
      36              :    USE qs_o3c_types,                    ONLY: get_o3c_vec,&
      37              :                                               o3c_vec_create,&
      38              :                                               o3c_vec_release,&
      39              :                                               o3c_vec_type
      40              :    USE ri_environment_methods,          ONLY: ri_metric_solver
      41              : 
      42              : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num
      43              : #include "./base/base_uses.f90"
      44              : 
      45              :    IMPLICIT NONE
      46              : 
      47              :    PRIVATE
      48              : 
      49              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'lri_ks_methods'
      50              : 
      51              :    PUBLIC :: calculate_lri_ks_matrix, calculate_ri_ks_matrix
      52              : 
      53              : CONTAINS
      54              : 
      55              : !*****************************************************************************
      56              : !> \brief update of LRIGPW KS matrix
      57              : !> \param lri_env ...
      58              : !> \param lri_v_int integrals of potential * ri basis set
      59              : !> \param h_matrix KS matrix, on entry containing the core hamiltonian
      60              : !> \param atomic_kind_set ...
      61              : !> \param cell_to_index ...
      62              : !> \note including this in lri_environment_methods?
      63              : ! **************************************************************************************************
      64          716 :    SUBROUTINE calculate_lri_ks_matrix(lri_env, lri_v_int, h_matrix, atomic_kind_set, cell_to_index)
      65              : 
      66              :       TYPE(lri_environment_type), POINTER                :: lri_env
      67              :       TYPE(lri_kind_type), DIMENSION(:), POINTER         :: lri_v_int
      68              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: h_matrix
      69              :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
      70              :       INTEGER, DIMENSION(:, :, :), OPTIONAL, POINTER     :: cell_to_index
      71              : 
      72              :       CHARACTER(*), PARAMETER :: routineN = 'calculate_lri_ks_matrix'
      73              : 
      74              :       INTEGER :: atom_a, atom_b, col, handle, i, iac, iatom, ic, ikind, ilist, jatom, jkind, &
      75              :          jneighbor, mepos, nba, nbb, nfa, nfb, nkind, nlist, nm, nn, nthread, row
      76          716 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind
      77              :       INTEGER, DIMENSION(3)                              :: cell
      78              :       LOGICAL                                            :: found, trans, use_cell_mapping
      79              :       REAL(KIND=dp)                                      :: dab, fw, isn, isna, isnb, rab(3), &
      80              :                                                             threshold
      81          716 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: vi, via, vib
      82          716 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: hf_work, hs_work, int3, wab, wbb
      83          716 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: h_block
      84              :       TYPE(dbcsr_type), POINTER                          :: hmat
      85              :       TYPE(lri_int_type), POINTER                        :: lrii
      86              :       TYPE(neighbor_list_iterator_p_type), &
      87          716 :          DIMENSION(:), POINTER                           :: nl_iterator
      88              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
      89          716 :          POINTER                                         :: soo_list
      90              : 
      91          716 :       CALL timeset(routineN, handle)
      92          716 :       NULLIFY (h_block, lrii, nl_iterator, soo_list)
      93              : 
      94          716 :       threshold = lri_env%eps_o3_int
      95              : 
      96          716 :       use_cell_mapping = (SIZE(h_matrix, 1) > 1)
      97          716 :       IF (use_cell_mapping) THEN
      98            6 :          CPASSERT(PRESENT(cell_to_index))
      99              :       END IF
     100              : 
     101          716 :       IF (ASSOCIATED(lri_env%soo_list)) THEN
     102          716 :          soo_list => lri_env%soo_list
     103              : 
     104          716 :          nkind = lri_env%lri_ints%nkind
     105              :          nthread = 1
     106          716 : !$       nthread = omp_get_max_threads()
     107              : 
     108          716 :          CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, atom_of_kind=atom_of_kind)
     109          716 :          CALL neighbor_list_iterator_create(nl_iterator, soo_list, nthread=nthread)
     110              : !$OMP PARALLEL DEFAULT(NONE)&
     111              : !$OMP SHARED (nthread,nl_iterator,nkind,atom_of_kind,threshold,lri_env,lri_v_int,&
     112              : !$OMP         h_matrix,use_cell_mapping,cell_to_index)&
     113              : !$OMP PRIVATE (mepos,ikind,jkind,iatom,jatom,nlist,ilist,jneighbor,rab,iac,dab,lrii,&
     114              : !$OMP          nfa,nfb,nba,nbb,nn,hs_work,hf_work,h_block,row,col,trans,found,wab,wbb,&
     115          716 : !$OMP          atom_a,atom_b,isn,nm,vi,isna,isnb,via,vib,fw,int3,cell,ic,hmat)
     116              : 
     117              :          mepos = 0
     118              : !$       mepos = omp_get_thread_num()
     119              : 
     120              :          DO WHILE (neighbor_list_iterate(nl_iterator, mepos) == 0)
     121              :             CALL get_iterator_info(nl_iterator, mepos=mepos, ikind=ikind, jkind=jkind, iatom=iatom, &
     122              :                                    jatom=jatom, nlist=nlist, ilist=ilist, inode=jneighbor, &
     123              :                                    r=rab, cell=cell)
     124              : 
     125              :             iac = ikind + nkind*(jkind - 1)
     126              :             dab = SQRT(SUM(rab*rab))
     127              : 
     128              :             IF (.NOT. ASSOCIATED(lri_env%lri_ints%lri_atom(iac)%lri_node)) CYCLE
     129              :             IF (lri_env%exact_1c_terms) THEN
     130              :                IF (iatom == jatom .AND. dab < lri_env%delta) CYCLE
     131              :             END IF
     132              : 
     133              :             lrii => lri_env%lri_ints%lri_atom(iac)%lri_node(ilist)%lri_int(jneighbor)
     134              : 
     135              :             nfa = lrii%nfa
     136              :             nfb = lrii%nfb
     137              :             nba = lrii%nba
     138              :             nbb = lrii%nbb
     139              :             nn = nfa + nfb
     140              : 
     141              :             atom_a = atom_of_kind(iatom)
     142              :             atom_b = atom_of_kind(jatom)
     143              : 
     144              :             IF (use_cell_mapping) THEN
     145              :                ic = cell_to_index(cell(1), cell(2), cell(3))
     146              :                CPASSERT(ic > 0)
     147              :             ELSE
     148              :                ic = 1
     149              :             END IF
     150              :             hmat => h_matrix(ic)%matrix
     151              : 
     152              :             ALLOCATE (int3(nba, nbb))
     153              :             IF (lrii%lrisr) THEN
     154              :                ALLOCATE (hs_work(nba, nbb))
     155              :                IF (iatom == jatom .AND. dab < lri_env%delta) THEN
     156              :                   nm = nfa
     157              :                   ALLOCATE (vi(nfa))
     158              :                   vi(1:nfa) = lri_v_int(ikind)%v_int(atom_a, 1:nfa)
     159              :                ELSE
     160              :                   nm = nn
     161              :                   ALLOCATE (vi(nn))
     162              :                   vi(1:nfa) = lri_v_int(ikind)%v_int(atom_a, 1:nfa)
     163              :                   vi(nfa + 1:nn) = lri_v_int(jkind)%v_int(atom_b, 1:nfb)
     164              :                END IF
     165              :                isn = SUM(lrii%sn(1:nm)*vi(1:nm))/lrii%nsn
     166              :                vi(1:nm) = MATMUL(lrii%sinv(1:nm, 1:nm), vi(1:nm)) - isn*lrii%sn(1:nm)
     167              :                hs_work(1:nba, 1:nbb) = isn*lrii%soo(1:nba, 1:nbb)
     168              :                IF (iatom == jatom .AND. dab < lri_env%delta) THEN
     169              :                   DO i = 1, nfa
     170              :                      CALL lri_decomp_i(int3, lrii%cabai, i)
     171              :                      hs_work(1:nba, 1:nbb) = hs_work(1:nba, 1:nbb) + vi(i)*int3(1:nba, 1:nbb)
     172              :                   END DO
     173              :                ELSE
     174              :                   DO i = 1, nfa
     175              :                      CALL lri_decomp_i(int3, lrii%cabai, i)
     176              :                      hs_work(1:nba, 1:nbb) = hs_work(1:nba, 1:nbb) + vi(i)*int3(1:nba, 1:nbb)
     177              :                   END DO
     178              :                   DO i = 1, nfb
     179              :                      CALL lri_decomp_i(int3, lrii%cabbi, i)
     180              :                      hs_work(1:nba, 1:nbb) = hs_work(1:nba, 1:nbb) + vi(nfa + i)*int3(1:nba, 1:nbb)
     181              :                   END DO
     182              :                END IF
     183              :                DEALLOCATE (vi)
     184              :             END IF
     185              : 
     186              :             IF (lrii%lriff) THEN
     187              :                ALLOCATE (hf_work(nba, nbb), wab(nba, nbb), wbb(nba, nbb))
     188              :                wab(1:nba, 1:nbb) = lri_env%wmat(ikind, jkind)%mat(1:nba, 1:nbb)
     189              :                wbb(1:nba, 1:nbb) = 1.0_dp - lri_env%wmat(ikind, jkind)%mat(1:nba, 1:nbb)
     190              :                !
     191              :                ALLOCATE (via(nfa), vib(nfb))
     192              :                via(1:nfa) = lri_v_int(ikind)%v_int(atom_a, 1:nfa)
     193              :                vib(1:nfb) = lri_v_int(jkind)%v_int(atom_b, 1:nfb)
     194              :                !
     195              :                isna = SUM(lrii%sna(1:nfa)*via(1:nfa))/lrii%nsna
     196              :                isnb = SUM(lrii%snb(1:nfb)*vib(1:nfb))/lrii%nsnb
     197              :                via(1:nfa) = MATMUL(lrii%asinv(1:nfa, 1:nfa), via(1:nfa)) - isna*lrii%sna(1:nfa)
     198              :                vib(1:nfb) = MATMUL(lrii%bsinv(1:nfb, 1:nfb), vib(1:nfb)) - isnb*lrii%snb(1:nfb)
     199              :                !
     200              :                hf_work(1:nba, 1:nbb) = (isna*wab(1:nba, 1:nbb) + isnb*wbb(1:nba, 1:nbb))*lrii%soo(1:nba, 1:nbb)
     201              :                !
     202              :                DO i = 1, nfa
     203              :                   IF (lrii%abascr(i) > threshold) THEN
     204              :                      CALL lri_decomp_i(int3, lrii%cabai, i)
     205              :                      hf_work(1:nba, 1:nbb) = hf_work(1:nba, 1:nbb) + &
     206              :                                              via(i)*int3(1:nba, 1:nbb)*wab(1:nba, 1:nbb)
     207              :                   END IF
     208              :                END DO
     209              :                DO i = 1, nfb
     210              :                   IF (lrii%abbscr(i) > threshold) THEN
     211              :                      CALL lri_decomp_i(int3, lrii%cabbi, i)
     212              :                      hf_work(1:nba, 1:nbb) = hf_work(1:nba, 1:nbb) + &
     213              :                                              vib(i)*int3(1:nba, 1:nbb)*wbb(1:nba, 1:nbb)
     214              :                   END IF
     215              :                END DO
     216              :                !
     217              :                DEALLOCATE (via, vib, wab, wbb)
     218              :             END IF
     219              :             DEALLOCATE (int3)
     220              : 
     221              :             ! add h_work to core hamiltonian
     222              :             IF (iatom <= jatom) THEN
     223              :                row = iatom
     224              :                col = jatom
     225              :                trans = .FALSE.
     226              :             ELSE
     227              :                row = jatom
     228              :                col = iatom
     229              :                trans = .TRUE.
     230              :             END IF
     231              : !$OMP CRITICAL(addhamiltonian)
     232              :             NULLIFY (h_block)
     233              :             CALL dbcsr_get_block_p(hmat, row, col, h_block, found)
     234              :             IF (.NOT. ASSOCIATED(h_block)) THEN
     235              :                CALL dbcsr_reserve_blocks(hmat, rows=[row], cols=[col])
     236              :                CALL dbcsr_get_block_p(hmat, row, col, h_block, found)
     237              :             END IF
     238              :             IF (lrii%lrisr) THEN
     239              :                fw = lrii%wsr
     240              :                IF (trans) THEN
     241              :                   h_block(1:nbb, 1:nba) = h_block(1:nbb, 1:nba) + fw*TRANSPOSE(hs_work(1:nba, 1:nbb))
     242              :                ELSE
     243              :                   h_block(1:nba, 1:nbb) = h_block(1:nba, 1:nbb) + fw*hs_work(1:nba, 1:nbb)
     244              :                END IF
     245              :             END IF
     246              :             IF (lrii%lriff) THEN
     247              :                fw = lrii%wff
     248              :                IF (trans) THEN
     249              :                   h_block(1:nbb, 1:nba) = h_block(1:nbb, 1:nba) + fw*TRANSPOSE(hf_work(1:nba, 1:nbb))
     250              :                ELSE
     251              :                   h_block(1:nba, 1:nbb) = h_block(1:nba, 1:nbb) + fw*hf_work(1:nba, 1:nbb)
     252              :                END IF
     253              :             END IF
     254              : !$OMP END CRITICAL(addhamiltonian)
     255              : 
     256              :             IF (lrii%lrisr) DEALLOCATE (hs_work)
     257              :             IF (lrii%lriff) DEALLOCATE (hf_work)
     258              :          END DO
     259              : !$OMP END PARALLEL
     260              : 
     261         3574 :          DO ic = 1, SIZE(h_matrix, 1)
     262         3574 :             CALL dbcsr_finalize(h_matrix(ic)%matrix)
     263              :          END DO
     264              : 
     265          716 :          CALL neighbor_list_iterator_release(nl_iterator)
     266              : 
     267              :       END IF
     268              : 
     269          716 :       CALL timestop(handle)
     270              : 
     271         1432 :    END SUBROUTINE calculate_lri_ks_matrix
     272              : 
     273              : !*****************************************************************************
     274              : !> \brief update of RIGPW KS matrix
     275              : !> \param lri_env ...
     276              : !> \param lri_v_int integrals of potential * ri basis set
     277              : !> \param h_matrix KS matrix, on entry containing the core hamiltonian
     278              : !> \param s_matrix overlap matrix
     279              : !> \param atomic_kind_set ...
     280              : !> \param ispin ...
     281              : !> \note including this in lri_environment_methods?
     282              : ! **************************************************************************************************
     283            0 :    SUBROUTINE calculate_ri_ks_matrix(lri_env, lri_v_int, h_matrix, s_matrix, &
     284              :                                      atomic_kind_set, ispin)
     285              : 
     286              :       TYPE(lri_environment_type), POINTER                :: lri_env
     287              :       TYPE(lri_kind_type), DIMENSION(:), POINTER         :: lri_v_int
     288              :       TYPE(dbcsr_type), POINTER                          :: h_matrix, s_matrix
     289              :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     290              :       INTEGER, INTENT(IN)                                :: ispin
     291              : 
     292              :       CHARACTER(*), PARAMETER :: routineN = 'calculate_ri_ks_matrix'
     293              : 
     294              :       INTEGER                                            :: atom_a, handle, i1, i2, iatom, ikind, n, &
     295              :                                                             natom, nbas
     296            0 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind, kind_of, nsize
     297              :       INTEGER, DIMENSION(:, :), POINTER                  :: bas_ptr
     298              :       REAL(KIND=dp)                                      :: fscal, ftrm1n
     299            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: fout, fvec
     300            0 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: v
     301            0 :       TYPE(o3c_vec_type), DIMENSION(:), POINTER          :: o3c_vec
     302              : 
     303            0 :       CALL timeset(routineN, handle)
     304              : 
     305            0 :       bas_ptr => lri_env%ri_fit%bas_ptr
     306            0 :       natom = SIZE(bas_ptr, 2)
     307            0 :       nbas = bas_ptr(2, natom)
     308            0 :       ALLOCATE (fvec(nbas), fout(nbas))
     309            0 :       CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
     310            0 :       DO iatom = 1, natom
     311            0 :          ikind = kind_of(iatom)
     312            0 :          atom_a = atom_of_kind(iatom)
     313            0 :          i1 = bas_ptr(1, iatom)
     314            0 :          i2 = bas_ptr(2, iatom)
     315            0 :          n = i2 - i1 + 1
     316            0 :          fvec(i1:i2) = lri_v_int(ikind)%v_int(atom_a, 1:n)
     317              :       END DO
     318              :       ! f(T) * R^(-1)*n
     319            0 :       ftrm1n = SUM(fvec(:)*lri_env%ri_fit%rm1n(:))
     320            0 :       lri_env%ri_fit%ftrm1n(ispin) = ftrm1n
     321            0 :       fscal = ftrm1n/lri_env%ri_fit%ntrm1n
     322              :       ! renormalize fvec -> fvec - fscal * n
     323            0 :       fvec(:) = fvec(:) - fscal*lri_env%ri_fit%nvec(:)
     324              :       ! solve Rx=f'
     325              :       CALL ri_metric_solver(mat=lri_env%ri_smat(1)%matrix, &
     326              :                             vecr=fvec(:), &
     327              :                             vecx=fout(:), &
     328              :                             matp=lri_env%ri_sinv(1)%matrix, &
     329              :                             solver=lri_env%ri_sinv_app, &
     330            0 :                             ptr=bas_ptr)
     331            0 :       lri_env%ri_fit%fout(:, ispin) = fout(:)
     332              : 
     333              :       ! add overlap matrix contribution
     334            0 :       CALL dbcsr_add(h_matrix, s_matrix, 1.0_dp, fscal)
     335              : 
     336              :       ! create a o3c_vec from fout
     337            0 :       ALLOCATE (nsize(natom), o3c_vec(natom))
     338            0 :       DO iatom = 1, natom
     339            0 :          i1 = bas_ptr(1, iatom)
     340            0 :          i2 = bas_ptr(2, iatom)
     341            0 :          n = i2 - i1 + 1
     342            0 :          nsize(iatom) = n
     343              :       END DO
     344            0 :       CALL o3c_vec_create(o3c_vec, nsize)
     345            0 :       DEALLOCATE (nsize)
     346            0 :       DO iatom = 1, natom
     347            0 :          i1 = bas_ptr(1, iatom)
     348            0 :          i2 = bas_ptr(2, iatom)
     349            0 :          n = i2 - i1 + 1
     350            0 :          CALL get_o3c_vec(o3c_vec, iatom, v)
     351            0 :          v(1:n) = fout(i1:i2)
     352              :       END DO
     353              :       ! add <T.f'>
     354            0 :       CALL contract3_o3c(lri_env%o3c, o3c_vec, h_matrix)
     355              :       !
     356            0 :       CALL o3c_vec_release(o3c_vec)
     357            0 :       DEALLOCATE (o3c_vec, fvec, fout)
     358              : 
     359            0 :       CALL timestop(handle)
     360              : 
     361            0 :    END SUBROUTINE calculate_ri_ks_matrix
     362              : 
     363              : END MODULE lri_ks_methods
        

Generated by: LCOV version 2.0-1