LCOV - code coverage report
Current view: top level - src - gw_utils_compute_integrals.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:92574dc) Lines: 92.7 % 220 204
Test Date: 2026-09-24 01:27:39 Functions: 63.6 % 11 7

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Utility method to build 3-center integrals for small cell GW
      10              : ! **************************************************************************************************
      11              : MODULE gw_utils_compute_integrals
      12              :    USE OMP_LIB,                         ONLY: omp_get_thread_num
      13              :    USE ai_contraction_sphi,             ONLY: abc_contract_xsmm
      14              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      15              :                                               get_atomic_kind_set
      16              :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      17              :                                               gto_basis_set_p_type,&
      18              :                                               gto_basis_set_type
      19              :    USE cell_types,                      ONLY: cell_type,&
      20              :                                               get_cell,&
      21              :                                               pbc
      22              :    USE cp_array_utils,                  ONLY: cp_2d_r_p_type
      23              :    USE cp_files,                        ONLY: close_file,&
      24              :                                               open_file
      25              :    USE gamma,                           ONLY: init_md_ftable
      26              :    USE input_constants,                 ONLY: do_potential_coulomb,&
      27              :                                               do_potential_id,&
      28              :                                               do_potential_short,&
      29              :                                               do_potential_truncated
      30              :    USE kinds,                           ONLY: dp
      31              :    USE libint_2c_3c,                    ONLY: cutoff_screen_factor,&
      32              :                                               eri_3center,&
      33              :                                               libint_potential_type
      34              :    USE libint_wrapper,                  ONLY: cp_libint_cleanup_3eri,&
      35              :                                               cp_libint_init_3eri,&
      36              :                                               cp_libint_set_contrdepth,&
      37              :                                               cp_libint_t
      38              :    USE message_passing,                 ONLY: mp_para_env_type
      39              :    USE orbital_pointers,                ONLY: ncoset
      40              :    USE particle_types,                  ONLY: particle_type
      41              :    USE post_scf_bandstructure_types,    ONLY: post_scf_bandstructure_type
      42              :    USE qs_environment_types,            ONLY: get_qs_env,&
      43              :                                               qs_environment_type
      44              :    USE t_c_g0,                          ONLY: get_lmax_init,&
      45              :                                               init
      46              : 
      47              : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num
      48              : #include "./base/base_uses.f90"
      49              : 
      50              :    IMPLICIT NONE
      51              : 
      52              :    PRIVATE
      53              : 
      54              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_utils_compute_integrals'
      55              : 
      56              :    PUBLIC :: build_3c_integral_block, build_3c_integral_block_ctx, &
      57              :              gw_3c_ctx_type, gw_3c_ctx_create, gw_3c_ctx_release, &
      58              :              gw_3c_ws_type, gw_3c_ws_create, gw_3c_ws_release
      59              : 
      60              : ! **************************************************************************************************
      61              : !> \brief Shared read-only context for repeated 3-center integral block builds: screening
      62              : !>        parameters, basis maxima, contracted sphi tables, and the one-time gamma /
      63              : !>        truncated-Coulomb table initializations. Create and release OUTSIDE any OMP parallel
      64              : !>        region; creation is MPI-collective when the potential is truncated.
      65              : ! **************************************************************************************************
      66              :    TYPE gw_3c_ctx_type
      67              :       TYPE(libint_potential_type)                        :: potential_parameter = libint_potential_type()
      68              :       INTEGER                                            :: op_ij = do_potential_id, &
      69              :                                                             op_jk = do_potential_id
      70              :       REAL(KIND=dp)                                      :: dr_ij = 0.0_dp, dr_jk = 0.0_dp, &
      71              :                                                             dr_ik = 0.0_dp
      72              :       INTEGER                                            :: maxli = 0, maxlj = 0, maxlk = 0, &
      73              :                                                             max_am = 0, m_max = 0
      74              :       INTEGER                                            :: max_ncoi = 0, max_ncoj = 0, max_ncok = 0
      75              :       INTEGER                                            :: max_nsgfi = 0, max_nsgfj = 0, &
      76              :                                                             max_nsgfk = 0, max_nset = 0, natom = 0
      77              :       TYPE(cp_2d_r_p_type), DIMENSION(:, :), POINTER     :: spi => NULL(), tspj => NULL(), &
      78              :                                                             spk => NULL()
      79              :       TYPE(gto_basis_set_p_type), DIMENSION(:), ALLOCATABLE :: basis_i, basis_j, basis_k
      80              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: kind_of
      81              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set => NULL()
      82              :       TYPE(cell_type), POINTER                           :: cell => NULL()
      83              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: hmat = 0.0_dp
      84              :    END TYPE gw_3c_ctx_type
      85              : 
      86              : ! **************************************************************************************************
      87              : !> \brief Per-thread workspace for 3-center integral block builds: libint object + contraction
      88              : !>        buffers. Each thread creates its own (inside the parallel region is fine).
      89              : ! **************************************************************************************************
      90              :    TYPE gw_3c_ws_type
      91              :       TYPE(cp_libint_t), ALLOCATABLE                                  :: lib
      92              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: cpp_buffer, ccp_buffer
      93              :    END TYPE gw_3c_ws_type
      94              : 
      95              : CONTAINS
      96              : 
      97              : ! **************************************************************************************************
      98              : !> \brief Build the shared 3c-integral context from the band-structure environment and explicitly
      99              : !>        supplied potential and basis sets.
     100              : !> \param ctx ...
     101              : !> \param bs_env ...
     102              : !> \param potential_parameter ...
     103              : !> \param basis_j ...
     104              : !> \param basis_k ...
     105              : !> \param basis_i ...
     106              : ! **************************************************************************************************
     107          780 :    SUBROUTINE gw_3c_ctx_create(ctx, bs_env, potential_parameter, basis_j, basis_k, basis_i)
     108              :       TYPE(gw_3c_ctx_type), INTENT(OUT)                  :: ctx
     109              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     110              :       TYPE(libint_potential_type), INTENT(IN)            :: potential_parameter
     111              :       TYPE(gto_basis_set_p_type), DIMENSION(:)           :: basis_j, basis_k, basis_i
     112              : 
     113           60 :       CPASSERT(ASSOCIATED(bs_env%ri_rs%atomic_kind_set))
     114           60 :       CPASSERT(ASSOCIATED(bs_env%ri_rs%cell))
     115           60 :       CPASSERT(ASSOCIATED(bs_env%para_env))
     116           60 :       CPASSERT(ASSOCIATED(bs_env%ri_rs%particle_set))
     117              : 
     118              :       CALL gw_3c_ctx_create_core(ctx, potential_parameter, basis_j, basis_k, basis_i, &
     119              :                                  bs_env%ri_rs%atomic_kind_set, bs_env%ri_rs%cell, &
     120           60 :                                  bs_env%n_atom, bs_env%para_env, bs_env%ri_rs%particle_set)
     121           60 :    END SUBROUTINE gw_3c_ctx_create
     122              : 
     123              : ! **************************************************************************************************
     124              : !> \brief Build screening and contraction data shared by repeated 3c-integral block evaluations.
     125              : !> \param ctx ...
     126              : !> \param potential_parameter ...
     127              : !> \param basis_j ...
     128              : !> \param basis_k ...
     129              : !> \param basis_i ...
     130              : !> \param atomic_kind_set ...
     131              : !> \param cell ...
     132              : !> \param natom ...
     133              : !> \param para_env ...
     134              : !> \param particle_set ...
     135              : ! **************************************************************************************************
     136       181748 :    SUBROUTINE gw_3c_ctx_create_core(ctx, potential_parameter, basis_j, basis_k, basis_i, &
     137              :                                     atomic_kind_set, cell, natom, para_env, particle_set)
     138              :       TYPE(gw_3c_ctx_type), INTENT(OUT)                  :: ctx
     139              :       TYPE(libint_potential_type), INTENT(IN)            :: potential_parameter
     140              :       TYPE(gto_basis_set_p_type), DIMENSION(:)           :: basis_j, basis_k, basis_i
     141              :       TYPE(atomic_kind_type), DIMENSION(:), INTENT(IN), &
     142              :          POINTER                                         :: atomic_kind_set
     143              :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
     144              :       INTEGER, INTENT(IN)                                :: natom
     145              :       TYPE(mp_para_env_type), INTENT(IN), POINTER        :: para_env
     146              :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
     147              :          POINTER                                         :: particle_set
     148              : 
     149              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'gw_3c_ctx_create_core'
     150              : 
     151              :       INTEGER                                            :: egfi, handle, ibasis, ilist, imax, iset, &
     152              :                                                             jset, kset, l, nbasis, ncoi, npgf_l, &
     153              :                                                             sgfi, unit_id
     154        12982 :       INTEGER, DIMENSION(:), POINTER                     :: lmax_i, lmin_i, npgfi, npgfj, npgfk, &
     155        12982 :                                                             nsgfi, nsgfj, nsgfk
     156              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set
     157              : 
     158        12982 :       CALL timeset(routineN, handle)
     159              : 
     160        12982 :       ctx%potential_parameter = potential_parameter
     161        12982 :       ctx%op_ij = potential_parameter%potential_type
     162        12982 :       ctx%op_jk = do_potential_id
     163              : 
     164        12982 :       IF (ctx%op_ij == do_potential_truncated .OR. ctx%op_ij == do_potential_short) THEN
     165        12982 :          ctx%dr_ij = potential_parameter%cutoff_radius*cutoff_screen_factor
     166        12982 :          ctx%dr_ik = potential_parameter%cutoff_radius*cutoff_screen_factor
     167            0 :       ELSE IF (ctx%op_ij == do_potential_coulomb) THEN
     168            0 :          ctx%dr_ij = 1000000.0_dp
     169            0 :          ctx%dr_ik = 1000000.0_dp
     170              :       END IF
     171              : 
     172        12982 :       ctx%cell => cell
     173        12982 :       ctx%natom = natom
     174        12982 :       ctx%particle_set => particle_set
     175        12982 :       CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, kind_of=ctx%kind_of)
     176        12982 :       CALL get_cell(cell=ctx%cell, h=ctx%hmat)
     177              : 
     178        51802 :       ctx%basis_i = basis_i
     179        51802 :       ctx%basis_j = basis_j
     180        51802 :       ctx%basis_k = basis_k
     181              : 
     182              :       ! max l per basis for libint; max nset/nco/nsgf for the LIBXSMM contraction buffers
     183        12982 :       nbasis = SIZE(basis_i)
     184        38820 :       DO ibasis = 1, nbasis
     185              :          CALL get_gto_basis_set(gto_basis_set=basis_i(ibasis)%gto_basis_set, maxl=imax, &
     186        25838 :                                 lmax=lmax_i, lmin=lmin_i, nset=iset, nsgf_set=nsgfi, npgf=npgfi)
     187        25838 :          ctx%maxli = MAX(ctx%maxli, imax)
     188        25838 :          ctx%max_nset = MAX(ctx%max_nset, iset)
     189        66002 :          ctx%max_nsgfi = MAX(ctx%max_nsgfi, MAXVAL(nsgfi))
     190        66002 :          ctx%max_ncoi = MAX(ctx%max_ncoi, MAXVAL(npgfi)*ncoset(ctx%maxli))
     191       103716 :          DO l = 0, imax
     192        39058 :             npgf_l = 0
     193       109424 :             DO jset = 1, iset
     194       109424 :                IF (lmin_i(jset) == l .AND. lmax_i(jset) == l) npgf_l = npgf_l + npgfi(jset)
     195              :             END DO
     196        64896 :             ctx%max_ncoi = MAX(ctx%max_ncoi, npgf_l*ncoset(l))
     197              :          END DO
     198              :       END DO
     199        38820 :       DO ibasis = 1, nbasis
     200              :          CALL get_gto_basis_set(gto_basis_set=basis_j(ibasis)%gto_basis_set, maxl=imax, &
     201        25838 :                                 nset=jset, nsgf_set=nsgfj, npgf=npgfj)
     202        25838 :          ctx%maxlj = MAX(ctx%maxlj, imax)
     203        25838 :          ctx%max_nset = MAX(ctx%max_nset, jset)
     204        77640 :          ctx%max_nsgfj = MAX(ctx%max_nsgfj, MAXVAL(nsgfj))
     205       116460 :          ctx%max_ncoj = MAX(ctx%max_ncoj, MAXVAL(npgfj)*ncoset(ctx%maxlj))
     206              :       END DO
     207        38820 :       DO ibasis = 1, nbasis
     208              :          CALL get_gto_basis_set(gto_basis_set=basis_k(ibasis)%gto_basis_set, maxl=imax, &
     209        25838 :                                 nset=kset, nsgf_set=nsgfk, npgf=npgfk)
     210        25838 :          ctx%maxlk = MAX(ctx%maxlk, imax)
     211        25838 :          ctx%max_nset = MAX(ctx%max_nset, kset)
     212        77640 :          ctx%max_nsgfk = MAX(ctx%max_nsgfk, MAXVAL(nsgfk))
     213       116460 :          ctx%max_ncok = MAX(ctx%max_ncok, MAXVAL(npgfk)*ncoset(ctx%maxlk))
     214              :       END DO
     215        12982 :       ctx%m_max = ctx%maxli + ctx%maxlj + ctx%maxlk
     216        12982 :       ctx%max_am = MAX(ctx%maxli, ctx%maxlj, ctx%maxlk)
     217              : 
     218              :       ! contiguous (and for j transposed) sphi copies, shared read-only across threads
     219              :       ALLOCATE (ctx%spi(ctx%max_nset, nbasis), ctx%tspj(ctx%max_nset, nbasis), &
     220       443824 :                 ctx%spk(ctx%max_nset, nbasis))
     221        38820 :       DO ibasis = 1, nbasis
     222       117650 :          DO iset = 1, ctx%max_nset
     223        78830 :             NULLIFY (ctx%spi(iset, ibasis)%array)
     224        78830 :             NULLIFY (ctx%tspj(iset, ibasis)%array)
     225       104668 :             NULLIFY (ctx%spk(iset, ibasis)%array)
     226              :          END DO
     227              :       END DO
     228        51928 :       DO ilist = 1, 3
     229       129442 :          DO ibasis = 1, nbasis
     230        77514 :             IF (ilist == 1) basis_set => basis_i(ibasis)%gto_basis_set
     231        77514 :             IF (ilist == 2) basis_set => basis_j(ibasis)%gto_basis_set
     232        77514 :             IF (ilist == 3) basis_set => basis_k(ibasis)%gto_basis_set
     233       260228 :             DO iset = 1, basis_set%nset
     234       143768 :                ncoi = basis_set%npgf(iset)*ncoset(basis_set%lmax(iset))
     235       143768 :                sgfi = basis_set%first_sgf(1, iset)
     236       143768 :                egfi = sgfi + basis_set%nsgf_set(iset) - 1
     237       221282 :                IF (ilist == 1) THEN
     238       160656 :                   ALLOCATE (ctx%spi(iset, ibasis)%array(ncoi, basis_set%nsgf_set(iset)))
     239       346322 :                   ctx%spi(iset, ibasis)%array(:, :) = basis_set%sphi(1:ncoi, sgfi:egfi)
     240       103604 :                ELSE IF (ilist == 2) THEN
     241       207208 :                   ALLOCATE (ctx%tspj(iset, ibasis)%array(basis_set%nsgf_set(iset), ncoi))
     242      1646902 :                   ctx%tspj(iset, ibasis)%array(:, :) = TRANSPOSE(basis_set%sphi(1:ncoi, sgfi:egfi))
     243              :                ELSE
     244       207208 :                   ALLOCATE (ctx%spk(iset, ibasis)%array(ncoi, basis_set%nsgf_set(iset)))
     245      1402574 :                   ctx%spk(iset, ibasis)%array(:, :) = basis_set%sphi(1:ncoi, sgfi:egfi)
     246              :                END IF
     247              :             END DO
     248              :          END DO
     249              :       END DO
     250              : 
     251              :       ! one-time table inits; the truncated-Coulomb init reads a file + bcasts => MPI-collective,
     252              :       ! must happen here and never inside the per-block path or an OMP region
     253        12982 :       IF (ctx%op_ij == do_potential_truncated .OR. ctx%op_jk == do_potential_truncated) THEN
     254        12982 :          IF (ctx%m_max > get_lmax_init()) THEN
     255            0 :             IF (para_env%mepos == 0) THEN
     256            0 :                CALL open_file(unit_number=unit_id, file_name=potential_parameter%filename)
     257              :             END IF
     258            0 :             CALL init(ctx%m_max, unit_id, para_env%mepos, para_env)
     259            0 :             IF (para_env%mepos == 0) THEN
     260            0 :                CALL close_file(unit_id)
     261              :             END IF
     262              :          END IF
     263              :       END IF
     264        12982 :       CALL init_md_ftable(nmax=ctx%m_max)
     265              : 
     266        12982 :       CALL timestop(handle)
     267              : 
     268        25964 :    END SUBROUTINE gw_3c_ctx_create_core
     269              : 
     270              : ! **************************************************************************************************
     271              : !> \brief Releases the shared 3c-integral context.
     272              : !> \param ctx ...
     273              : ! **************************************************************************************************
     274        12982 :    SUBROUTINE gw_3c_ctx_release(ctx)
     275              : 
     276              :       TYPE(gw_3c_ctx_type), INTENT(INOUT)                :: ctx
     277              : 
     278              :       INTEGER                                            :: ibasis, iset
     279              : 
     280        52900 :       DO iset = 1, SIZE(ctx%spi, 1)
     281       131730 :          DO ibasis = 1, SIZE(ctx%spi, 2)
     282        78830 :             IF (ASSOCIATED(ctx%spi(iset, ibasis)%array)) DEALLOCATE (ctx%spi(iset, ibasis)%array)
     283        78830 :             IF (ASSOCIATED(ctx%tspj(iset, ibasis)%array)) DEALLOCATE (ctx%tspj(iset, ibasis)%array)
     284       118748 :             IF (ASSOCIATED(ctx%spk(iset, ibasis)%array)) DEALLOCATE (ctx%spk(iset, ibasis)%array)
     285              :          END DO
     286              :       END DO
     287        12982 :       DEALLOCATE (ctx%spi, ctx%tspj, ctx%spk)
     288        12982 :       NULLIFY (ctx%spi, ctx%tspj, ctx%spk, ctx%particle_set, ctx%cell)
     289        12982 :       IF (ALLOCATED(ctx%kind_of)) DEALLOCATE (ctx%kind_of)
     290        12982 :       IF (ALLOCATED(ctx%basis_i)) DEALLOCATE (ctx%basis_i)
     291        12982 :       IF (ALLOCATED(ctx%basis_j)) DEALLOCATE (ctx%basis_j)
     292        12982 :       IF (ALLOCATED(ctx%basis_k)) DEALLOCATE (ctx%basis_k)
     293              : 
     294        12982 :    END SUBROUTINE gw_3c_ctx_release
     295              : 
     296              : ! **************************************************************************************************
     297              : !> \brief Creates a per-thread 3c workspace: libint object + LIBXSMM contraction buffers.
     298              : !> \param ws ...
     299              : !> \param ctx ...
     300              : ! **************************************************************************************************
     301        12992 :    SUBROUTINE gw_3c_ws_create(ws, ctx)
     302              : 
     303              :       TYPE(gw_3c_ws_type), INTENT(OUT)                   :: ws
     304              :       TYPE(gw_3c_ctx_type), INTENT(IN)                   :: ctx
     305              : 
     306        12992 :       ALLOCATE (ws%lib)
     307        12992 :       CALL cp_libint_init_3eri(ws%lib, ctx%max_am)
     308        12992 :       CALL cp_libint_set_contrdepth(ws%lib, 1)
     309            0 :       ALLOCATE (ws%cpp_buffer(ctx%max_nsgfj*ctx%max_ncok), &
     310        64960 :                 ws%ccp_buffer(ctx%max_nsgfj*ctx%max_nsgfk*ctx%max_ncoi))
     311              : 
     312        12992 :    END SUBROUTINE gw_3c_ws_create
     313              : 
     314              : ! **************************************************************************************************
     315              : !> \brief Releases a per-thread 3c workspace.
     316              : !> \param ws ...
     317              : ! **************************************************************************************************
     318        12992 :    SUBROUTINE gw_3c_ws_release(ws)
     319              : 
     320              :       TYPE(gw_3c_ws_type), INTENT(INOUT)                 :: ws
     321              : 
     322        12992 :       CALL cp_libint_cleanup_3eri(ws%lib)
     323        12992 :       DEALLOCATE (ws%lib)
     324        12992 :       DEALLOCATE (ws%cpp_buffer, ws%ccp_buffer)
     325              : 
     326        12992 :    END SUBROUTINE gw_3c_ws_release
     327              : 
     328              : ! **************************************************************************************************
     329              : !> \brief Computes the 3c integral block (mu(atom_j) nu(atom_k) | P(atom_i)) for ONE atom triple,
     330              : !>        accumulating into the caller-zeroed int_3c at the given block offsets.
     331              : !>        Thread-safe: reads the frozen ctx + read-only module tables, mutates only its arguments
     332              : !>        and the per-thread ws.
     333              : !> \param int_3c pre-zeroed target; the triple's contribution is accumulated in place
     334              : !> \param ctx shared context from gw_3c_ctx_create
     335              : !> \param ws per-thread workspace from gw_3c_ws_create
     336              : !> \param atom_j ...
     337              : !> \param atom_k ...
     338              : !> \param atom_i ...
     339              : !> \param cell_j ...
     340              : !> \param cell_k ...
     341              : !> \param cell_i ...
     342              : !> \param j_offset block offset of atom_j's first sgf in int_3c dim 1 (default 0)
     343              : !> \param k_offset block offset of atom_k's first sgf in int_3c dim 2 (default 0)
     344              : !> \param i_offset block offset of atom_i's first RI sgf in int_3c dim 3 (default 0)
     345              : !> \param screened .TRUE. if the kind-radius screens killed the whole triple (int_3c untouched)
     346              : ! **************************************************************************************************
     347        13673 :    SUBROUTINE build_3c_integral_block_ctx(int_3c, ctx, ws, atom_j, atom_k, atom_i, &
     348              :                                           cell_j, cell_k, cell_i, &
     349              :                                           j_offset, k_offset, i_offset, screened)
     350              : 
     351              :       REAL(KIND=dp), DIMENSION(:, :, :)                  :: int_3c
     352              :       TYPE(gw_3c_ctx_type), INTENT(IN)                   :: ctx
     353              :       TYPE(gw_3c_ws_type), INTENT(INOUT)                 :: ws
     354              :       INTEGER, INTENT(IN)                                :: atom_j, atom_k, atom_i
     355              :       INTEGER, DIMENSION(3), INTENT(IN), OPTIONAL        :: cell_j, cell_k, cell_i
     356              :       INTEGER, INTENT(IN), OPTIONAL                      :: j_offset, k_offset, i_offset
     357              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: screened
     358              : 
     359              :       INTEGER :: block_end_i, block_end_j, block_end_k, block_start_i, block_start_j, &
     360              :          block_start_k, ikind, iset, jkind, jset, kkind, kset, my_i_offset, my_j_offset, &
     361              :          my_k_offset, ncoi, ncoj, ncok, nseti, nsetj, nsetk, sgfi, sgfj, sgfk
     362              :       INTEGER, DIMENSION(3)                              :: my_cell_i, my_cell_j, my_cell_k
     363        13673 :       INTEGER, DIMENSION(:), POINTER                     :: lmax_i, lmax_j, lmax_k, lmin_i, lmin_j, &
     364        13673 :                                                             lmin_k, npgfi, npgfj, npgfk, nsgfi, &
     365        13673 :                                                             nsgfj, nsgfk
     366        13673 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgf_i, first_sgf_j, first_sgf_k
     367              :       REAL(KIND=dp)                                      :: dij, dik, djk, kind_radius_i, &
     368              :                                                             kind_radius_j, kind_radius_k, sijk_ext
     369        13673 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: sijk, sijk_contr
     370              :       REAL(KIND=dp), DIMENSION(3)                        :: ri, rij, rik, rj, rjk, rk
     371        13673 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_i, set_radius_j, set_radius_k
     372        13673 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgf_i, rpgf_j, rpgf_k, zeti, zetj, zetk
     373              : 
     374          651 :       IF (PRESENT(screened)) screened = .FALSE.
     375              : 
     376        13673 :       my_cell_i(1:3) = 0
     377        13673 :       IF (PRESENT(cell_i)) my_cell_i(1:3) = cell_i(1:3)
     378        13673 :       my_cell_j(1:3) = 0
     379        13673 :       IF (PRESENT(cell_j)) my_cell_j(1:3) = cell_j(1:3)
     380        13673 :       my_cell_k(1:3) = 0
     381        13673 :       IF (PRESENT(cell_k)) my_cell_k(1:3) = cell_k(1:3)
     382        13673 :       my_i_offset = 0
     383        13673 :       IF (PRESENT(i_offset)) my_i_offset = i_offset
     384        13673 :       my_j_offset = 0
     385        13673 :       IF (PRESENT(j_offset)) my_j_offset = j_offset
     386        13673 :       my_k_offset = 0
     387        13673 :       IF (PRESENT(k_offset)) my_k_offset = k_offset
     388              : 
     389       273460 :       ri = pbc(ctx%particle_set(atom_i)%r(1:3), ctx%cell) + MATMUL(ctx%hmat, REAL(my_cell_i, dp))
     390       273460 :       rj = pbc(ctx%particle_set(atom_j)%r(1:3), ctx%cell) + MATMUL(ctx%hmat, REAL(my_cell_j, dp))
     391       273460 :       rk = pbc(ctx%particle_set(atom_k)%r(1:3), ctx%cell) + MATMUL(ctx%hmat, REAL(my_cell_k, dp))
     392              : 
     393        54692 :       rjk(1:3) = rk(1:3) - rj(1:3)
     394        54692 :       rij(1:3) = rj(1:3) - ri(1:3)
     395        54692 :       rik(1:3) = rk(1:3) - ri(1:3)
     396              : 
     397        54692 :       djk = NORM2(rjk)
     398        54692 :       dij = NORM2(rij)
     399        54692 :       dik = NORM2(rik)
     400              : 
     401        13673 :       ikind = ctx%kind_of(atom_i)
     402        13673 :       jkind = ctx%kind_of(atom_j)
     403        13673 :       kkind = ctx%kind_of(atom_k)
     404              : 
     405              :       CALL get_gto_basis_set(ctx%basis_i(ikind)%gto_basis_set, first_sgf=first_sgf_i, &
     406              :                              lmax=lmax_i, lmin=lmin_i, npgf=npgfi, nset=nseti, &
     407              :                              nsgf_set=nsgfi, pgf_radius=rpgf_i, set_radius=set_radius_i, &
     408        13673 :                              zet=zeti, kind_radius=kind_radius_i)
     409              :       CALL get_gto_basis_set(ctx%basis_j(jkind)%gto_basis_set, first_sgf=first_sgf_j, &
     410              :                              lmax=lmax_j, lmin=lmin_j, npgf=npgfj, nset=nsetj, &
     411              :                              nsgf_set=nsgfj, pgf_radius=rpgf_j, set_radius=set_radius_j, &
     412        13673 :                              zet=zetj, kind_radius=kind_radius_j)
     413              :       CALL get_gto_basis_set(ctx%basis_k(kkind)%gto_basis_set, first_sgf=first_sgf_k, &
     414              :                              lmax=lmax_k, lmin=lmin_k, npgf=npgfk, nset=nsetk, &
     415              :                              nsgf_set=nsgfk, pgf_radius=rpgf_k, set_radius=set_radius_k, &
     416        13673 :                              zet=zetk, kind_radius=kind_radius_k)
     417              : 
     418              :       IF (kind_radius_j + kind_radius_i + ctx%dr_ij < dij .OR. &
     419        13673 :           kind_radius_j + kind_radius_k + ctx%dr_jk < djk .OR. &
     420              :           kind_radius_k + kind_radius_i + ctx%dr_ik < dik) THEN
     421            0 :          IF (PRESENT(screened)) screened = .TRUE.
     422            0 :          RETURN
     423              :       END IF
     424              : 
     425        37803 :       DO iset = 1, nseti
     426        89242 :          DO jset = 1, nsetj
     427        51439 :             IF (set_radius_j(jset) + set_radius_i(iset) + ctx%dr_ij < dij) CYCLE
     428       183684 :             DO kset = 1, nsetk
     429       111859 :                IF (set_radius_j(jset) + set_radius_k(kset) + ctx%dr_jk < djk) CYCLE
     430       103759 :                IF (set_radius_k(kset) + set_radius_i(iset) + ctx%dr_ik < dik) CYCLE
     431              : 
     432        98217 :                ncoi = npgfi(iset)*ncoset(lmax_i(iset))
     433        98217 :                ncoj = npgfj(jset)*ncoset(lmax_j(jset))
     434        98217 :                ncok = npgfk(kset)*ncoset(lmax_k(kset))
     435              : 
     436        98217 :                sgfi = first_sgf_i(1, iset)
     437        98217 :                sgfj = first_sgf_j(1, jset)
     438        98217 :                sgfk = first_sgf_k(1, kset)
     439              : 
     440        98217 :                IF (ncoj*ncok*ncoi <= 0) CYCLE
     441       491085 :                ALLOCATE (sijk(ncoj, ncok, ncoi))
     442        98217 :                sijk(:, :, :) = 0.0_dp
     443              : 
     444              :                CALL eri_3center(sijk, &
     445              :                                 lmin_j(jset), lmax_j(jset), npgfj(jset), zetj(:, jset), &
     446              :                                 rpgf_j(:, jset), rj, &
     447              :                                 lmin_k(kset), lmax_k(kset), npgfk(kset), zetk(:, kset), &
     448              :                                 rpgf_k(:, kset), rk, &
     449              :                                 lmin_i(iset), lmax_i(iset), npgfi(iset), zeti(:, iset), &
     450              :                                 rpgf_i(:, iset), ri, &
     451              :                                 djk, dij, dik, ws%lib, ctx%potential_parameter, &
     452        98217 :                                 int_abc_ext=sijk_ext)
     453              : 
     454       491085 :                ALLOCATE (sijk_contr(nsgfj(jset), nsgfk(kset), nsgfi(iset)))
     455              :                CALL abc_contract_xsmm(sijk_contr, sijk, ctx%tspj(jset, jkind)%array, &
     456              :                                       ctx%spk(kset, kkind)%array, ctx%spi(iset, ikind)%array, &
     457              :                                       ncoj, ncok, ncoi, nsgfj(jset), nsgfk(kset), &
     458        98217 :                                       nsgfi(iset), ws%cpp_buffer, ws%ccp_buffer)
     459        98217 :                DEALLOCATE (sijk)
     460              : 
     461        98217 :                block_start_j = sgfj + my_j_offset
     462        98217 :                block_end_j = sgfj + nsgfj(jset) - 1 + my_j_offset
     463        98217 :                block_start_k = sgfk + my_k_offset
     464        98217 :                block_end_k = sgfk + nsgfk(kset) - 1 + my_k_offset
     465        98217 :                block_start_i = sgfi + my_i_offset
     466        98217 :                block_end_i = sgfi + nsgfi(iset) - 1 + my_i_offset
     467              : 
     468              :                int_3c(block_start_j:block_end_j, &
     469              :                       block_start_k:block_end_k, &
     470              :                       block_start_i:block_end_i) = &
     471              :                   int_3c(block_start_j:block_end_j, &
     472              :                          block_start_k:block_end_k, &
     473              :                          block_start_i:block_end_i) + &
     474      1308301 :                   sijk_contr(:, :, :)
     475       163298 :                DEALLOCATE (sijk_contr)
     476              : 
     477              :             END DO
     478              :          END DO
     479              :       END DO
     480              : 
     481        41019 :    END SUBROUTINE build_3c_integral_block_ctx
     482              : 
     483              : ! **************************************************************************************************
     484              : !> \brief ...
     485              : !> \param int_3c ...
     486              : !> \param qs_env ...
     487              : !> \param potential_parameter ...
     488              : !> \param basis_j ...
     489              : !> \param basis_k ...
     490              : !> \param basis_i ...
     491              : !> \param cell_j ...
     492              : !> \param cell_k ...
     493              : !> \param cell_i ...
     494              : !> \param atom_j ...
     495              : !> \param atom_k ...
     496              : !> \param atom_i ...
     497              : !> \param j_bf_start_from_atom ...
     498              : !> \param k_bf_start_from_atom ...
     499              : !> \param i_bf_start_from_atom ...
     500              : ! **************************************************************************************************
     501        38766 :    SUBROUTINE build_3c_integral_block(int_3c, qs_env, potential_parameter, &
     502        12922 :                                       basis_j, basis_k, basis_i, &
     503              :                                       cell_j, cell_k, cell_i, atom_j, atom_k, atom_i, &
     504        12922 :                                       j_bf_start_from_atom, k_bf_start_from_atom, &
     505        12922 :                                       i_bf_start_from_atom)
     506              : 
     507              :       REAL(KIND=dp), DIMENSION(:, :, :)                  :: int_3c
     508              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     509              :       TYPE(libint_potential_type), INTENT(IN)            :: potential_parameter
     510              :       TYPE(gto_basis_set_p_type), DIMENSION(:)           :: basis_j, basis_k, basis_i
     511              :       INTEGER, DIMENSION(3), INTENT(IN), OPTIONAL        :: cell_j, cell_k, cell_i
     512              :       INTEGER, INTENT(IN), OPTIONAL                      :: atom_j, atom_k, atom_i
     513              :       INTEGER, DIMENSION(:), OPTIONAL                    :: j_bf_start_from_atom, &
     514              :                                                             k_bf_start_from_atom, &
     515              :                                                             i_bf_start_from_atom
     516              : 
     517              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'build_3c_integral_block'
     518              : 
     519              :       INTEGER                                            :: at_i, at_j, at_k, handle, my_i_offset, &
     520              :                                                             my_j_offset, my_k_offset, natom
     521        12922 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     522              :       TYPE(cell_type), POINTER                           :: cell
     523       167986 :       TYPE(gw_3c_ctx_type)                               :: ctx
     524        12922 :       TYPE(gw_3c_ws_type)                                :: ws
     525              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     526        12922 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     527              : 
     528        12922 :       CALL timeset(routineN, handle)
     529              : 
     530        12922 :       NULLIFY (atomic_kind_set, cell, para_env, particle_set)
     531              :       CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, cell=cell, natom=natom, &
     532        12922 :                       para_env=para_env, particle_set=particle_set)
     533              :       CALL gw_3c_ctx_create_core(ctx, potential_parameter, basis_j, basis_k, basis_i, &
     534        12922 :                                  atomic_kind_set, cell, natom, para_env, particle_set)
     535        12922 :       CALL gw_3c_ws_create(ws, ctx)
     536              : 
     537       823215 :       int_3c(:, :, :) = 0.0_dp
     538              : 
     539              :       ! loop over all RI atoms
     540        51303 :       DO at_i = 1, ctx%natom
     541              :          ! loop over all AO atoms
     542       165676 :          DO at_j = 1, ctx%natom
     543              :             ! loop over all AO atoms
     544       494333 :             DO at_k = 1, ctx%natom
     545              : 
     546       341579 :                IF (PRESENT(atom_i)) THEN
     547       340779 :                   IF (at_i /= atom_i) CYCLE
     548              :                END IF
     549       114773 :                IF (PRESENT(atom_j)) THEN
     550       114773 :                   IF (at_j /= atom_j) CYCLE
     551              :                END IF
     552        38581 :                IF (PRESENT(atom_k)) THEN
     553        38581 :                   IF (at_k /= atom_k) CYCLE
     554              :                END IF
     555              : 
     556        13022 :                IF (PRESENT(atom_j)) THEN
     557        13022 :                   my_j_offset = 0
     558              :                ELSE
     559            0 :                   CPASSERT(PRESENT(j_bf_start_from_atom))
     560            0 :                   my_j_offset = j_bf_start_from_atom(at_j) - 1
     561              :                END IF
     562        13022 :                IF (PRESENT(atom_k)) THEN
     563        13022 :                   my_k_offset = 0
     564              :                ELSE
     565            0 :                   CPASSERT(PRESENT(k_bf_start_from_atom))
     566            0 :                   my_k_offset = k_bf_start_from_atom(at_k) - 1
     567              :                END IF
     568        13022 :                IF (PRESENT(atom_i)) THEN
     569        12822 :                   my_i_offset = 0
     570              :                ELSE
     571          200 :                   CPASSERT(PRESENT(i_bf_start_from_atom))
     572          200 :                   my_i_offset = i_bf_start_from_atom(at_i) - 1
     573              :                END IF
     574              : 
     575              :                CALL build_3c_integral_block_ctx(int_3c, ctx, ws, at_j, at_k, at_i, &
     576              :                                                 cell_j=cell_j, cell_k=cell_k, cell_i=cell_i, &
     577              :                                                 j_offset=my_j_offset, k_offset=my_k_offset, &
     578       455952 :                                                 i_offset=my_i_offset)
     579              : 
     580              :             END DO ! atom_k (AO)
     581              :          END DO ! atom_j (AO)
     582              :       END DO ! atom_i (RI)
     583              : 
     584        12922 :       CALL gw_3c_ws_release(ws)
     585        12922 :       CALL gw_3c_ctx_release(ctx)
     586              : 
     587        12922 :       CALL timestop(handle)
     588              : 
     589        38766 :    END SUBROUTINE build_3c_integral_block
     590              : 
     591            0 : END MODULE gw_utils_compute_integrals
        

Generated by: LCOV version 2.0-1