LCOV - code coverage report
Current view: top level - src - ewald_methods_tb.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 206 206 100.0 %
Date: 2024-12-21 06:28:57 Functions: 3 3 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 Calculation of Ewald contributions in DFTB
      10             : !> \author JGH
      11             : ! **************************************************************************************************
      12             : MODULE ewald_methods_tb
      13             :    USE cell_types,                      ONLY: cell_type
      14             :    USE dgs,                             ONLY: dg_sum_patch,&
      15             :                                               dg_sum_patch_force_1d,&
      16             :                                               dg_sum_patch_force_3d
      17             :    USE ewald_environment_types,         ONLY: ewald_env_get,&
      18             :                                               ewald_environment_type
      19             :    USE ewald_pw_types,                  ONLY: ewald_pw_get,&
      20             :                                               ewald_pw_type
      21             :    USE kinds,                           ONLY: dp
      22             :    USE mathconstants,                   ONLY: fourpi,&
      23             :                                               oorootpi
      24             :    USE message_passing,                 ONLY: mp_comm_type,&
      25             :                                               mp_para_env_type
      26             :    USE particle_types,                  ONLY: particle_type
      27             :    USE pme_tools,                       ONLY: get_center,&
      28             :                                               set_list
      29             :    USE pw_grid_types,                   ONLY: pw_grid_type
      30             :    USE pw_grids,                        ONLY: get_pw_grid_info
      31             :    USE pw_methods,                      ONLY: pw_integral_a2b,&
      32             :                                               pw_multiply_with,&
      33             :                                               pw_transfer
      34             :    USE pw_poisson_methods,              ONLY: pw_poisson_rebuild,&
      35             :                                               pw_poisson_solve
      36             :    USE pw_poisson_types,                ONLY: greens_fn_type,&
      37             :                                               pw_poisson_type
      38             :    USE pw_pool_types,                   ONLY: pw_pool_type
      39             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      40             :                                               pw_r3d_rs_type
      41             :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      42             :                                               neighbor_list_iterate,&
      43             :                                               neighbor_list_iterator_create,&
      44             :                                               neighbor_list_iterator_p_type,&
      45             :                                               neighbor_list_iterator_release,&
      46             :                                               neighbor_list_set_p_type
      47             :    USE realspace_grid_types,            ONLY: realspace_grid_desc_type,&
      48             :                                               realspace_grid_type,&
      49             :                                               rs_grid_create,&
      50             :                                               rs_grid_release,&
      51             :                                               rs_grid_set_box,&
      52             :                                               rs_grid_zero,&
      53             :                                               transfer_pw2rs,&
      54             :                                               transfer_rs2pw
      55             :    USE spme,                            ONLY: get_patch
      56             :    USE virial_methods,                  ONLY: virial_pair_force
      57             :    USE virial_types,                    ONLY: virial_type
      58             : #include "./base/base_uses.f90"
      59             : 
      60             :    IMPLICIT NONE
      61             : 
      62             :    PRIVATE
      63             : 
      64             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ewald_methods_tb'
      65             : 
      66             :    PUBLIC :: tb_spme_evaluate, tb_ewald_overlap, tb_spme_zforce
      67             : 
      68             : CONTAINS
      69             : 
      70             : ! **************************************************************************************************
      71             : !> \brief ...
      72             : !> \param ewald_env ...
      73             : !> \param ewald_pw ...
      74             : !> \param particle_set ...
      75             : !> \param box ...
      76             : !> \param gmcharge ...
      77             : !> \param mcharge ...
      78             : !> \param calculate_forces ...
      79             : !> \param virial ...
      80             : !> \param use_virial ...
      81             : ! **************************************************************************************************
      82       18348 :    SUBROUTINE tb_spme_evaluate(ewald_env, ewald_pw, particle_set, box, &
      83       18348 :                                gmcharge, mcharge, calculate_forces, virial, use_virial)
      84             : 
      85             :       TYPE(ewald_environment_type), POINTER              :: ewald_env
      86             :       TYPE(ewald_pw_type), POINTER                       :: ewald_pw
      87             :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: particle_set
      88             :       TYPE(cell_type), POINTER                           :: box
      89             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(inout)      :: gmcharge
      90             :       REAL(KIND=dp), DIMENSION(:), INTENT(in)            :: mcharge
      91             :       LOGICAL, INTENT(in)                                :: calculate_forces
      92             :       TYPE(virial_type), POINTER                         :: virial
      93             :       LOGICAL, INTENT(in)                                :: use_virial
      94             : 
      95             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'tb_spme_evaluate'
      96             : 
      97             :       INTEGER                                            :: handle, i, ipart, j, n, npart, o_spline, &
      98             :                                                             p1
      99       18348 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: center
     100             :       INTEGER, DIMENSION(3)                              :: npts
     101             :       REAL(KIND=dp)                                      :: alpha, dvols, fat(3), ffa, fint, vgc
     102       18348 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: delta
     103             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: rhos
     104             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: f_stress, h_stress
     105             :       TYPE(greens_fn_type), POINTER                      :: green
     106             :       TYPE(mp_comm_type)                                 :: group
     107             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     108       73392 :       TYPE(pw_c1d_gs_type), DIMENSION(3)                 :: dphi_g
     109             :       TYPE(pw_c1d_gs_type), POINTER                      :: phi_g, rhob_g
     110             :       TYPE(pw_grid_type), POINTER                        :: grid_spme
     111             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     112             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     113             :       TYPE(pw_r3d_rs_type), POINTER                      :: rhob_r
     114             :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
     115      715572 :       TYPE(realspace_grid_type)                          :: rden, rpot
     116             :       TYPE(realspace_grid_type), ALLOCATABLE, &
     117       18348 :          DIMENSION(:)                                    :: drpot
     118             : 
     119       18348 :       CALL timeset(routineN, handle)
     120             :       !-------------- INITIALISATION ---------------------
     121             :       CALL ewald_env_get(ewald_env, alpha=alpha, o_spline=o_spline, group=group, &
     122       18348 :                          para_env=para_env)
     123       18348 :       NULLIFY (green, poisson_env, pw_pool)
     124             :       CALL ewald_pw_get(ewald_pw, pw_big_pool=pw_pool, rs_desc=rs_desc, &
     125       18348 :                         poisson_env=poisson_env)
     126       18348 :       CALL pw_poisson_rebuild(poisson_env)
     127       18348 :       green => poisson_env%green_fft
     128       18348 :       grid_spme => pw_pool%pw_grid
     129             : 
     130       18348 :       CALL get_pw_grid_info(grid_spme, dvol=dvols, npts=npts)
     131             : 
     132       18348 :       npart = SIZE(particle_set)
     133             : 
     134       18348 :       n = o_spline
     135       91740 :       ALLOCATE (rhos(n, n, n))
     136             : 
     137       18348 :       CALL rs_grid_create(rden, rs_desc)
     138       18348 :       CALL rs_grid_set_box(grid_spme, rs=rden)
     139       18348 :       CALL rs_grid_zero(rden)
     140             : 
     141       91740 :       ALLOCATE (center(3, npart), delta(3, npart))
     142       18348 :       CALL get_center(particle_set, box, center, delta, npts, n)
     143             : 
     144             :       !-------------- DENSITY CALCULATION ----------------
     145       18348 :       ipart = 0
     146      128393 :       DO
     147      146741 :          CALL set_list(particle_set, npart, center, p1, rden, ipart)
     148      146741 :          IF (p1 == 0) EXIT
     149             : 
     150             :          ! calculate function on small boxes
     151             :          CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
     152      128393 :                         is_shell=.FALSE., unit_charge=.TRUE.)
     153    31939749 :          rhos(:, :, :) = rhos(:, :, :)*mcharge(p1)
     154             : 
     155             :          ! add boxes to real space grid (big box)
     156      146741 :          CALL dg_sum_patch(rden, rhos, center(:, p1))
     157             :       END DO
     158             : 
     159       18348 :       NULLIFY (rhob_r)
     160       18348 :       ALLOCATE (rhob_r)
     161       18348 :       CALL pw_pool%create_pw(rhob_r)
     162             : 
     163       18348 :       CALL transfer_rs2pw(rden, rhob_r)
     164             : 
     165             :       ! transform density to G space and add charge function
     166       18348 :       NULLIFY (rhob_g)
     167       18348 :       ALLOCATE (rhob_g)
     168       18348 :       CALL pw_pool%create_pw(rhob_g)
     169       18348 :       CALL pw_transfer(rhob_r, rhob_g)
     170             :       ! update charge function
     171       18348 :       CALL pw_multiply_with(rhob_g, green%p3m_charge)
     172             : 
     173             :       !-------------- ELECTROSTATIC CALCULATION -----------
     174             : 
     175             :       ! allocate intermediate arrays
     176       73392 :       DO i = 1, 3
     177       73392 :          CALL pw_pool%create_pw(dphi_g(i))
     178             :       END DO
     179       18348 :       NULLIFY (phi_g)
     180       18348 :       ALLOCATE (phi_g)
     181       18348 :       CALL pw_pool%create_pw(phi_g)
     182       18348 :       IF (use_virial) THEN
     183         154 :          CALL pw_poisson_solve(poisson_env, rhob_g, vgc, phi_g, dphi_g, h_stress=h_stress)
     184             :       ELSE
     185       18194 :          CALL pw_poisson_solve(poisson_env, rhob_g, vgc, phi_g, dphi_g)
     186             :       END IF
     187             : 
     188       18348 :       CALL rs_grid_create(rpot, rs_desc)
     189       18348 :       CALL rs_grid_set_box(grid_spme, rs=rpot)
     190             : 
     191       18348 :       CALL pw_pool%give_back_pw(rhob_g)
     192       18348 :       DEALLOCATE (rhob_g)
     193             : 
     194       18348 :       CALL rs_grid_zero(rpot)
     195       18348 :       CALL pw_multiply_with(phi_g, green%p3m_charge)
     196       18348 :       CALL pw_transfer(phi_g, rhob_r)
     197       18348 :       CALL pw_pool%give_back_pw(phi_g)
     198       18348 :       DEALLOCATE (phi_g)
     199       18348 :       CALL transfer_pw2rs(rpot, rhob_r)
     200             : 
     201             :       !---------- END OF ELECTROSTATIC CALCULATION --------
     202             : 
     203             :       !------------- STRESS TENSOR CALCULATION ------------
     204             : 
     205       18348 :       IF (use_virial) THEN
     206         616 :          DO i = 1, 3
     207        1540 :             DO j = i, 3
     208         924 :                f_stress(i, j) = pw_integral_a2b(dphi_g(i), dphi_g(j))
     209        1386 :                f_stress(j, i) = f_stress(i, j)
     210             :             END DO
     211             :          END DO
     212         154 :          ffa = (1.0_dp/fourpi)*(0.5_dp/alpha)**2
     213        2002 :          virial%pv_virial = virial%pv_virial - (ffa*f_stress - h_stress)/REAL(para_env%num_pe, dp)
     214             :       END IF
     215             : 
     216             :       !--------END OF STRESS TENSOR CALCULATION -----------
     217             : 
     218       18348 :       IF (calculate_forces) THEN
     219             :          ! move derivative of potential to real space grid and
     220             :          ! multiply by charge function in g-space
     221       17434 :          ALLOCATE (drpot(3))
     222        3032 :          DO i = 1, 3
     223        2274 :             CALL rs_grid_create(drpot(i), rs_desc)
     224        2274 :             CALL rs_grid_set_box(grid_spme, rs=drpot(i))
     225        2274 :             CALL pw_multiply_with(dphi_g(i), green%p3m_charge)
     226        2274 :             CALL pw_transfer(dphi_g(i), rhob_r)
     227        2274 :             CALL pw_pool%give_back_pw(dphi_g(i))
     228        3032 :             CALL transfer_pw2rs(drpot(i), rhob_r)
     229             :          END DO
     230             :       ELSE
     231       70360 :          DO i = 1, 3
     232       70360 :             CALL pw_pool%give_back_pw(dphi_g(i))
     233             :          END DO
     234             :       END IF
     235       18348 :       CALL pw_pool%give_back_pw(rhob_r)
     236       18348 :       DEALLOCATE (rhob_r)
     237             : 
     238             :       !----------------- FORCE CALCULATION ----------------
     239             : 
     240       18348 :       ipart = 0
     241             :       DO
     242             : 
     243      146741 :          CALL set_list(particle_set, npart, center, p1, rden, ipart)
     244      146741 :          IF (p1 == 0) EXIT
     245             : 
     246             :          ! calculate function on small boxes
     247             :          CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
     248      128393 :                         is_shell=.FALSE., unit_charge=.TRUE.)
     249             : 
     250      128393 :          CALL dg_sum_patch_force_1d(rpot, rhos, center(:, p1), fint)
     251      128393 :          gmcharge(p1, 1) = gmcharge(p1, 1) + fint*dvols
     252             : 
     253      146741 :          IF (calculate_forces) THEN
     254        8330 :             CALL dg_sum_patch_force_3d(drpot, rhos, center(:, p1), fat)
     255        8330 :             gmcharge(p1, 2) = gmcharge(p1, 2) - fat(1)*dvols
     256        8330 :             gmcharge(p1, 3) = gmcharge(p1, 3) - fat(2)*dvols
     257        8330 :             gmcharge(p1, 4) = gmcharge(p1, 4) - fat(3)*dvols
     258             :          END IF
     259             : 
     260             :       END DO
     261             : 
     262             :       !--------------END OF FORCE CALCULATION -------------
     263             : 
     264             :       !------------------CLEANING UP ----------------------
     265             : 
     266       18348 :       CALL rs_grid_release(rden)
     267       18348 :       CALL rs_grid_release(rpot)
     268       18348 :       IF (calculate_forces) THEN
     269        3032 :          DO i = 1, 3
     270        3032 :             CALL rs_grid_release(drpot(i))
     271             :          END DO
     272        3032 :          DEALLOCATE (drpot)
     273             :       END IF
     274       18348 :       DEALLOCATE (rhos)
     275       18348 :       DEALLOCATE (center, delta)
     276             : 
     277       18348 :       CALL timestop(handle)
     278             : 
     279       55044 :    END SUBROUTINE tb_spme_evaluate
     280             : 
     281             : ! **************************************************************************************************
     282             : !> \brief ...
     283             : !> \param gmcharge ...
     284             : !> \param mcharge ...
     285             : !> \param alpha ...
     286             : !> \param n_list ...
     287             : !> \param virial ...
     288             : !> \param use_virial ...
     289             : ! **************************************************************************************************
     290       15872 :    SUBROUTINE tb_ewald_overlap(gmcharge, mcharge, alpha, n_list, virial, use_virial)
     291             : 
     292             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(inout)      :: gmcharge
     293             :       REAL(KIND=dp), DIMENSION(:), INTENT(in)            :: mcharge
     294             :       REAL(KIND=dp), INTENT(in)                          :: alpha
     295             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     296             :          POINTER                                         :: n_list
     297             :       TYPE(virial_type), POINTER                         :: virial
     298             :       LOGICAL, INTENT(IN)                                :: use_virial
     299             : 
     300             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'tb_ewald_overlap'
     301             : 
     302             :       INTEGER                                            :: handle, i, iatom, jatom, nmat
     303             :       REAL(KIND=dp)                                      :: dfr, dr, fr, pfr, rij(3)
     304             :       TYPE(neighbor_list_iterator_p_type), &
     305       15872 :          DIMENSION(:), POINTER                           :: nl_iterator
     306             : 
     307       15872 :       CALL timeset(routineN, handle)
     308             : 
     309       15872 :       nmat = SIZE(gmcharge, 2)
     310             : 
     311       15872 :       CALL neighbor_list_iterator_create(nl_iterator, n_list)
     312    75219857 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     313    75203985 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom, r=rij)
     314             : 
     315   300815940 :          dr = SQRT(SUM(rij(:)**2))
     316    75219857 :          IF (dr > 1.e-10) THEN
     317    75079125 :             fr = erfc(alpha*dr)/dr
     318    75079125 :             gmcharge(iatom, 1) = gmcharge(iatom, 1) + mcharge(jatom)*fr
     319    75079125 :             gmcharge(jatom, 1) = gmcharge(jatom, 1) + mcharge(iatom)*fr
     320    75079125 :             IF (nmat > 1) THEN
     321     9359599 :                dfr = -2._dp*alpha*EXP(-alpha*alpha*dr*dr)*oorootpi/dr - fr/dr
     322     9359599 :                dfr = -dfr/dr
     323    37438396 :                DO i = 2, nmat
     324    28078797 :                   gmcharge(iatom, i) = gmcharge(iatom, i) - rij(i - 1)*mcharge(jatom)*dfr
     325    37438396 :                   gmcharge(jatom, i) = gmcharge(jatom, i) + rij(i - 1)*mcharge(iatom)*dfr
     326             :                END DO
     327             :             END IF
     328    75079125 :             IF (use_virial) THEN
     329     6231309 :                IF (iatom == jatom) THEN
     330      132432 :                   pfr = -0.5_dp*dfr*mcharge(iatom)*mcharge(jatom)
     331             :                ELSE
     332     6098877 :                   pfr = -dfr*mcharge(iatom)*mcharge(jatom)
     333             :                END IF
     334     6231309 :                CALL virial_pair_force(virial%pv_virial, -pfr, rij, rij)
     335             :             END IF
     336             :          END IF
     337             : 
     338             :       END DO
     339       15872 :       CALL neighbor_list_iterator_release(nl_iterator)
     340             : 
     341       15872 :       CALL timestop(handle)
     342             : 
     343       15872 :    END SUBROUTINE tb_ewald_overlap
     344             : 
     345             : ! **************************************************************************************************
     346             : !> \brief ...
     347             : !> \param ewald_env ...
     348             : !> \param ewald_pw ...
     349             : !> \param particle_set ...
     350             : !> \param box ...
     351             : !> \param gmcharge ...
     352             : !> \param mcharge ...
     353             : ! **************************************************************************************************
     354          12 :    SUBROUTINE tb_spme_zforce(ewald_env, ewald_pw, particle_set, box, gmcharge, mcharge)
     355             : 
     356             :       TYPE(ewald_environment_type), POINTER              :: ewald_env
     357             :       TYPE(ewald_pw_type), POINTER                       :: ewald_pw
     358             :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: particle_set
     359             :       TYPE(cell_type), POINTER                           :: box
     360             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(inout)      :: gmcharge
     361             :       REAL(KIND=dp), DIMENSION(:), INTENT(in)            :: mcharge
     362             : 
     363             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'tb_spme_zforce'
     364             : 
     365             :       INTEGER                                            :: handle, i, ipart, n, npart, o_spline, p1
     366          12 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: center
     367             :       INTEGER, DIMENSION(3)                              :: npts
     368             :       REAL(KIND=dp)                                      :: alpha, dvols, fat(3), fint, vgc
     369          12 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: delta
     370             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: rhos
     371             :       TYPE(greens_fn_type), POINTER                      :: green
     372             :       TYPE(mp_comm_type)                                 :: group
     373             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     374          48 :       TYPE(pw_c1d_gs_type), DIMENSION(3)                 :: dphi_g
     375             :       TYPE(pw_c1d_gs_type), POINTER                      :: phi_g, rhob_g
     376             :       TYPE(pw_grid_type), POINTER                        :: grid_spme
     377             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     378             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     379             :       TYPE(pw_r3d_rs_type), POINTER                      :: rhob_r
     380             :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
     381         468 :       TYPE(realspace_grid_type)                          :: rden, rpot
     382         432 :       TYPE(realspace_grid_type), DIMENSION(3)            :: drpot
     383             : 
     384          12 :       CALL timeset(routineN, handle)
     385             :       !-------------- INITIALISATION ---------------------
     386             :       CALL ewald_env_get(ewald_env, alpha=alpha, o_spline=o_spline, group=group, &
     387          12 :                          para_env=para_env)
     388          12 :       NULLIFY (green, poisson_env, pw_pool)
     389             :       CALL ewald_pw_get(ewald_pw, pw_big_pool=pw_pool, rs_desc=rs_desc, &
     390          12 :                         poisson_env=poisson_env)
     391          12 :       CALL pw_poisson_rebuild(poisson_env)
     392          12 :       green => poisson_env%green_fft
     393          12 :       grid_spme => pw_pool%pw_grid
     394             : 
     395          12 :       CALL get_pw_grid_info(grid_spme, dvol=dvols, npts=npts)
     396             : 
     397          12 :       npart = SIZE(particle_set)
     398             : 
     399          12 :       n = o_spline
     400          60 :       ALLOCATE (rhos(n, n, n))
     401             : 
     402          12 :       CALL rs_grid_create(rden, rs_desc)
     403          12 :       CALL rs_grid_set_box(grid_spme, rs=rden)
     404          12 :       CALL rs_grid_zero(rden)
     405             : 
     406          60 :       ALLOCATE (center(3, npart), delta(3, npart))
     407          12 :       CALL get_center(particle_set, box, center, delta, npts, n)
     408             : 
     409             :       !-------------- DENSITY CALCULATION ----------------
     410          12 :       ipart = 0
     411         206 :       DO
     412         218 :          CALL set_list(particle_set, npart, center, p1, rden, ipart)
     413         218 :          IF (p1 == 0) EXIT
     414             : 
     415             :          ! calculate function on small boxes
     416             :          CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
     417         206 :                         is_shell=.FALSE., unit_charge=.TRUE.)
     418       53354 :          rhos(:, :, :) = rhos(:, :, :)*mcharge(p1)
     419             : 
     420             :          ! add boxes to real space grid (big box)
     421         218 :          CALL dg_sum_patch(rden, rhos, center(:, p1))
     422             :       END DO
     423             : 
     424          12 :       NULLIFY (rhob_r)
     425          12 :       ALLOCATE (rhob_r)
     426          12 :       CALL pw_pool%create_pw(rhob_r)
     427             : 
     428          12 :       CALL transfer_rs2pw(rden, rhob_r)
     429             : 
     430             :       ! transform density to G space and add charge function
     431          12 :       NULLIFY (rhob_g)
     432          12 :       ALLOCATE (rhob_g)
     433          12 :       CALL pw_pool%create_pw(rhob_g)
     434          12 :       CALL pw_transfer(rhob_r, rhob_g)
     435             :       ! update charge function
     436          12 :       CALL pw_multiply_with(rhob_g, green%p3m_charge)
     437             : 
     438             :       !-------------- ELECTROSTATIC CALCULATION -----------
     439             : 
     440             :       ! allocate intermediate arrays
     441          48 :       DO i = 1, 3
     442          48 :          CALL pw_pool%create_pw(dphi_g(i))
     443             :       END DO
     444          12 :       NULLIFY (phi_g)
     445          12 :       ALLOCATE (phi_g)
     446          12 :       CALL pw_pool%create_pw(phi_g)
     447          12 :       CALL pw_poisson_solve(poisson_env, rhob_g, vgc, phi_g, dphi_g)
     448             : 
     449          12 :       CALL rs_grid_create(rpot, rs_desc)
     450          12 :       CALL rs_grid_set_box(grid_spme, rs=rpot)
     451             : 
     452          12 :       CALL pw_pool%give_back_pw(rhob_g)
     453          12 :       DEALLOCATE (rhob_g)
     454             : 
     455          12 :       CALL rs_grid_zero(rpot)
     456          12 :       CALL pw_multiply_with(phi_g, green%p3m_charge)
     457          12 :       CALL pw_transfer(phi_g, rhob_r)
     458          12 :       CALL pw_pool%give_back_pw(phi_g)
     459          12 :       DEALLOCATE (phi_g)
     460          12 :       CALL transfer_pw2rs(rpot, rhob_r)
     461             : 
     462             :       !---------- END OF ELECTROSTATIC CALCULATION --------
     463             : 
     464             :       ! move derivative of potential to real space grid and
     465             :       ! multiply by charge function in g-space
     466          48 :       DO i = 1, 3
     467          36 :          CALL rs_grid_create(drpot(i), rs_desc)
     468          36 :          CALL rs_grid_set_box(grid_spme, rs=drpot(i))
     469          36 :          CALL pw_multiply_with(dphi_g(i), green%p3m_charge)
     470          36 :          CALL pw_transfer(dphi_g(i), rhob_r)
     471          36 :          CALL pw_pool%give_back_pw(dphi_g(i))
     472          48 :          CALL transfer_pw2rs(drpot(i), rhob_r)
     473             :       END DO
     474          12 :       CALL pw_pool%give_back_pw(rhob_r)
     475          12 :       DEALLOCATE (rhob_r)
     476             : 
     477             :       !----------------- FORCE CALCULATION ----------------
     478             : 
     479          12 :       ipart = 0
     480         206 :       DO
     481             : 
     482         218 :          CALL set_list(particle_set, npart, center, p1, rden, ipart)
     483         218 :          IF (p1 == 0) EXIT
     484             : 
     485             :          ! calculate function on small boxes
     486             :          CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
     487         206 :                         is_shell=.FALSE., unit_charge=.TRUE.)
     488             : 
     489         206 :          CALL dg_sum_patch_force_1d(rpot, rhos, center(:, p1), fint)
     490         206 :          gmcharge(p1, 1) = gmcharge(p1, 1) + fint*dvols
     491             : 
     492         206 :          CALL dg_sum_patch_force_3d(drpot, rhos, center(:, p1), fat)
     493         206 :          gmcharge(p1, 2) = gmcharge(p1, 2) - fat(1)*dvols
     494         206 :          gmcharge(p1, 3) = gmcharge(p1, 3) - fat(2)*dvols
     495         206 :          gmcharge(p1, 4) = gmcharge(p1, 4) - fat(3)*dvols
     496             : 
     497             :       END DO
     498             : 
     499             :       !--------------END OF FORCE CALCULATION -------------
     500             : 
     501             :       !------------------CLEANING UP ----------------------
     502             : 
     503          12 :       CALL rs_grid_release(rden)
     504          12 :       CALL rs_grid_release(rpot)
     505          48 :       DO i = 1, 3
     506          48 :          CALL rs_grid_release(drpot(i))
     507             :       END DO
     508          12 :       DEALLOCATE (rhos)
     509          12 :       DEALLOCATE (center, delta)
     510             : 
     511          12 :       CALL timestop(handle)
     512             : 
     513          36 :    END SUBROUTINE tb_spme_zforce
     514             : 
     515             : END MODULE ewald_methods_tb
     516             : 

Generated by: LCOV version 1.15