LCOV - code coverage report
Current view: top level - src - accint_weights_forces.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:70636b1) Lines: 92.3 % 143 132
Test Date: 2026-02-11 07:00:35 Functions: 100.0 % 3 3

            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
      10              : !> \author JGH (01.2026)
      11              : ! **************************************************************************************************
      12              : MODULE accint_weights_forces
      13              :    USE ao_util,                         ONLY: exp_radius_very_extended
      14              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      15              :                                               get_atomic_kind
      16              :    USE cell_types,                      ONLY: cell_type,&
      17              :                                               pbc
      18              :    USE cp_control_types,                ONLY: dft_control_type
      19              :    USE grid_api,                        ONLY: integrate_pgf_product
      20              :    USE input_constants,                 ONLY: sic_none,&
      21              :                                               xc_none
      22              :    USE input_section_types,             ONLY: section_vals_type,&
      23              :                                               section_vals_val_get
      24              :    USE kinds,                           ONLY: dp
      25              :    USE memory_utilities,                ONLY: reallocate
      26              :    USE particle_types,                  ONLY: particle_type
      27              :    USE pw_env_types,                    ONLY: pw_env_get,&
      28              :                                               pw_env_type
      29              :    USE pw_grids,                        ONLY: pw_grid_compare
      30              :    USE pw_methods,                      ONLY: pw_axpy,&
      31              :                                               pw_multiply_with,&
      32              :                                               pw_scale,&
      33              :                                               pw_zero
      34              :    USE pw_pool_types,                   ONLY: pw_pool_type
      35              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      36              :                                               pw_r3d_rs_type
      37              :    USE qs_environment_types,            ONLY: get_qs_env,&
      38              :                                               qs_environment_type
      39              :    USE qs_force_types,                  ONLY: qs_force_type
      40              :    USE qs_fxc,                          ONLY: qs_fxc_analytic
      41              :    USE qs_ks_types,                     ONLY: get_ks_env,&
      42              :                                               qs_ks_env_type
      43              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      44              :                                               qs_rho_type
      45              :    USE realspace_grid_types,            ONLY: realspace_grid_type,&
      46              :                                               transfer_pw2rs
      47              :    USE virial_types,                    ONLY: virial_type
      48              :    USE xc,                              ONLY: xc_exc_pw_create,&
      49              :                                               xc_vxc_pw_create
      50              : #include "./base/base_uses.f90"
      51              : 
      52              :    IMPLICIT NONE
      53              : 
      54              :    PRIVATE
      55              : 
      56              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .FALSE.
      57              : 
      58              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'accint_weights_forces'
      59              : 
      60              :    PUBLIC :: accint_weight_force
      61              : 
      62              : CONTAINS
      63              : 
      64              : ! **************************************************************************************************
      65              : !> \brief ...
      66              : !> \param qs_env ...
      67              : !> \param rho ...
      68              : !> \param rho1 ...
      69              : !> \param order ...
      70              : !> \param xc_section ...
      71              : !> \param triplet ...
      72              : ! **************************************************************************************************
      73         6577 :    SUBROUTINE accint_weight_force(qs_env, rho, rho1, order, xc_section, triplet)
      74              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      75              :       TYPE(qs_rho_type), POINTER                         :: rho, rho1
      76              :       INTEGER, INTENT(IN)                                :: order
      77              :       TYPE(section_vals_type), POINTER                   :: xc_section
      78              :       LOGICAL, INTENT(IN), OPTIONAL                      :: triplet
      79              : 
      80              :       CHARACTER(len=*), PARAMETER :: routineN = 'accint_weight_force'
      81              : 
      82              :       INTEGER                                            :: atom_a, handle, iatom, ikind, natom, &
      83              :                                                             natom_of_kind, nkind
      84         6577 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list
      85              :       LOGICAL                                            :: lr_triplet, use_virial
      86         6577 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: calpha, cvalue
      87         6577 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: aforce
      88              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: avirial
      89         6577 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
      90              :       TYPE(dft_control_type), POINTER                    :: dft_control
      91              :       TYPE(pw_env_type), POINTER                         :: pw_env
      92              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
      93              :       TYPE(pw_r3d_rs_type)                               :: e_rspace
      94         6577 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
      95              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
      96              :       TYPE(virial_type), POINTER                         :: virial
      97              : 
      98         6577 :       CALL timeset(routineN, handle)
      99              : 
     100         6577 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     101              : 
     102         6577 :       IF (dft_control%qs_control%gapw_control%accurate_xcint) THEN
     103              : 
     104          278 :          CALL get_qs_env(qs_env=qs_env, force=force, virial=virial)
     105          278 :          use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     106              : 
     107          278 :          CALL get_qs_env(qs_env, natom=natom, nkind=nkind)
     108          834 :          ALLOCATE (aforce(3, natom))
     109         1390 :          ALLOCATE (calpha(nkind), cvalue(nkind))
     110          896 :          cvalue = 1.0_dp
     111          896 :          calpha(1:nkind) = dft_control%qs_control%gapw_control%aw(1:nkind)
     112              : 
     113          278 :          CALL get_qs_env(qs_env, ks_env=ks_env, pw_env=pw_env)
     114          278 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     115          278 :          CALL auxbas_pw_pool%create_pw(e_rspace)
     116              : 
     117          278 :          lr_triplet = .FALSE.
     118          278 :          IF (PRESENT(triplet)) lr_triplet = triplet
     119              : 
     120          278 :          CALL xc_density(ks_env, rho, rho1, order, xc_section, lr_triplet, e_rspace)
     121          278 :          CALL pw_scale(e_rspace, e_rspace%pw_grid%dvol)
     122              : 
     123          278 :          CALL gauss_grid_force(e_rspace, qs_env, calpha, cvalue, aforce, avirial)
     124              : 
     125          278 :          CALL auxbas_pw_pool%give_back_pw(e_rspace)
     126              : 
     127          278 :          CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set)
     128          896 :          DO ikind = 1, nkind
     129          618 :             CALL get_atomic_kind(atomic_kind_set(ikind), natom=natom_of_kind, atom_list=atom_list)
     130         1734 :             DO iatom = 1, natom_of_kind
     131          838 :                atom_a = atom_list(iatom)
     132              :                force(ikind)%rho_elec(1:3, iatom) = &
     133         3970 :                   force(ikind)%rho_elec(1:3, iatom) + aforce(1:3, atom_a)
     134              :             END DO
     135              :          END DO
     136          278 :          IF (use_virial) THEN
     137            0 :             virial%pv_exc = virial%pv_exc + avirial
     138            0 :             virial%pv_virial = virial%pv_virial + avirial
     139              :          END IF
     140              : 
     141          278 :          DEALLOCATE (aforce)
     142              : 
     143              :       END IF
     144              : 
     145         6577 :       CALL timestop(handle)
     146              : 
     147        13154 :    END SUBROUTINE accint_weight_force
     148              : 
     149              : ! **************************************************************************************************
     150              : !> \brief computes the forces/virial due to atomic centered Gaussian functions
     151              : !> \param e_rspace Energy density
     152              : !> \param qs_env ...
     153              : !> \param calpha ...
     154              : !> \param cvalue ...
     155              : !> \param aforce ...
     156              : !> \param avirial ...
     157              : ! **************************************************************************************************
     158          278 :    SUBROUTINE gauss_grid_force(e_rspace, qs_env, calpha, cvalue, aforce, avirial)
     159              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: e_rspace
     160              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     161              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: calpha, cvalue
     162              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: aforce
     163              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(OUT)        :: avirial
     164              : 
     165              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'gauss_grid_force'
     166              : 
     167              :       INTEGER                                            :: atom_a, handle, iatom, ikind, j, &
     168              :                                                             natom_of_kind, npme
     169          278 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list, cores
     170              :       LOGICAL                                            :: use_virial
     171              :       REAL(KIND=dp)                                      :: alpha, eps_rho_rspace, radius
     172              :       REAL(KIND=dp), DIMENSION(3)                        :: force_a, force_b, ra
     173              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: my_virial_a, my_virial_b
     174          278 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: hab, pab
     175          278 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     176              :       TYPE(cell_type), POINTER                           :: cell
     177              :       TYPE(dft_control_type), POINTER                    :: dft_control
     178          278 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     179              :       TYPE(pw_env_type), POINTER                         :: pw_env
     180              :       TYPE(realspace_grid_type), POINTER                 :: rs_v
     181              : 
     182          278 :       CALL timeset(routineN, handle)
     183              : 
     184          278 :       ALLOCATE (cores(1))
     185          278 :       ALLOCATE (hab(1, 1))
     186          278 :       ALLOCATE (pab(1, 1))
     187              : 
     188          278 :       CALL get_qs_env(qs_env, pw_env=pw_env)
     189          278 :       CALL pw_env_get(pw_env, auxbas_rs_grid=rs_v)
     190              : 
     191          278 :       CALL transfer_pw2rs(rs_v, e_rspace)
     192              : 
     193              :       CALL get_qs_env(qs_env, &
     194              :                       atomic_kind_set=atomic_kind_set, &
     195              :                       cell=cell, &
     196              :                       dft_control=dft_control, &
     197          278 :                       particle_set=particle_set)
     198              : 
     199          278 :       use_virial = .TRUE.
     200          278 :       avirial = 0.0_dp
     201         3630 :       aforce = 0.0_dp
     202              : 
     203          278 :       eps_rho_rspace = dft_control%qs_control%eps_rho_rspace
     204              : 
     205          896 :       DO ikind = 1, SIZE(atomic_kind_set)
     206              : 
     207          618 :          CALL get_atomic_kind(atomic_kind_set(ikind), natom=natom_of_kind, atom_list=atom_list)
     208              : 
     209          618 :          alpha = calpha(ikind)
     210          618 :          pab(1, 1) = -cvalue(ikind)
     211          618 :          IF (alpha == 0.0_dp .OR. pab(1, 1) == 0.0_dp) CYCLE
     212              : 
     213          606 :          CALL reallocate(cores, 1, natom_of_kind)
     214          606 :          npme = 0
     215         1432 :          cores = 0
     216              : 
     217         1432 :          DO iatom = 1, natom_of_kind
     218          826 :             atom_a = atom_list(iatom)
     219          826 :             ra(:) = pbc(particle_set(atom_a)%r, cell)
     220         1432 :             IF (rs_v%desc%parallel .AND. .NOT. rs_v%desc%distributed) THEN
     221              :                ! replicated realspace grid, split the atoms up between procs
     222          826 :                IF (MODULO(iatom, rs_v%desc%group_size) == rs_v%desc%my_pos) THEN
     223          413 :                   npme = npme + 1
     224          413 :                   cores(npme) = iatom
     225              :                END IF
     226              :             ELSE
     227            0 :                npme = npme + 1
     228            0 :                cores(npme) = iatom
     229              :             END IF
     230              :          END DO
     231              : 
     232         1915 :          DO j = 1, npme
     233              : 
     234          413 :             iatom = cores(j)
     235          413 :             atom_a = atom_list(iatom)
     236          413 :             ra(:) = pbc(particle_set(atom_a)%r, cell)
     237          413 :             hab(1, 1) = 0.0_dp
     238          413 :             force_a(:) = 0.0_dp
     239          413 :             force_b(:) = 0.0_dp
     240          413 :             my_virial_a = 0.0_dp
     241          413 :             my_virial_b = 0.0_dp
     242              : 
     243              :             radius = exp_radius_very_extended(la_min=0, la_max=0, lb_min=0, lb_max=0, &
     244              :                                               ra=ra, rb=ra, rp=ra, &
     245              :                                               zetp=alpha, eps=eps_rho_rspace, &
     246              :                                               pab=pab, o1=0, o2=0, &
     247          413 :                                               prefactor=1.0_dp, cutoff=1.0_dp)
     248              : 
     249              :             CALL integrate_pgf_product(0, alpha, 0, &
     250              :                                        0, 0.0_dp, 0, ra, [0.0_dp, 0.0_dp, 0.0_dp], &
     251              :                                        rs_v, hab, pab=pab, o1=0, o2=0, &
     252              :                                        radius=radius, &
     253              :                                        calculate_forces=.TRUE., force_a=force_a, &
     254              :                                        force_b=force_b, use_virial=use_virial, my_virial_a=my_virial_a, &
     255          413 :                                        my_virial_b=my_virial_b, use_subpatch=.TRUE., subpatch_pattern=0)
     256              : 
     257         1652 :             aforce(1:3, atom_a) = aforce(1:3, atom_a) + force_a(1:3)
     258         5987 :             avirial = avirial + my_virial_a
     259              : 
     260              :          END DO
     261              : 
     262              :       END DO
     263              : 
     264          278 :       DEALLOCATE (hab, pab, cores)
     265              : 
     266          278 :       CALL timestop(handle)
     267              : 
     268          278 :    END SUBROUTINE gauss_grid_force
     269              : 
     270              : ! **************************************************************************************************
     271              : !> \brief calculates the XC density:
     272              : !>        order=0: exc will contain the xc energy density E_xc(r)
     273              : !>        order=1: exc will contain V_xc(r) * rho1(r)
     274              : !>        order=2: exc will contain F_xc(r) * rho1(r) * rho1(r)
     275              : !> \param ks_env to get all the needed things
     276              : !> \param rho_struct density
     277              : !> \param rho1_struct response density
     278              : !> \param order requested derivative order
     279              : !> \param xc_section ...
     280              : !> \param triplet ...
     281              : !> \param exc ...
     282              : !> \author JGH
     283              : ! **************************************************************************************************
     284          556 :    SUBROUTINE xc_density(ks_env, rho_struct, rho1_struct, order, xc_section, triplet, exc)
     285              : 
     286              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     287              :       TYPE(qs_rho_type), POINTER                         :: rho_struct, rho1_struct
     288              :       INTEGER, INTENT(IN)                                :: order
     289              :       TYPE(section_vals_type), POINTER                   :: xc_section
     290              :       LOGICAL, INTENT(IN)                                :: triplet
     291              :       TYPE(pw_r3d_rs_type)                               :: exc
     292              : 
     293              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'xc_density'
     294              : 
     295              :       INTEGER                                            :: handle, ispin, myfun, nspins
     296              :       LOGICAL                                            :: uf_grid
     297              :       REAL(KIND=dp)                                      :: excint, factor
     298              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: vdum
     299              :       TYPE(cell_type), POINTER                           :: cell
     300              :       TYPE(dft_control_type), POINTER                    :: dft_control
     301          278 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g
     302              :       TYPE(pw_c1d_gs_type), POINTER                      :: rho_nlcc_g
     303              :       TYPE(pw_env_type), POINTER                         :: pw_env
     304              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool, xc_pw_pool
     305          278 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho1_r, rho_r, tau1_r, tau_r, vxc_rho, &
     306          278 :                                                             vxc_tau
     307              :       TYPE(pw_r3d_rs_type), POINTER                      :: rho_nlcc, weights
     308              : 
     309          278 :       CALL timeset(routineN, handle)
     310              : 
     311              :       ! we always get true exc (not integration weighted)
     312          278 :       NULLIFY (weights)
     313              : 
     314              :       CALL get_ks_env(ks_env, &
     315              :                       dft_control=dft_control, &
     316              :                       pw_env=pw_env, &
     317              :                       cell=cell, &
     318              :                       rho_nlcc=rho_nlcc, &
     319          278 :                       rho_nlcc_g=rho_nlcc_g)
     320              : 
     321          278 :       CALL qs_rho_get(rho_struct, rho_r=rho_r, rho_g=rho_g, tau_r=tau_r)
     322              : 
     323          278 :       nspins = dft_control%nspins
     324              : 
     325          278 :       CALL section_vals_val_get(xc_section, "XC_FUNCTIONAL%_SECTION_PARAMETERS_", i_val=myfun)
     326              : 
     327          278 :       CALL pw_env_get(pw_env, xc_pw_pool=xc_pw_pool, auxbas_pw_pool=auxbas_pw_pool)
     328          278 :       uf_grid = .NOT. pw_grid_compare(auxbas_pw_pool%pw_grid, xc_pw_pool%pw_grid)
     329          278 :       IF (uf_grid) THEN
     330            0 :          CALL cp_warn(__LOCATION__, "Fine grid option not possible with energy density")
     331            0 :          CPABORT("Fine Grid in xc_density")
     332              :       END IF
     333              : 
     334          278 :       CALL pw_zero(exc)
     335              : 
     336          278 :       IF (myfun /= xc_none) THEN
     337              : 
     338          266 :          CPASSERT(ASSOCIATED(rho_struct))
     339          266 :          CPASSERT(dft_control%sic_method_id == sic_none)
     340              : 
     341              :          ! add the nlcc densities
     342          266 :          IF (ASSOCIATED(rho_nlcc) .AND. order <= 1) THEN
     343            6 :             factor = 1.0_dp
     344           12 :             DO ispin = 1, nspins
     345            6 :                CALL pw_axpy(rho_nlcc, rho_r(ispin), factor)
     346           12 :                CALL pw_axpy(rho_nlcc_g, rho_g(ispin), factor)
     347              :             END DO
     348              :          END IF
     349              : 
     350          266 :          NULLIFY (vxc_rho, vxc_tau)
     351          394 :          SELECT CASE (order)
     352              :          CASE (0)
     353              :             ! we could reduce to energy only here
     354          128 :             CALL xc_exc_pw_create(rho_r, rho_g, tau_r, xc_section, weights, xc_pw_pool, exc)
     355              :          CASE (1)
     356           84 :             CALL qs_rho_get(rho1_struct, rho_r=rho1_r, tau_r=tau1_r)
     357              :             CALL xc_vxc_pw_create(vxc_rho=vxc_rho, vxc_tau=vxc_tau, rho_r=rho_r, &
     358              :                                   rho_g=rho_g, tau=tau_r, exc=excint, &
     359              :                                   xc_section=xc_section, &
     360              :                                   weights=weights, pw_pool=xc_pw_pool, &
     361              :                                   compute_virial=.FALSE., &
     362           84 :                                   virial_xc=vdum)
     363              :          CASE (2)
     364           54 :             CALL qs_rho_get(rho1_struct, rho_r=rho1_r, tau_r=tau1_r)
     365              :             CALL qs_fxc_analytic(rho_struct, rho1_r, tau1_r, xc_section, weights, xc_pw_pool, &
     366           54 :                                  triplet, vxc_rho, vxc_tau)
     367              :          CASE DEFAULT
     368          266 :             CPABORT("Derivative order not available in xc_density")
     369              :          END SELECT
     370              : 
     371              :          ! remove the nlcc densities (keep stuff in original state)
     372          266 :          IF (ASSOCIATED(rho_nlcc) .AND. order <= 1) THEN
     373            6 :             factor = -1.0_dp
     374           12 :             DO ispin = 1, dft_control%nspins
     375            6 :                CALL pw_axpy(rho_nlcc, rho_r(ispin), factor)
     376           12 :                CALL pw_axpy(rho_nlcc_g, rho_g(ispin), factor)
     377              :             END DO
     378              :          END IF
     379              :          !
     380          138 :          SELECT CASE (order)
     381              :          CASE (0)
     382              :             !
     383              :          CASE (1, 2)
     384          138 :             CALL pw_zero(exc)
     385          138 :             IF (ASSOCIATED(vxc_rho)) THEN
     386          278 :                DO ispin = 1, nspins
     387          140 :                   CALL pw_multiply_with(vxc_rho(ispin), rho1_r(ispin))
     388          140 :                   CALL pw_axpy(vxc_rho(ispin), exc, 1.0_dp)
     389          278 :                   CALL vxc_rho(ispin)%release()
     390              :                END DO
     391          138 :                DEALLOCATE (vxc_rho)
     392              :             END IF
     393          138 :             IF (ASSOCIATED(vxc_tau)) THEN
     394            0 :                DO ispin = 1, nspins
     395            0 :                   CALL pw_multiply_with(vxc_tau(ispin), tau1_r(ispin))
     396            0 :                   CALL pw_axpy(vxc_tau(ispin), exc, 1.0_dp)
     397            0 :                   CALL vxc_tau(ispin)%release()
     398              :                END DO
     399            0 :                DEALLOCATE (vxc_tau)
     400              :             END IF
     401              :          CASE DEFAULT
     402          266 :             CPABORT("Derivative order not available in xc_density")
     403              :          END SELECT
     404              : 
     405          266 :          IF (order == 2) THEN
     406           54 :             CALL pw_scale(exc, 0.5_dp)
     407              :          END IF
     408              : 
     409              :       END IF
     410              : 
     411          278 :       CALL timestop(handle)
     412              : 
     413          278 :    END SUBROUTINE xc_density
     414              : 
     415              : END MODULE accint_weights_forces
        

Generated by: LCOV version 2.0-1