LCOV - code coverage report
Current view: top level - src - mp2_eri_gpw.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:34ef472) Lines: 318 326 97.5 %
Date: 2024-04-26 08:30:29 Functions: 11 11 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Routines to calculate 2c- and 3c-integrals for RI with GPW
      10             : !> \par History
      11             : !>      07.2019 separated from mp2_integrals.F [Frederick Stein]
      12             : ! **************************************************************************************************
      13             : MODULE mp2_eri_gpw
      14             :    USE ao_util,                         ONLY: exp_radius_very_extended
      15             :    USE atomic_kind_types,               ONLY: atomic_kind_type
      16             :    USE basis_set_types,                 ONLY: gto_basis_set_type
      17             :    USE cell_types,                      ONLY: cell_type,&
      18             :                                               pbc
      19             :    USE cp_control_types,                ONLY: dft_control_type
      20             :    USE cp_fm_types,                     ONLY: cp_fm_type
      21             :    USE dbcsr_api,                       ONLY: dbcsr_p_type,&
      22             :                                               dbcsr_set
      23             :    USE gaussian_gridlevels,             ONLY: gaussian_gridlevel
      24             :    USE input_constants,                 ONLY: do_potential_coulomb,&
      25             :                                               do_potential_id,&
      26             :                                               do_potential_long,&
      27             :                                               do_potential_mix_cl,&
      28             :                                               do_potential_short,&
      29             :                                               do_potential_truncated
      30             :    USE kinds,                           ONLY: dp
      31             :    USE libint_2c_3c,                    ONLY: libint_potential_type
      32             :    USE mathconstants,                   ONLY: fourpi
      33             :    USE message_passing,                 ONLY: mp_para_env_type
      34             :    USE orbital_pointers,                ONLY: ncoset
      35             :    USE particle_types,                  ONLY: particle_type
      36             :    USE pw_env_methods,                  ONLY: pw_env_create,&
      37             :                                               pw_env_rebuild
      38             :    USE pw_env_types,                    ONLY: pw_env_get,&
      39             :                                               pw_env_release,&
      40             :                                               pw_env_type
      41             :    USE pw_methods,                      ONLY: &
      42             :         pw_compl_gauss_damp, pw_copy, pw_derive, pw_gauss_damp, pw_gauss_damp_mix, pw_integral_ab, &
      43             :         pw_log_deriv_compl_gauss, pw_log_deriv_gauss, pw_log_deriv_mix_cl, pw_log_deriv_trunc, &
      44             :         pw_scale, pw_transfer, pw_truncated, pw_zero
      45             :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
      46             :    USE pw_poisson_types,                ONLY: pw_poisson_type
      47             :    USE pw_pool_types,                   ONLY: pw_pool_type
      48             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      49             :                                               pw_r3d_rs_type
      50             :    USE qs_collocate_density,            ONLY: calculate_rho_elec,&
      51             :                                               calculate_wavefunction,&
      52             :                                               collocate_single_gaussian
      53             :    USE qs_environment_types,            ONLY: get_qs_env,&
      54             :                                               qs_environment_type
      55             :    USE qs_force_types,                  ONLY: qs_force_type
      56             :    USE qs_integrate_potential,          ONLY: integrate_pgf_product,&
      57             :                                               integrate_v_rspace
      58             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      59             :                                               get_qs_kind_set,&
      60             :                                               qs_kind_type
      61             :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      62             :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      63             :    USE realspace_grid_types,            ONLY: map_gaussian_here,&
      64             :                                               realspace_grid_desc_p_type,&
      65             :                                               realspace_grid_type
      66             :    USE rs_pw_interface,                 ONLY: potential_pw2rs
      67             :    USE task_list_methods,               ONLY: generate_qs_task_list
      68             :    USE task_list_types,                 ONLY: allocate_task_list,&
      69             :                                               deallocate_task_list,&
      70             :                                               task_list_type
      71             : 
      72             : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num
      73             : #include "./base/base_uses.f90"
      74             : 
      75             :    IMPLICIT NONE
      76             : 
      77             :    PRIVATE
      78             : 
      79             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mp2_eri_gpw'
      80             : 
      81             :    PUBLIC :: mp2_eri_2c_integrate_gpw, mp2_eri_3c_integrate_gpw, calc_potential_gpw, cleanup_gpw, prepare_gpw, &
      82             :              integrate_potential_forces_2c, integrate_potential_forces_3c_1c, integrate_potential_forces_3c_2c, &
      83             :              virial_gpw_potential
      84             : 
      85             : CONTAINS
      86             : 
      87             : ! **************************************************************************************************
      88             : !> \brief ...
      89             : !> \param mo_coeff ...
      90             : !> \param psi_L ...
      91             : !> \param rho_g ...
      92             : !> \param atomic_kind_set ...
      93             : !> \param qs_kind_set ...
      94             : !> \param cell ...
      95             : !> \param dft_control ...
      96             : !> \param particle_set ...
      97             : !> \param pw_env_sub ...
      98             : !> \param external_vector ...
      99             : !> \param poisson_env ...
     100             : !> \param rho_r ...
     101             : !> \param pot_g ...
     102             : !> \param potential_parameter ...
     103             : !> \param mat_munu ...
     104             : !> \param qs_env ...
     105             : !> \param task_list_sub ...
     106             : ! **************************************************************************************************
     107       27358 :    SUBROUTINE mp2_eri_3c_integrate_gpw(mo_coeff, psi_L, rho_g, atomic_kind_set, qs_kind_set, cell, dft_control, particle_set, &
     108       13679 :                                        pw_env_sub, external_vector, poisson_env, rho_r, pot_g, &
     109             :                                        potential_parameter, mat_munu, qs_env, task_list_sub)
     110             : 
     111             :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_coeff
     112             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: psi_L
     113             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rho_g
     114             :       TYPE(atomic_kind_type), DIMENSION(:), INTENT(IN), &
     115             :          POINTER                                         :: atomic_kind_set
     116             :       TYPE(qs_kind_type), DIMENSION(:), INTENT(IN), &
     117             :          POINTER                                         :: qs_kind_set
     118             :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
     119             :       TYPE(dft_control_type), INTENT(IN), POINTER        :: dft_control
     120             :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
     121             :          POINTER                                         :: particle_set
     122             :       TYPE(pw_env_type), INTENT(IN), POINTER             :: pw_env_sub
     123             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: external_vector
     124             :       TYPE(pw_poisson_type), INTENT(IN), POINTER         :: poisson_env
     125             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: rho_r
     126             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: pot_g
     127             :       TYPE(libint_potential_type), INTENT(IN)            :: potential_parameter
     128             :       TYPE(dbcsr_p_type), INTENT(INOUT)                  :: mat_munu
     129             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     130             :       TYPE(task_list_type), INTENT(IN), POINTER          :: task_list_sub
     131             : 
     132             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'mp2_eri_3c_integrate_gpw'
     133             : 
     134             :       INTEGER                                            :: handle
     135             : 
     136       13679 :       CALL timeset(routineN, handle)
     137             : 
     138             :       ! pseudo psi_L
     139             :       CALL calculate_wavefunction(mo_coeff, 1, psi_L, rho_g, atomic_kind_set, &
     140             :                                   qs_kind_set, cell, dft_control, particle_set, pw_env_sub, &
     141             :                                   basis_type="RI_AUX", &
     142       13679 :                                   external_vector=external_vector)
     143             : 
     144       13679 :       CALL calc_potential_gpw(rho_r, rho_g, poisson_env, pot_g, potential_parameter)
     145             : 
     146             :       ! and finally (K|mu nu)
     147       13679 :       CALL dbcsr_set(mat_munu%matrix, 0.0_dp)
     148             :       CALL integrate_v_rspace(rho_r, hmat=mat_munu, qs_env=qs_env, &
     149             :                               calculate_forces=.FALSE., compute_tau=.FALSE., gapw=.FALSE., &
     150       13679 :                               pw_env_external=pw_env_sub, task_list_external=task_list_sub)
     151             : 
     152       13679 :       CALL timestop(handle)
     153             : 
     154       13679 :    END SUBROUTINE mp2_eri_3c_integrate_gpw
     155             : 
     156             : ! **************************************************************************************************
     157             : !> \brief Integrates the potential of an RI function
     158             : !> \param qs_env ...
     159             : !> \param para_env_sub ...
     160             : !> \param my_group_L_start ...
     161             : !> \param my_group_L_end ...
     162             : !> \param natom ...
     163             : !> \param potential_parameter ...
     164             : !> \param sab_orb_sub ...
     165             : !> \param L_local_col ...
     166             : !> \param kind_of ...
     167             : ! **************************************************************************************************
     168         368 :    SUBROUTINE mp2_eri_2c_integrate_gpw(qs_env, para_env_sub, my_group_L_start, my_group_L_end, &
     169         368 :                                        natom, potential_parameter, sab_orb_sub, L_local_col, kind_of)
     170             : 
     171             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     172             :       TYPE(mp_para_env_type), INTENT(IN), POINTER        :: para_env_sub
     173             :       INTEGER, INTENT(IN)                                :: my_group_L_start, my_group_L_end, natom
     174             :       TYPE(libint_potential_type), INTENT(IN)            :: potential_parameter
     175             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     176             :          INTENT(IN), POINTER                             :: sab_orb_sub
     177             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: L_local_col
     178             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: kind_of
     179             : 
     180             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'mp2_eri_2c_integrate_gpw'
     181             : 
     182             :       INTEGER :: dir, handle, handle2, i_counter, iatom, igrid_level, ikind, ipgf, iset, lb(3), &
     183             :          LLL, location(3), max_nseta, na1, na2, ncoa, nseta, offset, sgfa, tp(3), ub(3)
     184         368 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: offset_2d
     185         368 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, npgfa, nsgfa
     186         368 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa
     187             :       LOGICAL                                            :: map_it_here, use_subpatch
     188             :       REAL(KIND=dp)                                      :: cutoff_old, radius, relative_cutoff_old
     189         368 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: e_cutoff_old
     190         368 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: I_ab
     191             :       REAL(KIND=dp), DIMENSION(3)                        :: ra
     192         368 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a
     193         368 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: I_tmp2, rpgfa, sphi_a, zeta
     194         368 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     195             :       TYPE(cell_type), POINTER                           :: cell
     196             :       TYPE(dft_control_type), POINTER                    :: dft_control
     197             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a
     198         368 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     199             :       TYPE(pw_c1d_gs_type)                               :: pot_g, rho_g
     200             :       TYPE(pw_env_type), POINTER                         :: pw_env_sub
     201             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     202             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     203             :       TYPE(pw_r3d_rs_type)                               :: psi_L, rho_r
     204         368 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     205             :       TYPE(realspace_grid_desc_p_type), DIMENSION(:), &
     206         368 :          POINTER                                         :: rs_descs
     207         368 :       TYPE(realspace_grid_type), DIMENSION(:), POINTER   :: rs_v
     208             :       TYPE(task_list_type), POINTER                      :: task_list_sub
     209             : 
     210         368 :       CALL timeset(routineN, handle)
     211             : 
     212             :       CALL prepare_gpw(qs_env, dft_control, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_sub, pw_env_sub, &
     213         368 :                        auxbas_pw_pool, poisson_env, task_list_sub, rho_r, rho_g, pot_g, psi_L, sab_orb_sub)
     214             : 
     215         368 :       CALL get_qs_env(qs_env, cell=cell, qs_kind_set=qs_kind_set, atomic_kind_set=atomic_kind_set, particle_set=particle_set)
     216             : 
     217     1378448 :       L_local_col = 0.0_dp
     218             : 
     219         368 :       i_counter = 0
     220       16557 :       DO LLL = my_group_L_start, my_group_L_end
     221       16189 :          i_counter = i_counter + 1
     222             : 
     223             :          ! pseudo psi_L
     224             :          CALL collocate_single_gaussian(psi_L, rho_g, atomic_kind_set, &
     225             :                                         qs_kind_set, cell, dft_control, particle_set, pw_env_sub, &
     226       16189 :                                         required_function=LLL, basis_type="RI_AUX")
     227             : 
     228       16189 :          CALL timeset(routineN//"_pot_lm", handle2)
     229             : 
     230       16189 :          CALL calc_potential_gpw(rho_r, rho_g, poisson_env, pot_g, potential_parameter)
     231             : 
     232       16189 :          NULLIFY (rs_v)
     233       16189 :          NULLIFY (rs_descs)
     234       16189 :          CALL pw_env_get(pw_env_sub, rs_descs=rs_descs, rs_grids=rs_v)
     235       16189 :          CALL potential_pw2rs(rs_v, rho_r, pw_env_sub)
     236             : 
     237       16189 :          CALL timestop(handle2)
     238             : 
     239       16189 :          offset = 0
     240             :          ! Prepare offset ahead of OMP parallel loop
     241       16189 :          CALL get_qs_kind_set(qs_kind_set=qs_kind_set, maxnset=max_nseta, basis_type="RI_AUX")
     242       64756 :          ALLOCATE (offset_2d(max_nseta, natom))
     243             : 
     244       66582 :          DO iatom = 1, natom
     245       50393 :             ikind = kind_of(iatom)
     246       50393 :             CALL get_qs_kind(qs_kind=qs_kind_set(ikind), basis_set=basis_set_a, basis_type="RI_AUX")
     247       50393 :             nseta = basis_set_a%nset
     248       50393 :             nsgfa => basis_set_a%nsgf_set
     249      540937 :             DO iset = 1, nseta
     250      474355 :                offset = offset + nsgfa(iset)
     251      524748 :                offset_2d(iset, iatom) = offset
     252             :             END DO
     253             :          END DO
     254             : 
     255             :          ! integrate the little bastards
     256             :          !$OMP PARALLEL DO DEFAULT(NONE) &
     257             :          !$OMP SHARED(natom, particle_set, cell, pw_env_sub, rs_v, offset_2d, &
     258             :          !$OMP        qs_kind_set, ncoset, para_env_sub, dft_control, i_counter, &
     259             :          !$OMP        kind_of, l_local_col) &
     260             :          !$OMP PRIVATE(iatom, ikind, basis_set_a, first_sgfa, la_max, la_min, npgfa, &
     261             :          !$OMP         nseta, nsgfa, rpgfa, set_radius_a, sphi_a, zeta, &
     262             :          !$OMP         ra, iset, ncoa, I_tmp2, I_ab, igrid_level, &
     263             :          !$OMP         map_it_here, dir, tp, lb, ub, location, ipgf, &
     264       16189 :          !$OMP         sgfa, na1, na2, radius, offset, use_subpatch)
     265             :          DO iatom = 1, natom
     266             :             ikind = kind_of(iatom)
     267             :             CALL get_qs_kind(qs_kind=qs_kind_set(ikind), basis_set=basis_set_a, basis_type="RI_AUX")
     268             : 
     269             :             first_sgfa => basis_set_a%first_sgf
     270             :             la_max => basis_set_a%lmax
     271             :             la_min => basis_set_a%lmin
     272             :             npgfa => basis_set_a%npgf
     273             :             nseta = basis_set_a%nset
     274             :             nsgfa => basis_set_a%nsgf_set
     275             :             rpgfa => basis_set_a%pgf_radius
     276             :             set_radius_a => basis_set_a%set_radius
     277             :             sphi_a => basis_set_a%sphi
     278             :             zeta => basis_set_a%zet
     279             : 
     280             :             ra(:) = pbc(particle_set(iatom)%r, cell)
     281             : 
     282             :             DO iset = 1, nseta
     283             :                ncoa = npgfa(iset)*ncoset(la_max(iset))
     284             :                sgfa = first_sgfa(1, iset)
     285             : 
     286             :                ALLOCATE (I_tmp2(ncoa, 1))
     287             :                I_tmp2 = 0.0_dp
     288             :                ALLOCATE (I_ab(nsgfa(iset), 1))
     289             :                I_ab = 0.0_dp
     290             : 
     291             :                offset = offset_2d(iset, iatom)
     292             : 
     293             :                igrid_level = gaussian_gridlevel(pw_env_sub%gridlevel_info, MINVAL(zeta(:, iset)))
     294             :                use_subpatch = .NOT. ALL(rs_v(igrid_level)%desc%perd == 1)
     295             : 
     296             :                IF (map_gaussian_here(rs_v(igrid_level), cell%h_inv, ra, &
     297             :                                      offset, para_env_sub%num_pe, para_env_sub%mepos)) THEN
     298             :                   DO ipgf = 1, npgfa(iset)
     299             :                      sgfa = first_sgfa(1, iset)
     300             :                      na1 = (ipgf - 1)*ncoset(la_max(iset)) + 1
     301             :                      na2 = ipgf*ncoset(la_max(iset))
     302             :                      igrid_level = gaussian_gridlevel(pw_env_sub%gridlevel_info, zeta(ipgf, iset))
     303             : 
     304             :                      radius = exp_radius_very_extended(la_min=la_min(iset), la_max=la_max(iset), &
     305             :                                                        lb_min=0, lb_max=0, ra=ra, rb=ra, rp=ra, &
     306             :                                                        zetp=zeta(ipgf, iset), &
     307             :                                                        eps=dft_control%qs_control%eps_gvg_rspace, &
     308             :                                                        prefactor=1.0_dp, cutoff=1.0_dp)
     309             : 
     310             :                      CALL integrate_pgf_product( &
     311             :                         la_max=la_max(iset), zeta=zeta(ipgf, iset), la_min=la_min(iset), &
     312             :                         lb_max=0, zetb=0.0_dp, lb_min=0, &
     313             :                         ra=ra, rab=(/0.0_dp, 0.0_dp, 0.0_dp/), &
     314             :                         rsgrid=rs_v(igrid_level), &
     315             :                         hab=I_tmp2, &
     316             :                         o1=na1 - 1, &
     317             :                         o2=0, &
     318             :                         radius=radius, &
     319             :                         calculate_forces=.FALSE., &
     320             :                         use_subpatch=use_subpatch, &
     321             :                         subpatch_pattern=0)
     322             :                   END DO
     323             : 
     324             :                   CALL dgemm("T", "N", nsgfa(iset), 1, ncoa, &
     325             :                              1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     326             :                              I_tmp2(1, 1), SIZE(I_tmp2, 1), &
     327             :                              1.0_dp, I_ab(1, 1), SIZE(I_ab, 1))
     328             : 
     329             :                   L_local_col(offset - nsgfa(iset) + 1:offset, i_counter) = I_ab(1:nsgfa(iset), 1)
     330             :                END IF
     331             : 
     332             :                DEALLOCATE (I_tmp2)
     333             :                DEALLOCATE (I_ab)
     334             : 
     335             :             END DO
     336             :          END DO
     337             :          !$OMP END PARALLEL DO
     338       48935 :          DEALLOCATE (offset_2d)
     339             : 
     340             :       END DO
     341             : 
     342     2756528 :       CALL para_env_sub%sum(L_local_col)
     343             : 
     344             :       CALL cleanup_gpw(qs_env, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_sub, pw_env_sub, &
     345         368 :                        task_list_sub, auxbas_pw_pool, rho_r, rho_g, pot_g, psi_L)
     346             : 
     347         368 :       CALL timestop(handle)
     348             : 
     349         736 :    END SUBROUTINE
     350             : 
     351             : ! **************************************************************************************************
     352             : !> \brief Integrates the potential of a RI function obtaining the forces and stress tensor
     353             : !> \param rho_r ...
     354             : !> \param LLL ...
     355             : !> \param matrix ...
     356             : !> \param rho_g ...
     357             : !> \param atomic_kind_set ...
     358             : !> \param qs_kind_set ...
     359             : !> \param particle_set ...
     360             : !> \param cell ...
     361             : !> \param pw_env_sub ...
     362             : !> \param poisson_env ...
     363             : !> \param pot_g ...
     364             : !> \param potential_parameter ...
     365             : !> \param use_virial ...
     366             : !> \param rho_g_copy ...
     367             : !> \param dvg ...
     368             : !> \param kind_of ...
     369             : !> \param atom_of_kind ...
     370             : !> \param G_PQ_local ...
     371             : !> \param force ...
     372             : !> \param h_stress ...
     373             : !> \param para_env_sub ...
     374             : !> \param dft_control ...
     375             : !> \param psi_L ...
     376             : !> \param factor ...
     377             : ! **************************************************************************************************
     378       32376 :    SUBROUTINE integrate_potential_forces_2c(rho_r, LLL, matrix, rho_g, atomic_kind_set, &
     379             :                                             qs_kind_set, particle_set, cell, pw_env_sub, poisson_env, pot_g, &
     380             :                                             potential_parameter, use_virial, rho_g_copy, dvg, &
     381       10792 :                                             kind_of, atom_of_kind, G_PQ_local, force, h_stress, para_env_sub, &
     382             :                                             dft_control, psi_L, factor)
     383             : 
     384             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: rho_r
     385             :       INTEGER, INTENT(IN)                                :: LLL
     386             :       TYPE(cp_fm_type), INTENT(IN)                       :: matrix
     387             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rho_g
     388             :       TYPE(atomic_kind_type), DIMENSION(:), INTENT(IN), &
     389             :          POINTER                                         :: atomic_kind_set
     390             :       TYPE(qs_kind_type), DIMENSION(:), INTENT(IN), &
     391             :          POINTER                                         :: qs_kind_set
     392             :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
     393             :          POINTER                                         :: particle_set
     394             :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
     395             :       TYPE(pw_env_type), INTENT(IN), POINTER             :: pw_env_sub
     396             :       TYPE(pw_poisson_type), INTENT(IN), POINTER         :: poisson_env
     397             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: pot_g
     398             :       TYPE(libint_potential_type), INTENT(IN)            :: potential_parameter
     399             :       LOGICAL, INTENT(IN)                                :: use_virial
     400             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rho_g_copy, dvg(3)
     401             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: kind_of, atom_of_kind
     402             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: G_PQ_local
     403             :       TYPE(qs_force_type), DIMENSION(:), INTENT(IN), &
     404             :          POINTER                                         :: force
     405             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT)      :: h_stress
     406             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env_sub
     407             :       TYPE(dft_control_type), INTENT(IN), POINTER        :: dft_control
     408             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: psi_L
     409             :       REAL(KIND=dp), INTENT(IN)                          :: factor
     410             : 
     411             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'integrate_potential_forces_2c'
     412             : 
     413             :       INTEGER                                            :: handle, handle2
     414             : 
     415       10792 :       CALL timeset(routineN, handle)
     416             : 
     417             :       ! calculate potential associated to the single aux function
     418       10792 :       CALL timeset(routineN//"_wf_pot", handle2)
     419             :       ! pseudo psi_L
     420       10792 :       CALL pw_zero(rho_r)
     421       10792 :       CALL pw_zero(rho_g)
     422             :       CALL collocate_single_gaussian(rho_r, rho_g, atomic_kind_set, &
     423             :                                      qs_kind_set, cell, dft_control, particle_set, &
     424       10792 :                                      pw_env_sub, required_function=LLL, basis_type='RI_AUX')
     425       10792 :       IF (use_virial) THEN
     426        2145 :          CALL calc_potential_gpw(rho_r, rho_g, poisson_env, pot_g, potential_parameter, dvg)
     427             :       ELSE
     428        8647 :          CALL calc_potential_gpw(rho_r, rho_g, poisson_env, pot_g, potential_parameter)
     429             :       END IF
     430       10792 :       CALL timestop(handle2)
     431             : 
     432       10792 :       IF (use_virial) THEN
     433             :          ! make a copy of the density in G space
     434        2145 :          CALL pw_copy(rho_g, rho_g_copy)
     435             : 
     436             :          ! add the volume contribution to the virial due to
     437             :          ! the (P|Q) integrals, first we put the full gamme_PQ
     438             :          ! pseudo wave-function into grid in order to calculate the
     439             :          ! hartree potential derivatives
     440        2145 :          CALL pw_zero(psi_L)
     441        2145 :          CALL pw_zero(rho_g)
     442             :          CALL calculate_wavefunction(matrix, 1, psi_L, rho_g, atomic_kind_set, &
     443             :                                      qs_kind_set, cell, dft_control, particle_set, pw_env_sub, &
     444             :                                      basis_type="RI_AUX", &
     445      188146 :                                      external_vector=0.5_dp*factor*G_PQ_local)
     446             :          ! transfer to reciprocal space and calculate potential
     447        2145 :          CALL calc_potential_gpw(psi_L, rho_g, poisson_env, pot_g, potential_parameter, no_transfer=.TRUE.)
     448             :          ! update virial with volume term (first calculate hartree like energy (diagonal part of the virial))
     449        2145 :          CALL virial_gpw_potential(rho_g_copy, pot_g, rho_g, dvg, h_stress, potential_parameter, para_env_sub)
     450             :       END IF
     451             : 
     452             :       ! integrate the potential of the single gaussian and update
     453             :       ! 2-center forces with Gamma_PQ
     454             :       CALL integrate_potential(pw_env_sub, rho_r, kind_of, atom_of_kind, particle_set, qs_kind_set, &
     455      926972 :                                -0.25_dp*factor*G_PQ_local, cell, force, use_virial, h_stress, para_env_sub, dft_control)
     456             : 
     457       10792 :       CALL timestop(handle)
     458       10792 :    END SUBROUTINE integrate_potential_forces_2c
     459             : 
     460             : ! **************************************************************************************************
     461             : !> \brief Takes the precomputed potential of an RI wave-function and determines matrix element and
     462             : !>        gradients with product of Gaussians
     463             : !> \param mat_munu ...
     464             : !> \param rho_r ...
     465             : !> \param matrix_P_munu ...
     466             : !> \param qs_env ...
     467             : !> \param pw_env_sub ...
     468             : !> \param task_list_sub ...
     469             : ! **************************************************************************************************
     470       10294 :    SUBROUTINE integrate_potential_forces_3c_1c(mat_munu, rho_r, matrix_P_munu, qs_env, pw_env_sub, &
     471             :                                                task_list_sub)
     472             : 
     473             :       TYPE(dbcsr_p_type), INTENT(INOUT)                  :: mat_munu
     474             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_r
     475             :       TYPE(dbcsr_p_type), INTENT(IN)                     :: matrix_P_munu
     476             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     477             :       TYPE(pw_env_type), INTENT(IN), POINTER             :: pw_env_sub
     478             :       TYPE(task_list_type), INTENT(INOUT), POINTER       :: task_list_sub
     479             : 
     480             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'integrate_potential_forces_3c_1c'
     481             : 
     482             :       INTEGER                                            :: handle
     483             : 
     484       10294 :       CALL timeset(routineN, handle)
     485             : 
     486             :       ! integrate the potential of the single gaussian and update
     487             :       ! 3-center forces
     488       10294 :       CALL dbcsr_set(mat_munu%matrix, 0.0_dp)
     489             :       CALL integrate_v_rspace(rho_r, hmat=mat_munu, pmat=matrix_P_munu, &
     490             :                               qs_env=qs_env, calculate_forces=.TRUE., compute_tau=.FALSE., gapw=.FALSE., &
     491             :                               pw_env_external=pw_env_sub, &
     492       10294 :                               task_list_external=task_list_sub)
     493             : 
     494       10294 :       CALL timestop(handle)
     495       10294 :    END SUBROUTINE integrate_potential_forces_3c_1c
     496             : 
     497             : ! **************************************************************************************************
     498             : !> \brief Integrates potential of two Gaussians to a potential
     499             : !> \param matrix_P_munu ...
     500             : !> \param rho_r ...
     501             : !> \param rho_g ...
     502             : !> \param task_list_sub ...
     503             : !> \param pw_env_sub ...
     504             : !> \param potential_parameter ...
     505             : !> \param ks_env ...
     506             : !> \param poisson_env ...
     507             : !> \param pot_g ...
     508             : !> \param use_virial ...
     509             : !> \param rho_g_copy ...
     510             : !> \param dvg ...
     511             : !> \param h_stress ...
     512             : !> \param para_env_sub ...
     513             : !> \param kind_of ...
     514             : !> \param atom_of_kind ...
     515             : !> \param qs_kind_set ...
     516             : !> \param particle_set ...
     517             : !> \param cell ...
     518             : !> \param LLL ...
     519             : !> \param force ...
     520             : !> \param dft_control ...
     521             : ! **************************************************************************************************
     522       10294 :    SUBROUTINE integrate_potential_forces_3c_2c(matrix_P_munu, rho_r, rho_g, task_list_sub, pw_env_sub, &
     523             :                                                potential_parameter, &
     524             :                                                ks_env, poisson_env, pot_g, use_virial, rho_g_copy, dvg, &
     525       10294 :                                                h_stress, para_env_sub, kind_of, atom_of_kind, &
     526             :                                                qs_kind_set, particle_set, cell, LLL, force, dft_control)
     527             : 
     528             :       TYPE(dbcsr_p_type), INTENT(IN)                     :: matrix_P_munu
     529             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: rho_r
     530             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rho_g
     531             :       TYPE(task_list_type), INTENT(IN), POINTER          :: task_list_sub
     532             :       TYPE(pw_env_type), INTENT(IN), POINTER             :: pw_env_sub
     533             :       TYPE(libint_potential_type), INTENT(IN)            :: potential_parameter
     534             :       TYPE(qs_ks_env_type), INTENT(IN), POINTER          :: ks_env
     535             :       TYPE(pw_poisson_type), INTENT(IN), POINTER         :: poisson_env
     536             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: pot_g
     537             :       LOGICAL, INTENT(IN)                                :: use_virial
     538             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rho_g_copy
     539             :       TYPE(pw_c1d_gs_type), INTENT(IN)                   :: dvg(3)
     540             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT)      :: h_stress
     541             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env_sub
     542             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: kind_of, atom_of_kind
     543             :       TYPE(qs_kind_type), DIMENSION(:), INTENT(IN), &
     544             :          POINTER                                         :: qs_kind_set
     545             :       TYPE(particle_type), DIMENSION(:), INTENT(IN), &
     546             :          POINTER                                         :: particle_set
     547             :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
     548             :       INTEGER, INTENT(IN)                                :: LLL
     549             :       TYPE(qs_force_type), DIMENSION(:), INTENT(IN), &
     550             :          POINTER                                         :: force
     551             :       TYPE(dft_control_type), INTENT(IN), POINTER        :: dft_control
     552             : 
     553             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'integrate_potential_forces_3c_2c'
     554             : 
     555             :       INTEGER                                            :: atom_a, handle, handle2, iatom, &
     556             :                                                             igrid_level, ikind, iorb, ipgf, iset, &
     557             :                                                             na1, na2, ncoa, nseta, offset, sgfa
     558       10294 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, npgfa, nsgfa
     559       10294 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa
     560             :       LOGICAL                                            :: map_it_here, skip_shell, use_subpatch
     561             :       REAL(KIND=dp)                                      :: radius
     562       10294 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: I_ab
     563             :       REAL(KIND=dp), DIMENSION(3)                        :: force_a, force_b, ra
     564             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: my_virial_a, my_virial_b
     565       10294 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a
     566       10294 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: I_tmp2, pab, rpgfa, sphi_a, zeta
     567             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a
     568             :       TYPE(realspace_grid_desc_p_type), DIMENSION(:), &
     569       10294 :          POINTER                                         :: rs_descs
     570       10294 :       TYPE(realspace_grid_type), DIMENSION(:), POINTER   :: rs_v
     571             : 
     572       10294 :       CALL timeset(routineN, handle)
     573             : 
     574             :       ! put the gamma density on grid
     575       10294 :       CALL timeset(routineN//"_Gpot", handle2)
     576       10294 :       CALL pw_zero(rho_r)
     577       10294 :       CALL pw_zero(rho_g)
     578             :       CALL calculate_rho_elec(matrix_p=matrix_P_munu%matrix, &
     579             :                               rho=rho_r, &
     580             :                               rho_gspace=rho_g, &
     581             :                               task_list_external=task_list_sub, &
     582             :                               pw_env_external=pw_env_sub, &
     583       10294 :                               ks_env=ks_env)
     584             :       ! calculate associated hartree potential
     585             :       !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     586       10294 :       CALL calc_potential_gpw(rho_r, rho_g, poisson_env, pot_g, potential_parameter)
     587       10294 :       CALL timestop(handle2)
     588             : 
     589       10294 :       IF (use_virial) CALL virial_gpw_potential(rho_g_copy, pot_g, rho_g, dvg, h_stress, potential_parameter, para_env_sub)
     590             : 
     591             :       ! integrate potential with auxiliary basis function derivatives
     592       10294 :       NULLIFY (rs_v)
     593       10294 :       NULLIFY (rs_descs)
     594       10294 :       CALL pw_env_get(pw_env_sub, rs_descs=rs_descs, rs_grids=rs_v)
     595       10294 :       CALL potential_pw2rs(rs_v, rho_r, pw_env_sub)
     596             : 
     597       10294 :       offset = 0
     598       42402 :       DO iatom = 1, SIZE(kind_of)
     599       32108 :          ikind = kind_of(iatom)
     600       32108 :          atom_a = atom_of_kind(iatom)
     601             :          CALL get_qs_kind(qs_kind=qs_kind_set(ikind), basis_set=basis_set_a, &
     602       32108 :                           basis_type="RI_AUX")
     603             : 
     604       32108 :          first_sgfa => basis_set_a%first_sgf
     605       32108 :          la_max => basis_set_a%lmax
     606       32108 :          la_min => basis_set_a%lmin
     607       32108 :          npgfa => basis_set_a%npgf
     608       32108 :          nseta = basis_set_a%nset
     609       32108 :          nsgfa => basis_set_a%nsgf_set
     610       32108 :          rpgfa => basis_set_a%pgf_radius
     611       32108 :          set_radius_a => basis_set_a%set_radius
     612       32108 :          sphi_a => basis_set_a%sphi
     613       32108 :          zeta => basis_set_a%zet
     614             : 
     615       32108 :          ra(:) = pbc(particle_set(iatom)%r, cell)
     616             : 
     617       32108 :          force_a(:) = 0.0_dp
     618       32108 :          force_b(:) = 0.0_dp
     619       32108 :          IF (use_virial) THEN
     620        6506 :             my_virial_a = 0.0_dp
     621        6506 :             my_virial_b = 0.0_dp
     622             :          END IF
     623             : 
     624      337559 :          DO iset = 1, nseta
     625      305451 :             ncoa = npgfa(iset)*ncoset(la_max(iset))
     626      305451 :             sgfa = first_sgfa(1, iset)
     627             : 
     628      916353 :             ALLOCATE (I_tmp2(ncoa, 1))
     629     2165580 :             I_tmp2 = 0.0_dp
     630      916353 :             ALLOCATE (I_ab(nsgfa(iset), 1))
     631     1485748 :             I_ab = 0.0_dp
     632      916353 :             ALLOCATE (pab(ncoa, 1))
     633     2165580 :             pab = 0.0_dp
     634             : 
     635      305451 :             skip_shell = .TRUE.
     636     1180297 :             DO iorb = 1, nsgfa(iset)
     637     1180297 :                IF (iorb + offset == LLL) THEN
     638       10294 :                   I_ab(iorb, 1) = 1.0_dp
     639       10294 :                   skip_shell = .FALSE.
     640             :                END IF
     641             :             END DO
     642             : 
     643      305451 :             IF (skip_shell) THEN
     644      295157 :                offset = offset + nsgfa(iset)
     645      295157 :                DEALLOCATE (I_tmp2)
     646      295157 :                DEALLOCATE (I_ab)
     647      295157 :                DEALLOCATE (pab)
     648      295157 :                CYCLE
     649             :             END IF
     650             : 
     651             :             CALL dgemm("N", "N", ncoa, 1, nsgfa(iset), &
     652             :                        1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     653             :                        I_ab(1, 1), SIZE(I_ab, 1), &
     654       10294 :                        0.0_dp, pab(1, 1), SIZE(pab, 1))
     655       10294 :             DEALLOCATE (I_ab)
     656             : 
     657       31296 :             igrid_level = gaussian_gridlevel(pw_env_sub%gridlevel_info, MINVAL(zeta(:, iset)))
     658       10294 :             map_it_here = .FALSE.
     659       41176 :             use_subpatch = .NOT. ALL(rs_v(igrid_level)%desc%perd == 1)
     660             : 
     661       10294 :             IF (map_gaussian_here(rs_v(igrid_level), cell%h_inv, ra, offset, para_env_sub%num_pe, para_env_sub%mepos)) THEN
     662       19916 :                DO ipgf = 1, npgfa(iset)
     663       10120 :                   na1 = (ipgf - 1)*ncoset(la_max(iset)) + 1
     664       10120 :                   na2 = ipgf*ncoset(la_max(iset))
     665       10120 :                   igrid_level = gaussian_gridlevel(pw_env_sub%gridlevel_info, zeta(ipgf, iset))
     666             : 
     667             :                   radius = exp_radius_very_extended(la_min=la_min(iset), la_max=la_max(iset), &
     668             :                                                     lb_min=0, lb_max=0, ra=ra, rb=ra, rp=ra, &
     669             :                                                     zetp=zeta(ipgf, iset), &
     670             :                                                     eps=dft_control%qs_control%eps_gvg_rspace, &
     671       10120 :                                                     prefactor=1.0_dp, cutoff=1.0_dp)
     672             : 
     673             :                   CALL integrate_pgf_product(la_max=la_max(iset), zeta=zeta(ipgf, iset)/2.0_dp, la_min=la_min(iset), &
     674             :                                              lb_max=0, zetb=zeta(ipgf, iset)/2.0_dp, lb_min=0, &
     675             :                                              ra=ra, rab=(/0.0_dp, 0.0_dp, 0.0_dp/), &
     676             :                                              rsgrid=rs_v(igrid_level), &
     677             :                                              hab=I_tmp2, &
     678             :                                              pab=pab, &
     679             :                                              o1=na1 - 1, &
     680             :                                              o2=0, &
     681             :                                              radius=radius, &
     682             :                                              calculate_forces=.TRUE., &
     683             :                                              force_a=force_a, force_b=force_b, &
     684             :                                              use_virial=use_virial, &
     685             :                                              my_virial_a=my_virial_a, &
     686             :                                              my_virial_b=my_virial_b, &
     687             :                                              use_subpatch=use_subpatch, &
     688       19916 :                                              subpatch_pattern=0)
     689             :                END DO
     690             :             END IF
     691             : 
     692       10294 :             DEALLOCATE (I_tmp2)
     693       10294 :             DEALLOCATE (pab)
     694             : 
     695       42402 :             offset = offset + nsgfa(iset)
     696             : 
     697             :          END DO
     698             : 
     699             :          force(ikind)%rho_elec(:, atom_a) = &
     700      128432 :             force(ikind)%rho_elec(:, atom_a) + force_a(:) + force_b(:)
     701       42402 :          IF (use_virial) THEN
     702       84578 :             h_stress = h_stress + my_virial_a + my_virial_b
     703             :          END IF
     704             :       END DO
     705             : 
     706       10294 :       CALL timestop(handle)
     707             : 
     708       20588 :    END SUBROUTINE integrate_potential_forces_3c_2c
     709             : 
     710             : ! **************************************************************************************************
     711             : !> \brief Calculates stress tensor contribution from the operator
     712             : !> \param rho_g_copy ...
     713             : !> \param pot_g ...
     714             : !> \param rho_g ...
     715             : !> \param dvg ...
     716             : !> \param h_stress ...
     717             : !> \param potential_parameter ...
     718             : !> \param para_env_sub ...
     719             : ! **************************************************************************************************
     720        4290 :    SUBROUTINE virial_gpw_potential(rho_g_copy, pot_g, rho_g, dvg, h_stress, potential_parameter, para_env_sub)
     721             : 
     722             :       TYPE(pw_c1d_gs_type), INTENT(IN)                   :: rho_g_copy, pot_g
     723             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rho_g
     724             :       TYPE(pw_c1d_gs_type), INTENT(IN)                   :: dvg(3)
     725             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT)      :: h_stress
     726             :       TYPE(libint_potential_type), INTENT(IN)            :: potential_parameter
     727             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env_sub
     728             : 
     729             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'virial_gpw_potential'
     730             : 
     731             :       INTEGER                                            :: alpha, beta, handle
     732             :       INTEGER, DIMENSION(3)                              :: comp
     733             :       REAL(KIND=dp)                                      :: e_hartree
     734             : 
     735             :       ! add the volume contribution
     736        4290 :       CALL timeset(routineN, handle)
     737        4290 :       e_hartree = 0.0_dp
     738        4290 :       e_hartree = pw_integral_ab(rho_g_copy, pot_g)
     739             : 
     740       17160 :       DO alpha = 1, 3
     741       12870 :          comp = 0
     742       12870 :          comp(alpha) = 1
     743       12870 :          CALL pw_copy(pot_g, rho_g)
     744       12870 :          CALL pw_derive(rho_g, comp)
     745       12870 :          CALL factor_virial_gpw(rho_g, potential_parameter)
     746       12870 :          h_stress(alpha, alpha) = h_stress(alpha, alpha) - e_hartree/REAL(para_env_sub%num_pe, dp)
     747       42900 :          DO beta = alpha, 3
     748             :             h_stress(alpha, beta) = h_stress(alpha, beta) &
     749       25740 :                                     - 2.0_dp*pw_integral_ab(rho_g, dvg(beta))/fourpi/REAL(para_env_sub%num_pe, dp)
     750       38610 :             h_stress(beta, alpha) = h_stress(alpha, beta)
     751             :          END DO
     752             :       END DO
     753             : 
     754        4290 :       CALL timestop(handle)
     755        4290 :    END SUBROUTINE virial_gpw_potential
     756             : 
     757             : ! **************************************************************************************************
     758             : !> \brief Multiplies a potential in g space with the factor ln(V(g)/Vc(g))' with Vc(g) being the
     759             : !>        Fourier-transformed of the Coulomg potential
     760             : !> \param pw ...
     761             : !> \param potential_parameter parameters of potential V(g)
     762             : ! **************************************************************************************************
     763       12870 :    SUBROUTINE factor_virial_gpw(pw, potential_parameter)
     764             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: pw
     765             :       TYPE(libint_potential_type), INTENT(IN)            :: potential_parameter
     766             : 
     767       12870 :       SELECT CASE (potential_parameter%potential_type)
     768             :       CASE (do_potential_coulomb)
     769        1329 :          RETURN
     770             :       CASE (do_potential_long)
     771        1329 :          CALL pw_log_deriv_gauss(pw, potential_parameter%omega)
     772             :       CASE (do_potential_short)
     773           0 :          CALL pw_log_deriv_compl_gauss(pw, potential_parameter%omega)
     774             :       CASE (do_potential_mix_cl)
     775             :          CALL pw_log_deriv_mix_cl(pw, potential_parameter%omega, &
     776         249 :                                   potential_parameter%scale_coulomb, potential_parameter%scale_longrange)
     777             :       CASE (do_potential_truncated)
     778           0 :          CALL pw_log_deriv_trunc(pw, potential_parameter%cutoff_radius)
     779             :       CASE (do_potential_id)
     780           0 :          CALL pw_zero(pw)
     781             :       CASE DEFAULT
     782       12870 :          CPABORT("Unknown potential type")
     783             :       END SELECT
     784             : 
     785             :    END SUBROUTINE factor_virial_gpw
     786             : 
     787             : ! **************************************************************************************************
     788             : !> \brief Integrate potential of RI function with RI function
     789             : !> \param pw_env_sub ...
     790             : !> \param pot_r ...
     791             : !> \param kind_of ...
     792             : !> \param atom_of_kind ...
     793             : !> \param particle_set ...
     794             : !> \param qs_kind_set ...
     795             : !> \param G_PQ_local ...
     796             : !> \param cell ...
     797             : !> \param force ...
     798             : !> \param use_virial ...
     799             : !> \param h_stress ...
     800             : !> \param para_env_sub ...
     801             : !> \param dft_control ...
     802             : ! **************************************************************************************************
     803       10792 :    SUBROUTINE integrate_potential(pw_env_sub, pot_r, kind_of, atom_of_kind, particle_set, qs_kind_set, &
     804       10792 :                                   G_PQ_local, cell, force, use_virial, h_stress, para_env_sub, dft_control)
     805             : 
     806             :       TYPE(pw_env_type), INTENT(IN), POINTER             :: pw_env_sub
     807             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: pot_r
     808             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: kind_of, atom_of_kind
     809             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     810             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     811             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: G_PQ_local
     812             :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
     813             :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     814             :       LOGICAL, INTENT(IN)                                :: use_virial
     815             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT)      :: h_stress
     816             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env_sub
     817             :       TYPE(dft_control_type), INTENT(IN), POINTER        :: dft_control
     818             : 
     819             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'integrate_potential'
     820             : 
     821             :       INTEGER                                            :: atom_a, handle, iatom, igrid_level, &
     822             :                                                             ikind, ipgf, iset, na1, na2, ncoa, &
     823             :                                                             nseta, offset, sgfa
     824       10792 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, npgfa, nsgfa
     825       10792 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa
     826             :       LOGICAL                                            :: use_subpatch
     827             :       REAL(KIND=dp)                                      :: radius
     828       10792 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: I_ab
     829             :       REAL(KIND=dp), DIMENSION(3)                        :: force_a, force_b, ra
     830             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: my_virial_a, my_virial_b
     831       10792 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a
     832       10792 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: I_tmp2, pab, rpgfa, sphi_a, zeta
     833             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a
     834             :       TYPE(realspace_grid_desc_p_type), DIMENSION(:), &
     835       10792 :          POINTER                                         :: rs_descs
     836       10792 :       TYPE(realspace_grid_type), DIMENSION(:), POINTER   :: rs_v
     837             : 
     838       10792 :       CALL timeset(routineN, handle)
     839             : 
     840       10792 :       NULLIFY (rs_v)
     841       10792 :       NULLIFY (rs_descs)
     842       10792 :       CALL pw_env_get(pw_env_sub, rs_descs=rs_descs, rs_grids=rs_v)
     843       10792 :       CALL potential_pw2rs(rs_v, pot_r, pw_env_sub)
     844             : 
     845       10792 :       offset = 0
     846       44394 :       DO iatom = 1, SIZE(kind_of)
     847       33602 :          ikind = kind_of(iatom)
     848       33602 :          atom_a = atom_of_kind(iatom)
     849             :          CALL get_qs_kind(qs_kind=qs_kind_set(ikind), basis_set=basis_set_a, &
     850       33602 :                           basis_type="RI_AUX")
     851             : 
     852       33602 :          first_sgfa => basis_set_a%first_sgf
     853       33602 :          la_max => basis_set_a%lmax
     854       33602 :          la_min => basis_set_a%lmin
     855       33602 :          npgfa => basis_set_a%npgf
     856       33602 :          nseta = basis_set_a%nset
     857       33602 :          nsgfa => basis_set_a%nsgf_set
     858       33602 :          rpgfa => basis_set_a%pgf_radius
     859       33602 :          set_radius_a => basis_set_a%set_radius
     860       33602 :          sphi_a => basis_set_a%sphi
     861       33602 :          zeta => basis_set_a%zet
     862             : 
     863       33602 :          ra(:) = pbc(particle_set(iatom)%r, cell)
     864             : 
     865       33602 :          force_a(:) = 0.0_dp
     866       33602 :          force_b(:) = 0.0_dp
     867       33602 :          IF (use_virial) THEN
     868        7004 :             my_virial_a = 0.0_dp
     869        7004 :             my_virial_b = 0.0_dp
     870             :          END IF
     871             : 
     872      353495 :          DO iset = 1, nseta
     873      319893 :             ncoa = npgfa(iset)*ncoset(la_max(iset))
     874      319893 :             sgfa = first_sgfa(1, iset)
     875             : 
     876      959679 :             ALLOCATE (I_tmp2(ncoa, 1))
     877     2268168 :             I_tmp2 = 0.0_dp
     878      959679 :             ALLOCATE (I_ab(nsgfa(iset), 1))
     879     1555966 :             I_ab = 0.0_dp
     880      959679 :             ALLOCATE (pab(ncoa, 1))
     881     2268168 :             pab = 0.0_dp
     882             : 
     883     1236073 :             I_ab(1:nsgfa(iset), 1) = -4.0_dp*G_PQ_local(offset + 1:offset + nsgfa(iset))
     884             : 
     885             :             CALL dgemm("N", "N", ncoa, 1, nsgfa(iset), &
     886             :                        1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
     887             :                        I_ab(1, 1), SIZE(I_ab, 1), &
     888      319893 :                        0.0_dp, pab(1, 1), SIZE(pab, 1))
     889             : 
     890     1555966 :             I_ab = 0.0_dp
     891             : 
     892      961335 :             igrid_level = gaussian_gridlevel(pw_env_sub%gridlevel_info, MINVAL(zeta(:, iset)))
     893     1279572 :             use_subpatch = .NOT. ALL(rs_v(igrid_level)%desc%perd == 1)
     894             : 
     895      319893 :             IF (map_gaussian_here(rs_v(igrid_level), cell%h_inv, ra, offset, para_env_sub%num_pe, para_env_sub%mepos)) THEN
     896      611730 :                DO ipgf = 1, npgfa(iset)
     897      306279 :                   na1 = (ipgf - 1)*ncoset(la_max(iset)) + 1
     898      306279 :                   na2 = ipgf*ncoset(la_max(iset))
     899      306279 :                   igrid_level = gaussian_gridlevel(pw_env_sub%gridlevel_info, zeta(ipgf, iset))
     900             : 
     901             :                   radius = exp_radius_very_extended(la_min=la_min(iset), la_max=la_max(iset), &
     902             :                                                     lb_min=0, lb_max=0, ra=ra, rb=ra, rp=ra, &
     903             :                                                     zetp=zeta(ipgf, iset), &
     904             :                                                     eps=dft_control%qs_control%eps_gvg_rspace, &
     905      306279 :                                                     prefactor=1.0_dp, cutoff=1.0_dp)
     906             : 
     907             :                   CALL integrate_pgf_product(la_max=la_max(iset), zeta=zeta(ipgf, iset)/2.0_dp, la_min=la_min(iset), &
     908             :                                              lb_max=0, zetb=zeta(ipgf, iset)/2.0_dp, lb_min=0, &
     909             :                                              ra=ra, rab=(/0.0_dp, 0.0_dp, 0.0_dp/), &
     910             :                                              rsgrid=rs_v(igrid_level), &
     911             :                                              hab=I_tmp2, &
     912             :                                              pab=pab, &
     913             :                                              o1=na1 - 1, &
     914             :                                              o2=0, &
     915             :                                              radius=radius, &
     916             :                                              calculate_forces=.TRUE., &
     917             :                                              force_a=force_a, force_b=force_b, &
     918             :                                              use_virial=use_virial, &
     919             :                                              my_virial_a=my_virial_a, &
     920             :                                              my_virial_b=my_virial_b, &
     921             :                                              use_subpatch=use_subpatch, &
     922      611730 :                                              subpatch_pattern=0)
     923             : 
     924             :                END DO
     925             : 
     926             :             END IF
     927             : 
     928      319893 :             DEALLOCATE (I_tmp2)
     929      319893 :             DEALLOCATE (I_ab)
     930      319893 :             DEALLOCATE (pab)
     931             : 
     932      353495 :             offset = offset + nsgfa(iset)
     933             : 
     934             :          END DO
     935             : 
     936             :          force(ikind)%rho_elec(:, atom_a) = &
     937      134408 :             force(ikind)%rho_elec(:, atom_a) + force_a(:) + force_b
     938       44394 :          IF (use_virial) THEN
     939       91052 :             h_stress = h_stress + my_virial_a + my_virial_b
     940             :          END IF
     941             :       END DO
     942             : 
     943       10792 :       CALL timestop(handle)
     944             : 
     945       21584 :    END SUBROUTINE
     946             : 
     947             : ! **************************************************************************************************
     948             : !> \brief Prepares GPW calculation for RI-MP2/RI-RPA
     949             : !> \param qs_env ...
     950             : !> \param dft_control ...
     951             : !> \param e_cutoff_old ...
     952             : !> \param cutoff_old ...
     953             : !> \param relative_cutoff_old ...
     954             : !> \param para_env_sub ...
     955             : !> \param pw_env_sub ...
     956             : !> \param auxbas_pw_pool ...
     957             : !> \param poisson_env ...
     958             : !> \param task_list_sub ...
     959             : !> \param rho_r ...
     960             : !> \param rho_g ...
     961             : !> \param pot_g ...
     962             : !> \param psi_L ...
     963             : !> \param sab_orb_sub ...
     964             : ! **************************************************************************************************
     965         950 :    SUBROUTINE prepare_gpw(qs_env, dft_control, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_sub, pw_env_sub, &
     966             :                           auxbas_pw_pool, poisson_env, task_list_sub, rho_r, rho_g, pot_g, psi_L, sab_orb_sub)
     967             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     968             :       TYPE(dft_control_type), INTENT(IN), POINTER        :: dft_control
     969             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     970             :          INTENT(OUT)                                     :: e_cutoff_old
     971             :       REAL(KIND=dp), INTENT(OUT)                         :: cutoff_old, relative_cutoff_old
     972             :       TYPE(mp_para_env_type), INTENT(IN), POINTER        :: para_env_sub
     973             :       TYPE(pw_env_type), POINTER                         :: pw_env_sub
     974             :       TYPE(pw_pool_type), INTENT(IN), POINTER            :: auxbas_pw_pool
     975             :       TYPE(pw_poisson_type), INTENT(IN), POINTER         :: poisson_env
     976             :       TYPE(task_list_type), POINTER                      :: task_list_sub
     977             :       TYPE(pw_r3d_rs_type), INTENT(OUT)                  :: rho_r
     978             :       TYPE(pw_c1d_gs_type), INTENT(OUT)                  :: rho_g, pot_g
     979             :       TYPE(pw_r3d_rs_type), INTENT(OUT)                  :: psi_L
     980             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     981             :          INTENT(IN), POINTER                             :: sab_orb_sub
     982             : 
     983             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'prepare_gpw'
     984             : 
     985             :       INTEGER                                            :: handle, i_multigrid, n_multigrid
     986             :       LOGICAL                                            :: skip_load_balance_distributed
     987             :       REAL(KIND=dp)                                      :: progression_factor
     988             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     989             : 
     990         950 :       CALL timeset(routineN, handle)
     991             : 
     992         950 :       CALL get_qs_env(qs_env, dft_control=dft_control, ks_env=ks_env)
     993             : 
     994             :       ! hack hack hack XXXXXXXXXXXXXXX rebuilds the pw_en with the new cutoffs
     995         950 :       progression_factor = dft_control%qs_control%progression_factor
     996         950 :       n_multigrid = SIZE(dft_control%qs_control%e_cutoff)
     997        2850 :       ALLOCATE (e_cutoff_old(n_multigrid))
     998        4750 :       e_cutoff_old(:) = dft_control%qs_control%e_cutoff
     999         950 :       cutoff_old = dft_control%qs_control%cutoff
    1000             : 
    1001         950 :       dft_control%qs_control%cutoff = qs_env%mp2_env%mp2_gpw%cutoff*0.5_dp
    1002         950 :       dft_control%qs_control%e_cutoff(1) = dft_control%qs_control%cutoff
    1003        3800 :       DO i_multigrid = 2, n_multigrid
    1004             :          dft_control%qs_control%e_cutoff(i_multigrid) = dft_control%qs_control%e_cutoff(i_multigrid - 1) &
    1005        3800 :                                                         /progression_factor
    1006             :       END DO
    1007             : 
    1008         950 :       relative_cutoff_old = dft_control%qs_control%relative_cutoff
    1009         950 :       dft_control%qs_control%relative_cutoff = qs_env%mp2_env%mp2_gpw%relative_cutoff*0.5_dp
    1010             : 
    1011             :       ! a pw_env
    1012         950 :       NULLIFY (pw_env_sub)
    1013         950 :       CALL pw_env_create(pw_env_sub)
    1014         950 :       CALL pw_env_rebuild(pw_env_sub, qs_env, para_env_sub)
    1015             : 
    1016             :       CALL pw_env_get(pw_env_sub, auxbas_pw_pool=auxbas_pw_pool, &
    1017         950 :                       poisson_env=poisson_env)
    1018             :       ! hack hack hack XXXXXXXXXXXXXXX
    1019             : 
    1020             :       ! now we need a task list, hard code skip_load_balance_distributed
    1021         950 :       NULLIFY (task_list_sub)
    1022         950 :       skip_load_balance_distributed = dft_control%qs_control%skip_load_balance_distributed
    1023         950 :       CALL allocate_task_list(task_list_sub)
    1024             :       CALL generate_qs_task_list(ks_env, task_list_sub, &
    1025             :                                  reorder_rs_grid_ranks=.TRUE., soft_valid=.FALSE., &
    1026             :                                  skip_load_balance_distributed=skip_load_balance_distributed, &
    1027         950 :                                  pw_env_external=pw_env_sub, sab_orb_external=sab_orb_sub)
    1028             : 
    1029             :       ! get some of the grids ready
    1030         950 :       CALL auxbas_pw_pool%create_pw(rho_r)
    1031         950 :       CALL auxbas_pw_pool%create_pw(rho_g)
    1032         950 :       CALL auxbas_pw_pool%create_pw(pot_g)
    1033         950 :       CALL auxbas_pw_pool%create_pw(psi_L)
    1034             : 
    1035             :       ! run the FFT once, to set up buffers and to take into account the memory
    1036         950 :       CALL pw_zero(rho_r)
    1037         950 :       CALL pw_transfer(rho_r, rho_g)
    1038             : 
    1039         950 :       CALL timestop(handle)
    1040             : 
    1041         950 :    END SUBROUTINE prepare_gpw
    1042             : 
    1043             : ! **************************************************************************************************
    1044             : !> \brief Cleanup GPW integration for RI-MP2/RI-RPA
    1045             : !> \param qs_env ...
    1046             : !> \param e_cutoff_old ...
    1047             : !> \param cutoff_old ...
    1048             : !> \param relative_cutoff_old ...
    1049             : !> \param para_env_sub ...
    1050             : !> \param pw_env_sub ...
    1051             : !> \param task_list_sub ...
    1052             : !> \param auxbas_pw_pool ...
    1053             : !> \param rho_r ...
    1054             : !> \param rho_g ...
    1055             : !> \param pot_g ...
    1056             : !> \param psi_L ...
    1057             : ! **************************************************************************************************
    1058         950 :    SUBROUTINE cleanup_gpw(qs_env, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_sub, pw_env_sub, &
    1059             :                           task_list_sub, auxbas_pw_pool, rho_r, rho_g, pot_g, psi_L)
    1060             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
    1061             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    1062             :          INTENT(IN)                                      :: e_cutoff_old
    1063             :       REAL(KIND=dp), INTENT(IN)                          :: cutoff_old, relative_cutoff_old
    1064             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env_sub
    1065             :       TYPE(pw_env_type), POINTER                         :: pw_env_sub
    1066             :       TYPE(task_list_type), POINTER                      :: task_list_sub
    1067             :       TYPE(pw_pool_type), INTENT(IN), POINTER            :: auxbas_pw_pool
    1068             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: rho_r
    1069             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rho_g, pot_g
    1070             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: psi_L
    1071             : 
    1072             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'cleanup_gpw'
    1073             : 
    1074             :       INTEGER                                            :: handle
    1075             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1076             : 
    1077         950 :       CALL timeset(routineN, handle)
    1078             : 
    1079             :       ! and now free the whole lot
    1080         950 :       CALL auxbas_pw_pool%give_back_pw(rho_r)
    1081         950 :       CALL auxbas_pw_pool%give_back_pw(rho_g)
    1082         950 :       CALL auxbas_pw_pool%give_back_pw(pot_g)
    1083         950 :       CALL auxbas_pw_pool%give_back_pw(psi_L)
    1084             : 
    1085         950 :       CALL deallocate_task_list(task_list_sub)
    1086         950 :       CALL pw_env_release(pw_env_sub, para_env=para_env_sub)
    1087             : 
    1088         950 :       CALL get_qs_env(qs_env, dft_control=dft_control)
    1089             : 
    1090             :       ! restore the initial value of the cutoff
    1091        4750 :       dft_control%qs_control%e_cutoff = e_cutoff_old
    1092         950 :       dft_control%qs_control%cutoff = cutoff_old
    1093         950 :       dft_control%qs_control%relative_cutoff = relative_cutoff_old
    1094             : 
    1095         950 :       CALL timestop(handle)
    1096             : 
    1097         950 :    END SUBROUTINE cleanup_gpw
    1098             : 
    1099             : ! **************************************************************************************************
    1100             : !> \brief Calculates potential from a given density in g-space
    1101             : !> \param pot_r on output: potential in r space
    1102             : !> \param rho_g on input: rho in g space
    1103             : !> \param poisson_env ...
    1104             : !> \param pot_g on output: potential in g space
    1105             : !> \param potential_parameter Potential parameters, if not provided, assume Coulomb potential
    1106             : !> \param dvg in output: first derivatives of the corresponding Coulomb potential
    1107             : !> \param no_transfer whether NOT to transform potential from g-space to r-space (default: do it)
    1108             : ! **************************************************************************************************
    1109       54858 :    SUBROUTINE calc_potential_gpw(pot_r, rho_g, poisson_env, pot_g, potential_parameter, dvg, no_transfer)
    1110             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: pot_r
    1111             :       TYPE(pw_c1d_gs_type), INTENT(IN)                   :: rho_g
    1112             :       TYPE(pw_poisson_type), INTENT(IN), POINTER         :: poisson_env
    1113             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: pot_g
    1114             :       TYPE(libint_potential_type), INTENT(IN), OPTIONAL  :: potential_parameter
    1115             :       TYPE(pw_c1d_gs_type), DIMENSION(3), &
    1116             :          INTENT(INOUT), OPTIONAL                         :: dvg
    1117             :       LOGICAL, INTENT(IN), OPTIONAL                      :: no_transfer
    1118             : 
    1119             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calc_potential_gpw'
    1120             : 
    1121             :       INTEGER                                            :: comp(3), handle, idir, my_potential_type
    1122             :       LOGICAL                                            :: my_transfer
    1123             : 
    1124       54858 :       CALL timeset(routineN, handle)
    1125             : 
    1126       54858 :       my_potential_type = do_potential_coulomb
    1127       54858 :       IF (PRESENT(potential_parameter)) THEN
    1128       54858 :          my_potential_type = potential_parameter%potential_type
    1129             :       END IF
    1130             : 
    1131       54858 :       my_transfer = .TRUE.
    1132       54858 :       IF (PRESENT(no_transfer)) my_transfer = .NOT. no_transfer
    1133             : 
    1134             :       ! in case we do Coulomb metric for RI, we need the Coulomb operator, but for RI with the
    1135             :       ! overlap metric, we do not need the Coulomb operator
    1136       54858 :       IF (my_potential_type /= do_potential_id) THEN
    1137       53862 :          IF (PRESENT(dvg)) THEN
    1138        2311 :             CALL pw_poisson_solve(poisson_env, rho_g, vhartree=pot_g, dvhartree=dvg)
    1139             :          ELSE
    1140       51551 :             CALL pw_poisson_solve(poisson_env, rho_g, vhartree=pot_g)
    1141             :          END IF
    1142       53862 :          IF (my_potential_type == do_potential_long) CALL pw_gauss_damp(pot_g, potential_parameter%omega)
    1143       53862 :          IF (my_potential_type == do_potential_short) CALL pw_compl_gauss_damp(pot_g, potential_parameter%omega)
    1144       53862 :          IF (my_potential_type == do_potential_truncated) CALL pw_truncated(pot_g, potential_parameter%cutoff_radius)
    1145       53862 :          IF (my_potential_type == do_potential_mix_cl) CALL pw_gauss_damp_mix(pot_g, potential_parameter%omega, &
    1146             :                                                                               potential_parameter%scale_coulomb, &
    1147         332 :                                                                               potential_parameter%scale_longrange)
    1148       53862 :          IF (my_transfer) CALL pw_transfer(pot_g, pot_r)
    1149             :       ELSE
    1150             :          ! If we use an overlap metric, make sure to use the correct potential=density on output
    1151         996 :          CALL pw_copy(rho_g, pot_g)
    1152         996 :          IF (PRESENT(dvg)) THEN
    1153           0 :          DO idir = 1, 3
    1154           0 :             CALL pw_copy(pot_g, dvg(idir))
    1155           0 :             comp = 0
    1156           0 :             comp(idir) = 1
    1157           0 :             CALL pw_derive(dvg(idir), comp)
    1158             :          END DO
    1159             :          END IF
    1160         996 :          IF (my_transfer) CALL pw_transfer(rho_g, pot_r)
    1161             :       END IF
    1162             : 
    1163       54858 :       IF (my_transfer) CALL pw_scale(pot_r, pot_r%pw_grid%dvol)
    1164       54858 :       CALL timestop(handle)
    1165             : 
    1166       54858 :    END SUBROUTINE calc_potential_gpw
    1167             : 
    1168             : END MODULE mp2_eri_gpw

Generated by: LCOV version 1.15