LCOV - code coverage report
Current view: top level - src - spme.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 439 441 99.5 %
Date: 2024-12-21 06:28:57 Functions: 7 7 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 Calculate the electrostatic energy by the Smooth Particle Ewald method
      10             : !> \par History
      11             : !>      JGH (03-May-2001) : first correctly working version
      12             : !> \author JGH (21-Mar-2001)
      13             : ! **************************************************************************************************
      14             : MODULE spme
      15             : 
      16             :    USE atomic_kind_types,               ONLY: get_atomic_kind
      17             :    USE atprop_types,                    ONLY: atprop_type
      18             :    USE bibliography,                    ONLY: Essmann1995,&
      19             :                                               cite_reference
      20             :    USE cell_types,                      ONLY: cell_type
      21             :    USE dgs,                             ONLY: dg_sum_patch,&
      22             :                                               dg_sum_patch_force_1d,&
      23             :                                               dg_sum_patch_force_3d
      24             :    USE ewald_environment_types,         ONLY: ewald_env_get,&
      25             :                                               ewald_environment_type
      26             :    USE ewald_pw_types,                  ONLY: ewald_pw_get,&
      27             :                                               ewald_pw_type
      28             :    USE kinds,                           ONLY: dp
      29             :    USE mathconstants,                   ONLY: fourpi
      30             :    USE message_passing,                 ONLY: mp_comm_type,&
      31             :                                               mp_para_env_type
      32             :    USE particle_types,                  ONLY: particle_type
      33             :    USE pme_tools,                       ONLY: get_center,&
      34             :                                               set_list
      35             :    USE pw_grid_types,                   ONLY: pw_grid_type
      36             :    USE pw_grids,                        ONLY: get_pw_grid_info
      37             :    USE pw_methods,                      ONLY: pw_integral_a2b,&
      38             :                                               pw_multiply_with,&
      39             :                                               pw_transfer
      40             :    USE pw_poisson_methods,              ONLY: pw_poisson_rebuild,&
      41             :                                               pw_poisson_solve
      42             :    USE pw_poisson_types,                ONLY: greens_fn_type,&
      43             :                                               pw_poisson_type
      44             :    USE pw_pool_types,                   ONLY: pw_pool_type
      45             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      46             :                                               pw_r3d_rs_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 shell_potential_types,           ONLY: shell_kind_type
      56             : #include "./base/base_uses.f90"
      57             : 
      58             :    IMPLICIT NONE
      59             : 
      60             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'spme'
      61             : 
      62             :    PRIVATE
      63             :    PUBLIC :: spme_evaluate, spme_potential, spme_forces, spme_virial, get_patch
      64             : 
      65             :    INTERFACE get_patch
      66             :       MODULE PROCEDURE get_patch_a, get_patch_b
      67             :    END INTERFACE
      68             : 
      69             : CONTAINS
      70             : 
      71             : ! **************************************************************************************************
      72             : !> \brief ...
      73             : !> \param ewald_env ...
      74             : !> \param ewald_pw ...
      75             : !> \param box ...
      76             : !> \param particle_set ...
      77             : !> \param fg_coulomb ...
      78             : !> \param vg_coulomb ...
      79             : !> \param pv_g ...
      80             : !> \param shell_particle_set ...
      81             : !> \param core_particle_set ...
      82             : !> \param fgshell_coulomb ...
      83             : !> \param fgcore_coulomb ...
      84             : !> \param use_virial ...
      85             : !> \param charges ...
      86             : !> \param atprop ...
      87             : !> \par History
      88             : !>      JGH (03-May-2001) : SPME with charge definition
      89             : !> \author JGH (21-Mar-2001)
      90             : ! **************************************************************************************************
      91       29500 :    SUBROUTINE spme_evaluate(ewald_env, ewald_pw, box, particle_set, &
      92       29500 :                             fg_coulomb, vg_coulomb, pv_g, shell_particle_set, core_particle_set, &
      93       29500 :                             fgshell_coulomb, fgcore_coulomb, use_virial, charges, atprop)
      94             : 
      95             :       TYPE(ewald_environment_type), POINTER              :: ewald_env
      96             :       TYPE(ewald_pw_type), POINTER                       :: ewald_pw
      97             :       TYPE(cell_type), POINTER                           :: box
      98             :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: particle_set
      99             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: fg_coulomb
     100             :       REAL(KIND=dp), INTENT(OUT)                         :: vg_coulomb
     101             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: pv_g
     102             :       TYPE(particle_type), DIMENSION(:), OPTIONAL, &
     103             :          POINTER                                         :: shell_particle_set, core_particle_set
     104             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT), &
     105             :          OPTIONAL                                        :: fgshell_coulomb, fgcore_coulomb
     106             :       LOGICAL, INTENT(IN)                                :: use_virial
     107             :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: charges
     108             :       TYPE(atprop_type), POINTER                         :: atprop
     109             : 
     110             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'spme_evaluate'
     111             : 
     112             :       INTEGER                                            :: handle, i, ipart, j, n, ncore, npart, &
     113             :                                                             nshell, o_spline, p1, p1_shell
     114       59000 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: center, core_center, shell_center
     115             :       INTEGER, DIMENSION(3)                              :: npts
     116             :       LOGICAL                                            :: do_shell
     117             :       REAL(KIND=dp)                                      :: alpha, dvols, fat1, ffa
     118       29500 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: core_delta, delta, shell_delta
     119             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: rhos
     120             :       REAL(KIND=dp), DIMENSION(3)                        :: fat
     121             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: f_stress, h_stress
     122             :       TYPE(greens_fn_type), POINTER                      :: green
     123             :       TYPE(mp_comm_type)                                 :: group
     124      118000 :       TYPE(pw_c1d_gs_type), DIMENSION(3)                 :: dphi_g
     125             :       TYPE(pw_c1d_gs_type), POINTER                      :: phi_g, rhob_g
     126             :       TYPE(pw_grid_type), POINTER                        :: grid_spme
     127             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     128             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     129             :       TYPE(pw_r3d_rs_type), POINTER                      :: rhob_r
     130             :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
     131     1062000 :       TYPE(realspace_grid_type), DIMENSION(3)            :: drpot
     132             :       TYPE(realspace_grid_type), POINTER                 :: rden, rpot
     133             : 
     134       29500 :       NULLIFY (grid_spme, green, poisson_env, phi_g, rhob_g, rhob_r, pw_pool, rden, rpot)
     135       29500 :       CALL timeset(routineN, handle)
     136       29500 :       CALL cite_reference(Essmann1995)
     137             : 
     138             :       !-------------- INITIALISATION ---------------------
     139             :       CALL ewald_env_get(ewald_env, alpha=alpha, o_spline=o_spline, &
     140       29500 :                          group=group)
     141             :       CALL ewald_pw_get(ewald_pw, pw_big_pool=pw_pool, rs_desc=rs_desc, &
     142       29500 :                         poisson_env=poisson_env)
     143       29500 :       CALL pw_poisson_rebuild(poisson_env)
     144       29500 :       green => poisson_env%green_fft
     145       29500 :       grid_spme => pw_pool%pw_grid
     146             : 
     147       29500 :       npart = SIZE(particle_set)
     148             : 
     149       29500 :       CALL get_pw_grid_info(grid_spme, npts=npts, dvol=dvols)
     150             : 
     151       29500 :       n = o_spline
     152      147500 :       ALLOCATE (rhos(n, n, n))
     153      619500 :       ALLOCATE (rden)
     154       29500 :       CALL rs_grid_create(rden, rs_desc)
     155       29500 :       CALL rs_grid_set_box(grid_spme, rs=rden)
     156       29500 :       CALL rs_grid_zero(rden)
     157             : 
     158      147500 :       ALLOCATE (center(3, npart), delta(3, npart))
     159       29500 :       CALL get_center(particle_set, box, center, delta, npts, n)
     160             : 
     161       29500 :       IF (PRESENT(shell_particle_set) .AND. (PRESENT(core_particle_set))) THEN
     162        9418 :          CPASSERT(ASSOCIATED(shell_particle_set))
     163        9418 :          CPASSERT(ASSOCIATED(core_particle_set))
     164        9418 :          nshell = SIZE(shell_particle_set)
     165        9418 :          ncore = SIZE(core_particle_set)
     166        9418 :          CPASSERT(nshell == ncore)
     167       47090 :          ALLOCATE (shell_center(3, nshell), shell_delta(3, nshell))
     168        9418 :          CALL get_center(shell_particle_set, box, shell_center, shell_delta, npts, n)
     169       28254 :          ALLOCATE (core_center(3, nshell), core_delta(3, nshell))
     170        9418 :          CALL get_center(core_particle_set, box, core_center, core_delta, npts, n)
     171             :       END IF
     172             : 
     173             :       !-------------- DENSITY CALCULATION ----------------
     174       29500 :       ipart = 0
     175             :       ! Particles
     176             :       DO
     177     3598394 :          CALL set_list(particle_set, npart, center, p1, rden, ipart)
     178     3598394 :          IF (p1 == 0) EXIT
     179             : 
     180     3568894 :          do_shell = (particle_set(p1)%shell_index /= 0)
     181     3568894 :          IF (do_shell) CYCLE
     182             :          ! calculate function on small boxes
     183             :          CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
     184     3153509 :                         is_shell=.FALSE., unit_charge=.FALSE., charges=charges)
     185             : 
     186             :          ! add boxes to real space grid (big box)
     187     3598394 :          CALL dg_sum_patch(rden, rhos, center(:, p1))
     188             :       END DO
     189             :       ! Shell-Model
     190       29500 :       IF (PRESENT(shell_particle_set) .AND. PRESENT(core_particle_set)) THEN
     191        9418 :          ipart = 0
     192      424803 :          DO
     193             :             ! calculate function on small boxes
     194             :             CALL set_list(shell_particle_set, nshell, shell_center, p1_shell, &
     195      424803 :                           rden, ipart)
     196      424803 :             IF (p1_shell == 0) EXIT
     197             :             CALL get_patch(shell_particle_set, shell_delta, green, p1_shell, rhos, &
     198      415385 :                            is_core=.FALSE., is_shell=.TRUE., unit_charge=.FALSE.)
     199             : 
     200             :             ! add boxes to real space grid (big box)
     201      424803 :             CALL dg_sum_patch(rden, rhos, shell_center(:, p1_shell))
     202             :          END DO
     203        9418 :          ipart = 0
     204      424803 :          DO
     205             :             ! calculate function on small boxes
     206             :             CALL set_list(core_particle_set, nshell, core_center, p1_shell, &
     207      424803 :                           rden, ipart)
     208      424803 :             IF (p1_shell == 0) EXIT
     209             :             CALL get_patch(core_particle_set, core_delta, green, p1_shell, rhos, &
     210      415385 :                            is_core=.TRUE., is_shell=.FALSE., unit_charge=.FALSE.)
     211             : 
     212             :             ! add boxes to real space grid (big box)
     213      424803 :             CALL dg_sum_patch(rden, rhos, core_center(:, p1_shell))
     214             :          END DO
     215             :       END IF
     216             :       !----------- END OF DENSITY CALCULATION -------------
     217             : 
     218       29500 :       NULLIFY (rhob_r)
     219       29500 :       ALLOCATE (rhob_r)
     220       29500 :       CALL pw_pool%create_pw(rhob_r)
     221       29500 :       CALL transfer_rs2pw(rden, rhob_r)
     222             :       ! transform density to G space and add charge function
     223       29500 :       NULLIFY (rhob_g)
     224       29500 :       ALLOCATE (rhob_g)
     225       29500 :       CALL pw_pool%create_pw(rhob_g)
     226       29500 :       CALL pw_transfer(rhob_r, rhob_g)
     227             :       ! update charge function
     228       29500 :       CALL pw_multiply_with(rhob_g, green%p3m_charge)
     229             : 
     230             :       !-------------- ELECTROSTATIC CALCULATION -----------
     231             :       ! allocate intermediate arrays
     232      118000 :       DO i = 1, 3
     233      118000 :          CALL pw_pool%create_pw(dphi_g(i))
     234             :       END DO
     235       29500 :       NULLIFY (phi_g)
     236       29500 :       ALLOCATE (phi_g)
     237       29500 :       CALL pw_pool%create_pw(phi_g)
     238             :       CALL pw_poisson_solve(poisson_env, rhob_g, vg_coulomb, phi_g, dphi_g, &
     239       29500 :                             h_stress)
     240             :       !---------- END OF ELECTROSTATIC CALCULATION --------
     241             : 
     242             :       ! Atomic Energy
     243       29500 :       IF (atprop%energy) THEN
     244        4872 :          ALLOCATE (rpot)
     245         232 :          CALL rs_grid_create(rpot, rs_desc)
     246         232 :          CALL rs_grid_set_box(grid_spme, rs=rpot)
     247         232 :          CALL pw_multiply_with(phi_g, green%p3m_charge)
     248         232 :          CALL pw_transfer(phi_g, rhob_r)
     249         232 :          CALL transfer_pw2rs(rpot, rhob_r)
     250         232 :          ipart = 0
     251             :          DO
     252        2335 :             CALL set_list(particle_set, npart, center, p1, rden, ipart)
     253        2335 :             IF (p1 == 0) EXIT
     254        2103 :             do_shell = (particle_set(p1)%shell_index /= 0)
     255        2103 :             IF (do_shell) CYCLE
     256             :             ! calculate function on small boxes
     257             :             CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
     258        1023 :                            is_shell=.FALSE., unit_charge=.FALSE., charges=charges)
     259             :             ! integrate box and potential
     260        1023 :             CALL dg_sum_patch_force_1d(rpot, rhos, center(:, p1), fat1)
     261        1255 :             IF (atprop%energy) THEN
     262        1023 :                atprop%atener(p1) = atprop%atener(p1) + 0.5_dp*fat1*dvols
     263             :             END IF
     264             :          END DO
     265             :          ! Core-shell model
     266         232 :          IF (PRESENT(shell_particle_set) .AND. PRESENT(core_particle_set)) THEN
     267          30 :             ipart = 0
     268        1110 :             DO
     269        1110 :                CALL set_list(shell_particle_set, nshell, shell_center, p1_shell, rden, ipart)
     270        1110 :                IF (p1_shell == 0) EXIT
     271             :                CALL get_patch(shell_particle_set, shell_delta, green, p1_shell, rhos, &
     272        1080 :                               is_core=.FALSE., is_shell=.TRUE., unit_charge=.FALSE.)
     273        1080 :                CALL dg_sum_patch_force_1d(rpot, rhos, shell_center(:, p1_shell), fat1)
     274        1080 :                p1 = shell_particle_set(p1_shell)%atom_index
     275        1110 :                IF (atprop%energy) THEN
     276        1080 :                   atprop%atener(p1) = atprop%atener(p1) + 0.5_dp*fat1*dvols
     277             :                END IF
     278             :             END DO
     279          30 :             ipart = 0
     280        1110 :             DO
     281        1110 :                CALL set_list(core_particle_set, nshell, core_center, p1_shell, rden, ipart)
     282        1110 :                IF (p1_shell == 0) EXIT
     283             :                CALL get_patch(core_particle_set, core_delta, green, p1_shell, rhos, &
     284        1080 :                               is_core=.TRUE., is_shell=.FALSE., unit_charge=.FALSE.)
     285        1080 :                CALL dg_sum_patch_force_1d(rpot, rhos, core_center(:, p1_shell), fat1)
     286        1080 :                p1 = core_particle_set(p1_shell)%atom_index
     287        1110 :                IF (atprop%energy) THEN
     288        1080 :                   atprop%atener(p1) = atprop%atener(p1) + 0.5_dp*fat1*dvols
     289             :                END IF
     290             :             END DO
     291             :          END IF
     292         232 :          CALL rs_grid_release(rpot)
     293         232 :          DEALLOCATE (rpot)
     294             :       END IF
     295             : 
     296       29500 :       CALL pw_pool%give_back_pw(phi_g)
     297       29500 :       CALL pw_pool%give_back_pw(rhob_g)
     298       29500 :       DEALLOCATE (phi_g, rhob_g)
     299             : 
     300             :       !------------- STRESS TENSOR CALCULATION ------------
     301       29500 :       IF (use_virial) THEN
     302       53808 :          DO i = 1, 3
     303      134520 :             DO j = i, 3
     304       80712 :                f_stress(i, j) = pw_integral_a2b(dphi_g(i), dphi_g(j))
     305      121068 :                f_stress(j, i) = f_stress(i, j)
     306             :             END DO
     307             :          END DO
     308       13452 :          ffa = (1.0_dp/fourpi)*(0.5_dp/alpha)**2
     309      174876 :          f_stress = -ffa*f_stress
     310      174876 :          pv_g = h_stress + f_stress
     311             :       END IF
     312             :       !--------END OF STRESS TENSOR CALCULATION -----------
     313             :       ! move derivative of potential to real space grid and
     314             :       ! multiply by charge function in g-space
     315      118000 :       DO i = 1, 3
     316       88500 :          CALL rs_grid_create(drpot(i), rs_desc)
     317       88500 :          CALL rs_grid_set_box(grid_spme, rs=drpot(i))
     318       88500 :          CALL pw_multiply_with(dphi_g(i), green%p3m_charge)
     319       88500 :          CALL pw_transfer(dphi_g(i), rhob_r)
     320       88500 :          CALL pw_pool%give_back_pw(dphi_g(i))
     321      118000 :          CALL transfer_pw2rs(drpot(i), rhob_r)
     322             :       END DO
     323             : 
     324       29500 :       CALL pw_pool%give_back_pw(rhob_r)
     325       29500 :       DEALLOCATE (rhob_r)
     326             :       !----------------- FORCE CALCULATION ----------------
     327             :       ! initialize the forces
     328    25692572 :       fg_coulomb = 0.0_dp
     329             :       ! Particles
     330       29500 :       ipart = 0
     331             :       DO
     332     3598394 :          CALL set_list(particle_set, npart, center, p1, rden, ipart)
     333     3598394 :          IF (p1 == 0) EXIT
     334             : 
     335     3568894 :          do_shell = (particle_set(p1)%shell_index /= 0)
     336     3568894 :          IF (do_shell) CYCLE
     337             :          ! calculate function on small boxes
     338             :          CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
     339     3153509 :                         is_shell=.FALSE., unit_charge=.FALSE., charges=charges)
     340             : 
     341             :          ! add boxes to real space grid (big box)
     342     3153509 :          CALL dg_sum_patch_force_3d(drpot, rhos, center(:, p1), fat)
     343     3153509 :          fg_coulomb(1, p1) = fg_coulomb(1, p1) - fat(1)*dvols
     344     3153509 :          fg_coulomb(2, p1) = fg_coulomb(2, p1) - fat(2)*dvols
     345     3568894 :          fg_coulomb(3, p1) = fg_coulomb(3, p1) - fat(3)*dvols
     346             :       END DO
     347             :       ! Shell-Model
     348       29500 :       IF (PRESENT(shell_particle_set) .AND. (PRESENT(core_particle_set))) THEN
     349        9418 :          IF (PRESENT(fgshell_coulomb)) THEN
     350        9418 :             ipart = 0
     351     3054338 :             fgshell_coulomb = 0.0_dp
     352      424803 :             DO
     353             :                ! calculate function on small boxes
     354             :                CALL set_list(shell_particle_set, nshell, shell_center, p1_shell, &
     355      424803 :                              rden, ipart)
     356      424803 :                IF (p1_shell == 0) EXIT
     357             : 
     358             :                CALL get_patch(shell_particle_set, shell_delta, green, &
     359      415385 :                               p1_shell, rhos, is_core=.FALSE., is_shell=.TRUE., unit_charge=.FALSE.)
     360             : 
     361             :                ! add boxes to real space grid (big box)
     362      415385 :                CALL dg_sum_patch_force_3d(drpot, rhos, shell_center(:, p1_shell), fat)
     363      415385 :                fgshell_coulomb(1, p1_shell) = fgshell_coulomb(1, p1_shell) - fat(1)*dvols
     364      415385 :                fgshell_coulomb(2, p1_shell) = fgshell_coulomb(2, p1_shell) - fat(2)*dvols
     365      415385 :                fgshell_coulomb(3, p1_shell) = fgshell_coulomb(3, p1_shell) - fat(3)*dvols
     366             : 
     367             :             END DO
     368             :          END IF
     369        9418 :          IF (PRESENT(fgcore_coulomb)) THEN
     370        9418 :             ipart = 0
     371     3054338 :             fgcore_coulomb = 0.0_dp
     372      424803 :             DO
     373             :                ! calculate function on small boxes
     374             :                CALL set_list(core_particle_set, nshell, core_center, p1_shell, &
     375      424803 :                              rden, ipart)
     376      424803 :                IF (p1_shell == 0) EXIT
     377             : 
     378             :                CALL get_patch(core_particle_set, core_delta, green, &
     379      415385 :                               p1_shell, rhos, is_core=.TRUE., is_shell=.FALSE., unit_charge=.FALSE.)
     380             : 
     381             :                ! add boxes to real space grid (big box)
     382      415385 :                CALL dg_sum_patch_force_3d(drpot, rhos, core_center(:, p1_shell), fat)
     383      415385 :                fgcore_coulomb(1, p1_shell) = fgcore_coulomb(1, p1_shell) - fat(1)*dvols
     384      415385 :                fgcore_coulomb(2, p1_shell) = fgcore_coulomb(2, p1_shell) - fat(2)*dvols
     385      415385 :                fgcore_coulomb(3, p1_shell) = fgcore_coulomb(3, p1_shell) - fat(3)*dvols
     386             :             END DO
     387             :          END IF
     388             : 
     389             :       END IF
     390             :       !--------------END OF FORCE CALCULATION -------------
     391             : 
     392             :       !------------------CLEANING UP ----------------------
     393       29500 :       CALL rs_grid_release(rden)
     394       29500 :       DEALLOCATE (rden)
     395      118000 :       DO i = 1, 3
     396      118000 :          CALL rs_grid_release(drpot(i))
     397             :       END DO
     398             : 
     399       29500 :       DEALLOCATE (rhos)
     400       29500 :       DEALLOCATE (center, delta)
     401       29500 :       IF (ALLOCATED(shell_center)) THEN
     402        9418 :          DEALLOCATE (shell_center, shell_delta)
     403             :       END IF
     404       29500 :       IF (ALLOCATED(core_center)) THEN
     405        9418 :          DEALLOCATE (core_center, core_delta)
     406             :       END IF
     407       29500 :       CALL timestop(handle)
     408             : 
     409      147500 :    END SUBROUTINE spme_evaluate
     410             : 
     411             : ! **************************************************************************************************
     412             : !> \brief Calculate the electrostatic potential from particles A (charge A) at
     413             : !>        positions of particles B
     414             : !> \param ewald_env ...
     415             : !> \param ewald_pw ...
     416             : !> \param box ...
     417             : !> \param particle_set_a ...
     418             : !> \param charges_a ...
     419             : !> \param particle_set_b ...
     420             : !> \param potential ...
     421             : !> \par History
     422             : !>      JGH (23-Oct-2014) : adapted from SPME evaluate
     423             : !> \author JGH (23-Oct-2014)
     424             : ! **************************************************************************************************
     425       11112 :    SUBROUTINE spme_potential(ewald_env, ewald_pw, box, particle_set_a, charges_a, &
     426       11112 :                              particle_set_b, potential)
     427             : 
     428             :       TYPE(ewald_environment_type), POINTER              :: ewald_env
     429             :       TYPE(ewald_pw_type), POINTER                       :: ewald_pw
     430             :       TYPE(cell_type), POINTER                           :: box
     431             :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: particle_set_a
     432             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), POINTER   :: charges_a
     433             :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: particle_set_b
     434             :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: potential
     435             : 
     436             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'spme_potential'
     437             : 
     438             :       INTEGER                                            :: handle, ipart, n, npart_a, npart_b, &
     439             :                                                             o_spline, p1
     440             :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: center
     441             :       INTEGER, DIMENSION(3)                              :: npts
     442             :       REAL(KIND=dp)                                      :: alpha, dvols, fat1
     443             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: delta
     444             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: rhos
     445             :       TYPE(greens_fn_type), POINTER                      :: green
     446             :       TYPE(mp_comm_type)                                 :: group
     447             :       TYPE(pw_c1d_gs_type), POINTER                      :: phi_g, rhob_g
     448             :       TYPE(pw_grid_type), POINTER                        :: grid_spme
     449             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     450             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     451             :       TYPE(pw_r3d_rs_type), POINTER                      :: rhob_r
     452             :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
     453             :       TYPE(realspace_grid_type), POINTER                 :: rden, rpot
     454             : 
     455       11112 :       NULLIFY (grid_spme, green, poisson_env, phi_g, rhob_g, rhob_r, pw_pool, &
     456       11112 :                rden, rpot)
     457       11112 :       CALL timeset(routineN, handle)
     458       11112 :       CALL cite_reference(Essmann1995)
     459             : 
     460             :       !-------------- INITIALISATION ---------------------
     461       11112 :       CALL ewald_env_get(ewald_env, alpha=alpha, o_spline=o_spline, group=group)
     462       11112 :       CALL ewald_pw_get(ewald_pw, pw_big_pool=pw_pool, rs_desc=rs_desc, poisson_env=poisson_env)
     463       11112 :       CALL pw_poisson_rebuild(poisson_env)
     464       11112 :       green => poisson_env%green_fft
     465       11112 :       grid_spme => pw_pool%pw_grid
     466             : 
     467       11112 :       npart_a = SIZE(particle_set_a)
     468       11112 :       npart_b = SIZE(particle_set_b)
     469             : 
     470       11112 :       CALL get_pw_grid_info(grid_spme, npts=npts, dvol=dvols)
     471             : 
     472       11112 :       n = o_spline
     473       55560 :       ALLOCATE (rhos(n, n, n))
     474      233352 :       ALLOCATE (rden)
     475       11112 :       CALL rs_grid_create(rden, rs_desc)
     476       11112 :       CALL rs_grid_set_box(grid_spme, rs=rden)
     477       11112 :       CALL rs_grid_zero(rden)
     478             : 
     479       55560 :       ALLOCATE (center(3, npart_a), delta(3, npart_a))
     480       11112 :       CALL get_center(particle_set_a, box, center, delta, npts, n)
     481             : 
     482             :       !-------------- DENSITY CALCULATION ----------------
     483       11112 :       ipart = 0
     484             :       ! Particles
     485       37038 :       DO
     486       48150 :          CALL set_list(particle_set_a, npart_a, center, p1, rden, ipart)
     487       48150 :          IF (p1 == 0) EXIT
     488             : 
     489             :          ! calculate function on small boxes
     490       37038 :          CALL get_patch(particle_set_a, delta, green, p1, rhos, charges_a)
     491             : 
     492             :          ! add boxes to real space grid (big box)
     493       48150 :          CALL dg_sum_patch(rden, rhos, center(:, p1))
     494             :       END DO
     495       11112 :       DEALLOCATE (center, delta)
     496             :       !----------- END OF DENSITY CALCULATION -------------
     497             : 
     498       11112 :       NULLIFY (rhob_r)
     499       11112 :       ALLOCATE (rhob_r)
     500       11112 :       CALL pw_pool%create_pw(rhob_r)
     501       11112 :       CALL transfer_rs2pw(rden, rhob_r)
     502             :       ! transform density to G space and add charge function
     503       11112 :       NULLIFY (rhob_g)
     504       11112 :       ALLOCATE (rhob_g)
     505       11112 :       CALL pw_pool%create_pw(rhob_g)
     506       11112 :       CALL pw_transfer(rhob_r, rhob_g)
     507             :       ! update charge function
     508       11112 :       CALL pw_multiply_with(rhob_g, green%p3m_charge)
     509             : 
     510             :       !-------------- ELECTROSTATIC CALCULATION -----------
     511             :       ! allocate intermediate arrays
     512       11112 :       NULLIFY (phi_g)
     513       11112 :       ALLOCATE (phi_g)
     514       11112 :       CALL pw_pool%create_pw(phi_g)
     515       11112 :       CALL pw_poisson_solve(poisson_env, density=rhob_g, vhartree=phi_g)
     516             :       !---------- END OF ELECTROSTATIC CALCULATION --------
     517             : 
     518             :       !-------------- POTENTAIL AT ATOMIC POSITIONS -------
     519       55560 :       ALLOCATE (center(3, npart_b), delta(3, npart_b))
     520       11112 :       CALL get_center(particle_set_b, box, center, delta, npts, n)
     521       11112 :       rpot => rden
     522       11112 :       CALL pw_multiply_with(phi_g, green%p3m_charge)
     523       11112 :       CALL pw_transfer(phi_g, rhob_r)
     524       11112 :       CALL transfer_pw2rs(rpot, rhob_r)
     525       11112 :       ipart = 0
     526       37038 :       DO
     527       48150 :          CALL set_list(particle_set_b, npart_b, center, p1, rden, ipart)
     528       48150 :          IF (p1 == 0) EXIT
     529             :          ! calculate function on small boxes
     530             :          CALL get_patch(particle_set_b, delta, green, p1, rhos, &
     531       37038 :                         is_core=.FALSE., is_shell=.FALSE., unit_charge=.TRUE.)
     532             :          ! integrate box and potential
     533       37038 :          CALL dg_sum_patch_force_1d(rpot, rhos, center(:, p1), fat1)
     534       37038 :          potential(p1) = potential(p1) + fat1*dvols
     535             :       END DO
     536             : 
     537             :       !------------------CLEANING UP ----------------------
     538       11112 :       CALL pw_pool%give_back_pw(phi_g)
     539       11112 :       CALL pw_pool%give_back_pw(rhob_g)
     540       11112 :       CALL pw_pool%give_back_pw(rhob_r)
     541       11112 :       DEALLOCATE (phi_g, rhob_g, rhob_r)
     542       11112 :       CALL rs_grid_release(rden)
     543       11112 :       DEALLOCATE (rden)
     544             : 
     545       11112 :       DEALLOCATE (rhos)
     546       11112 :       DEALLOCATE (center, delta)
     547       11112 :       CALL timestop(handle)
     548             : 
     549       33336 :    END SUBROUTINE spme_potential
     550             : 
     551             : ! **************************************************************************************************
     552             : !> \brief Calculate the forces on particles B for the electrostatic interaction
     553             : !>        betrween particles A and B
     554             : !> \param ewald_env ...
     555             : !> \param ewald_pw ...
     556             : !> \param box ...
     557             : !> \param particle_set_a ...
     558             : !> \param charges_a ...
     559             : !> \param particle_set_b ...
     560             : !> \param charges_b ...
     561             : !> \param forces_b ...
     562             : !> \par History
     563             : !>      JGH (27-Oct-2014) : adapted from SPME evaluate
     564             : !> \author JGH (23-Oct-2014)
     565             : ! **************************************************************************************************
     566         116 :    SUBROUTINE spme_forces(ewald_env, ewald_pw, box, particle_set_a, charges_a, &
     567         116 :                           particle_set_b, charges_b, forces_b)
     568             : 
     569             :       TYPE(ewald_environment_type), POINTER              :: ewald_env
     570             :       TYPE(ewald_pw_type), POINTER                       :: ewald_pw
     571             :       TYPE(cell_type), POINTER                           :: box
     572             :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: particle_set_a
     573             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), POINTER   :: charges_a
     574             :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: particle_set_b
     575             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), POINTER   :: charges_b
     576             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: forces_b
     577             : 
     578             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'spme_forces'
     579             : 
     580             :       INTEGER                                            :: handle, i, ipart, n, npart_a, npart_b, &
     581             :                                                             o_spline, p1
     582         116 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: center
     583             :       INTEGER, DIMENSION(3)                              :: npts
     584             :       REAL(KIND=dp)                                      :: alpha, dvols
     585         116 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: delta
     586             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: rhos
     587             :       REAL(KIND=dp), DIMENSION(3)                        :: fat
     588             :       TYPE(greens_fn_type), POINTER                      :: green
     589             :       TYPE(mp_comm_type)                                 :: group
     590         464 :       TYPE(pw_c1d_gs_type), DIMENSION(3)                 :: dphi_g
     591             :       TYPE(pw_c1d_gs_type), POINTER                      :: phi_g, rhob_g
     592             :       TYPE(pw_grid_type), POINTER                        :: grid_spme
     593             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     594             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     595             :       TYPE(pw_r3d_rs_type), POINTER                      :: rhob_r
     596             :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
     597        4176 :       TYPE(realspace_grid_type), DIMENSION(3)            :: drpot
     598             :       TYPE(realspace_grid_type), POINTER                 :: rden
     599             : 
     600         116 :       NULLIFY (grid_spme, green, poisson_env, phi_g, rhob_g, rhob_r, &
     601         116 :                pw_pool, rden)
     602         116 :       CALL timeset(routineN, handle)
     603         116 :       CALL cite_reference(Essmann1995)
     604             : 
     605             :       !-------------- INITIALISATION ---------------------
     606         116 :       CALL ewald_env_get(ewald_env, alpha=alpha, o_spline=o_spline, group=group)
     607         116 :       CALL ewald_pw_get(ewald_pw, pw_big_pool=pw_pool, rs_desc=rs_desc, poisson_env=poisson_env)
     608         116 :       CALL pw_poisson_rebuild(poisson_env)
     609         116 :       green => poisson_env%green_fft
     610         116 :       grid_spme => pw_pool%pw_grid
     611             : 
     612         116 :       npart_a = SIZE(particle_set_a)
     613         116 :       npart_b = SIZE(particle_set_b)
     614             : 
     615         116 :       CALL get_pw_grid_info(grid_spme, npts=npts, dvol=dvols)
     616             : 
     617         116 :       n = o_spline
     618         580 :       ALLOCATE (rhos(n, n, n))
     619        2436 :       ALLOCATE (rden)
     620         116 :       CALL rs_grid_create(rden, rs_desc)
     621         116 :       CALL rs_grid_set_box(grid_spme, rs=rden)
     622         116 :       CALL rs_grid_zero(rden)
     623             : 
     624         580 :       ALLOCATE (center(3, npart_a), delta(3, npart_a))
     625         116 :       CALL get_center(particle_set_a, box, center, delta, npts, n)
     626             : 
     627             :       !-------------- DENSITY CALCULATION ----------------
     628         116 :       ipart = 0
     629             :       ! Particles
     630         252 :       DO
     631         368 :          CALL set_list(particle_set_a, npart_a, center, p1, rden, ipart)
     632         368 :          IF (p1 == 0) EXIT
     633             : 
     634             :          ! calculate function on small boxes
     635         252 :          CALL get_patch(particle_set_a, delta, green, p1, rhos, charges_a)
     636             : 
     637             :          ! add boxes to real space grid (big box)
     638         368 :          CALL dg_sum_patch(rden, rhos, center(:, p1))
     639             :       END DO
     640         116 :       DEALLOCATE (center, delta)
     641             :       !----------- END OF DENSITY CALCULATION -------------
     642             : 
     643         116 :       NULLIFY (rhob_r)
     644         116 :       ALLOCATE (rhob_r)
     645         116 :       CALL pw_pool%create_pw(rhob_r)
     646         116 :       CALL transfer_rs2pw(rden, rhob_r)
     647             :       ! transform density to G space and add charge function
     648         116 :       NULLIFY (rhob_g)
     649         116 :       ALLOCATE (rhob_g)
     650         116 :       CALL pw_pool%create_pw(rhob_g)
     651         116 :       CALL pw_transfer(rhob_r, rhob_g)
     652             :       ! update charge function
     653         116 :       CALL pw_multiply_with(rhob_g, green%p3m_charge)
     654             : 
     655             :       !-------------- ELECTROSTATIC CALCULATION -----------
     656             :       ! allocate intermediate arrays
     657         464 :       DO i = 1, 3
     658         464 :          CALL pw_pool%create_pw(dphi_g(i))
     659             :       END DO
     660         116 :       NULLIFY (phi_g)
     661         116 :       ALLOCATE (phi_g)
     662         116 :       CALL pw_pool%create_pw(phi_g)
     663             :       CALL pw_poisson_solve(poisson_env, density=rhob_g, vhartree=phi_g, &
     664         116 :                             dvhartree=dphi_g)
     665             :       !---------- END OF ELECTROSTATIC CALCULATION --------
     666             :       ! move derivative of potential to real space grid and
     667             :       ! multiply by charge function in g-space
     668         464 :       DO i = 1, 3
     669         348 :          CALL rs_grid_create(drpot(i), rs_desc)
     670         348 :          CALL rs_grid_set_box(grid_spme, rs=drpot(i))
     671         348 :          CALL pw_multiply_with(dphi_g(i), green%p3m_charge)
     672         348 :          CALL pw_transfer(dphi_g(i), rhob_r)
     673         348 :          CALL pw_pool%give_back_pw(dphi_g(i))
     674         464 :          CALL transfer_pw2rs(drpot(i), rhob_r)
     675             :       END DO
     676             :       !----------------- FORCE CALCULATION ----------------
     677         580 :       ALLOCATE (center(3, npart_b), delta(3, npart_b))
     678         116 :       CALL get_center(particle_set_b, box, center, delta, npts, n)
     679         116 :       ipart = 0
     680         252 :       DO
     681         368 :          CALL set_list(particle_set_b, npart_b, center, p1, rden, ipart)
     682         368 :          IF (p1 == 0) EXIT
     683             :          ! calculate function on small boxes
     684             :          CALL get_patch(particle_set_b, delta, green, p1, rhos, &
     685         252 :                         is_core=.FALSE., is_shell=.FALSE., unit_charge=.FALSE., charges=charges_b)
     686             :          ! add boxes to real space grid (big box)
     687         252 :          CALL dg_sum_patch_force_3d(drpot, rhos, center(:, p1), fat)
     688         252 :          forces_b(1, p1) = forces_b(1, p1) - fat(1)*dvols
     689         252 :          forces_b(2, p1) = forces_b(2, p1) - fat(2)*dvols
     690         368 :          forces_b(3, p1) = forces_b(3, p1) - fat(3)*dvols
     691             :       END DO
     692             :       !------------------CLEANING UP ----------------------
     693         464 :       DO i = 1, 3
     694         464 :          CALL rs_grid_release(drpot(i))
     695             :       END DO
     696         116 :       CALL pw_pool%give_back_pw(phi_g)
     697         116 :       CALL pw_pool%give_back_pw(rhob_g)
     698         116 :       CALL pw_pool%give_back_pw(rhob_r)
     699         116 :       DEALLOCATE (phi_g, rhob_g, rhob_r)
     700         116 :       CALL rs_grid_release(rden)
     701         116 :       DEALLOCATE (rden)
     702             : 
     703         116 :       DEALLOCATE (rhos)
     704         116 :       DEALLOCATE (center, delta)
     705         116 :       CALL timestop(handle)
     706             : 
     707        1740 :    END SUBROUTINE spme_forces
     708             : 
     709             : ! **************************************************************************************************
     710             : !> \brief Internal Virial for 1/2 [rho||rho] (rho=mcharge)
     711             : !> \param ewald_env ...
     712             : !> \param ewald_pw ...
     713             : !> \param particle_set ...
     714             : !> \param box ...
     715             : !> \param mcharge ...
     716             : !> \param virial ...
     717             : ! **************************************************************************************************
     718          22 :    SUBROUTINE spme_virial(ewald_env, ewald_pw, particle_set, box, mcharge, virial)
     719             : 
     720             :       TYPE(ewald_environment_type), POINTER              :: ewald_env
     721             :       TYPE(ewald_pw_type), POINTER                       :: ewald_pw
     722             :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: particle_set
     723             :       TYPE(cell_type), POINTER                           :: box
     724             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: mcharge
     725             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(OUT)        :: virial
     726             : 
     727             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'spme_virial'
     728             : 
     729             :       INTEGER                                            :: handle, i, ipart, j, n, npart, o_spline, &
     730             :                                                             p1
     731          22 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: center
     732             :       INTEGER, DIMENSION(3)                              :: npts
     733             :       REAL(KIND=dp)                                      :: alpha, dvols, ffa, vgc
     734          22 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: delta
     735             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: rhos
     736             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: f_stress, h_stress
     737             :       TYPE(greens_fn_type), POINTER                      :: green
     738             :       TYPE(mp_comm_type)                                 :: group
     739             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     740          88 :       TYPE(pw_c1d_gs_type), DIMENSION(3)                 :: dphi_g
     741             :       TYPE(pw_c1d_gs_type), POINTER                      :: phi_g, rhob_g
     742             :       TYPE(pw_grid_type), POINTER                        :: grid_spme
     743             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     744             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     745             :       TYPE(pw_r3d_rs_type), POINTER                      :: rhob_r
     746             :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
     747         858 :       TYPE(realspace_grid_type)                          :: rden, rpot
     748             : 
     749          22 :       CALL timeset(routineN, handle)
     750             :       !-------------- INITIALISATION ---------------------
     751          22 :       virial = 0.0_dp
     752             :       CALL ewald_env_get(ewald_env, alpha=alpha, o_spline=o_spline, group=group, &
     753          22 :                          para_env=para_env)
     754          22 :       NULLIFY (green, poisson_env, pw_pool)
     755             :       CALL ewald_pw_get(ewald_pw, pw_big_pool=pw_pool, rs_desc=rs_desc, &
     756          22 :                         poisson_env=poisson_env)
     757          22 :       CALL pw_poisson_rebuild(poisson_env)
     758          22 :       green => poisson_env%green_fft
     759          22 :       grid_spme => pw_pool%pw_grid
     760             : 
     761          22 :       CALL get_pw_grid_info(grid_spme, dvol=dvols, npts=npts)
     762             : 
     763          22 :       npart = SIZE(particle_set)
     764             : 
     765          22 :       n = o_spline
     766         110 :       ALLOCATE (rhos(n, n, n))
     767             : 
     768          22 :       CALL rs_grid_create(rden, rs_desc)
     769          22 :       CALL rs_grid_set_box(grid_spme, rs=rden)
     770          22 :       CALL rs_grid_zero(rden)
     771             : 
     772         110 :       ALLOCATE (center(3, npart), delta(3, npart))
     773          22 :       CALL get_center(particle_set, box, center, delta, npts, n)
     774             : 
     775             :       !-------------- DENSITY CALCULATION ----------------
     776          22 :       ipart = 0
     777          94 :       DO
     778         116 :          CALL set_list(particle_set, npart, center, p1, rden, ipart)
     779         116 :          IF (p1 == 0) EXIT
     780             : 
     781             :          ! calculate function on small boxes
     782             :          CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
     783          94 :                         is_shell=.FALSE., unit_charge=.TRUE.)
     784        7990 :          rhos(:, :, :) = rhos(:, :, :)*mcharge(p1)
     785             : 
     786             :          ! add boxes to real space grid (big box)
     787         116 :          CALL dg_sum_patch(rden, rhos, center(:, p1))
     788             :       END DO
     789             : 
     790          22 :       NULLIFY (rhob_r)
     791          22 :       ALLOCATE (rhob_r)
     792          22 :       CALL pw_pool%create_pw(rhob_r)
     793             : 
     794          22 :       CALL transfer_rs2pw(rden, rhob_r)
     795             : 
     796             :       ! transform density to G space and add charge function
     797          22 :       NULLIFY (rhob_g)
     798          22 :       ALLOCATE (rhob_g)
     799          22 :       CALL pw_pool%create_pw(rhob_g)
     800          22 :       CALL pw_transfer(rhob_r, rhob_g)
     801             :       ! update charge function
     802          22 :       CALL pw_multiply_with(rhob_g, green%p3m_charge)
     803             : 
     804             :       !-------------- ELECTROSTATIC CALCULATION -----------
     805             : 
     806             :       ! allocate intermediate arrays
     807          88 :       DO i = 1, 3
     808          88 :          CALL pw_pool%create_pw(dphi_g(i))
     809             :       END DO
     810          22 :       NULLIFY (phi_g)
     811          22 :       ALLOCATE (phi_g)
     812          22 :       CALL pw_pool%create_pw(phi_g)
     813          22 :       CALL pw_poisson_solve(poisson_env, rhob_g, vgc, phi_g, dphi_g, h_stress=h_stress)
     814             : 
     815          22 :       CALL rs_grid_create(rpot, rs_desc)
     816          22 :       CALL rs_grid_set_box(grid_spme, rs=rpot)
     817             : 
     818          22 :       CALL pw_pool%give_back_pw(rhob_g)
     819          22 :       DEALLOCATE (rhob_g)
     820             : 
     821          22 :       CALL rs_grid_zero(rpot)
     822          22 :       CALL pw_multiply_with(phi_g, green%p3m_charge)
     823          22 :       CALL pw_transfer(phi_g, rhob_r)
     824          22 :       CALL pw_pool%give_back_pw(phi_g)
     825          22 :       DEALLOCATE (phi_g)
     826          22 :       CALL transfer_pw2rs(rpot, rhob_r)
     827             : 
     828             :       !---------- END OF ELECTROSTATIC CALCULATION --------
     829             : 
     830             :       !------------- STRESS TENSOR CALCULATION ------------
     831             : 
     832          88 :       DO i = 1, 3
     833         220 :          DO j = i, 3
     834         132 :             f_stress(i, j) = pw_integral_a2b(dphi_g(i), dphi_g(j))
     835         198 :             f_stress(j, i) = f_stress(i, j)
     836             :          END DO
     837             :       END DO
     838          22 :       ffa = (1.0_dp/fourpi)*(0.5_dp/alpha)**2
     839         286 :       virial = virial - (ffa*f_stress - h_stress)/REAL(para_env%num_pe, dp)
     840             : 
     841             :       !--------END OF STRESS TENSOR CALCULATION -----------
     842             : 
     843          88 :       DO i = 1, 3
     844          88 :          CALL pw_pool%give_back_pw(dphi_g(i))
     845             :       END DO
     846          22 :       CALL pw_pool%give_back_pw(rhob_r)
     847          22 :       DEALLOCATE (rhob_r)
     848             : 
     849          22 :       CALL rs_grid_release(rden)
     850          22 :       CALL rs_grid_release(rpot)
     851          22 :       DEALLOCATE (rhos)
     852          22 :       DEALLOCATE (center, delta)
     853             : 
     854          22 :       CALL timestop(handle)
     855             : 
     856          66 :    END SUBROUTINE spme_virial
     857             : 
     858             : ! **************************************************************************************************
     859             : !> \brief Calculates local density in a small box
     860             : !> \param part ...
     861             : !> \param delta ...
     862             : !> \param green ...
     863             : !> \param p ...
     864             : !> \param rhos ...
     865             : !> \param is_core ...
     866             : !> \param is_shell ...
     867             : !> \param unit_charge ...
     868             : !> \param charges ...
     869             : !> \par History
     870             : !>      none
     871             : !> \author JGH (21-Mar-2001)
     872             : ! **************************************************************************************************
     873     8266323 :    SUBROUTINE get_patch_a(part, delta, green, p, rhos, is_core, is_shell, &
     874             :                           unit_charge, charges)
     875             : 
     876             :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: part
     877             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: delta
     878             :       TYPE(greens_fn_type), INTENT(IN)                   :: green
     879             :       INTEGER, INTENT(IN)                                :: p
     880             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)     :: rhos
     881             :       LOGICAL, INTENT(IN)                                :: is_core, is_shell, unit_charge
     882             :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: charges
     883             : 
     884             :       INTEGER                                            :: nbox
     885             :       LOGICAL                                            :: use_charge_array
     886             :       REAL(KIND=dp)                                      :: q
     887             :       REAL(KIND=dp), DIMENSION(3)                        :: r
     888             :       TYPE(shell_kind_type), POINTER                     :: shell
     889             : 
     890     8266323 :       NULLIFY (shell)
     891     8266323 :       use_charge_array = .FALSE.
     892     8266323 :       IF (PRESENT(charges)) use_charge_array = ASSOCIATED(charges)
     893     8266323 :       IF (is_core .AND. is_shell) THEN
     894           0 :          CPABORT("Shell-model: cannot be core and shell simultaneously")
     895             :       END IF
     896             : 
     897     8266323 :       nbox = SIZE(rhos, 1)
     898    33065292 :       r = part(p)%r
     899     8266323 :       q = 1.0_dp
     900     8266323 :       IF (.NOT. unit_charge) THEN
     901     7971993 :          IF (is_core) THEN
     902      831850 :             CALL get_atomic_kind(atomic_kind=part(p)%atomic_kind, shell=shell)
     903      831850 :             q = shell%charge_core
     904     7140143 :          ELSE IF (is_shell) THEN
     905      831850 :             CALL get_atomic_kind(atomic_kind=part(p)%atomic_kind, shell=shell)
     906      831850 :             q = shell%charge_shell
     907             :          ELSE
     908     6308293 :             CALL get_atomic_kind(atomic_kind=part(p)%atomic_kind, qeff=q)
     909             :          END IF
     910     7971993 :          IF (use_charge_array) q = charges(p)
     911             :       END IF
     912     8266323 :       CALL spme_get_patch(rhos, nbox, delta(:, p), q, green%p3m_coeff)
     913             : 
     914     8266323 :    END SUBROUTINE get_patch_a
     915             : 
     916             : ! **************************************************************************************************
     917             : !> \brief Calculates local density in a small box
     918             : !> \param part ...
     919             : !> \param delta ...
     920             : !> \param green ...
     921             : !> \param p ...
     922             : !> \param rhos ...
     923             : !> \param charges ...
     924             : !> \par History
     925             : !>      none
     926             : !> \author JGH (21-Mar-2001)
     927             : ! **************************************************************************************************
     928       37290 :    SUBROUTINE get_patch_b(part, delta, green, p, rhos, charges)
     929             : 
     930             :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: part
     931             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: delta
     932             :       TYPE(greens_fn_type), INTENT(IN)                   :: green
     933             :       INTEGER, INTENT(IN)                                :: p
     934             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)     :: rhos
     935             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: charges
     936             : 
     937             :       INTEGER                                            :: nbox
     938             :       REAL(KIND=dp)                                      :: q
     939             :       REAL(KIND=dp), DIMENSION(3)                        :: r
     940             : 
     941       37290 :       CPASSERT(ASSOCIATED(charges))
     942       37290 :       nbox = SIZE(rhos, 1)
     943      149160 :       r = part(p)%r
     944       37290 :       q = charges(p)
     945       37290 :       CALL spme_get_patch(rhos, nbox, delta(:, p), q, green%p3m_coeff)
     946             : 
     947       37290 :    END SUBROUTINE get_patch_b
     948             : 
     949             : ! **************************************************************************************************
     950             : !> \brief Calculates SPME charge assignment
     951             : !> \param rhos ...
     952             : !> \param n ...
     953             : !> \param delta ...
     954             : !> \param q ...
     955             : !> \param coeff ...
     956             : !> \par History
     957             : !>      DG (29-Mar-2001) : code implemented
     958             : !> \author JGH (22-Mar-2001)
     959             : ! **************************************************************************************************
     960     8303613 :    SUBROUTINE spme_get_patch(rhos, n, delta, q, coeff)
     961             : 
     962             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)     :: rhos
     963             :       INTEGER, INTENT(IN)                                :: n
     964             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: delta
     965             :       REAL(KIND=dp), INTENT(IN)                          :: q
     966             :       REAL(KIND=dp), DIMENSION(-(n-1):n-1, 0:n-1), &
     967             :          INTENT(IN)                                      :: coeff
     968             : 
     969             :       INTEGER, PARAMETER                                 :: nmax = 12
     970             : 
     971             :       INTEGER                                            :: i, i1, i2, i3, j, l
     972             :       REAL(KIND=dp)                                      :: r2, r3
     973             :       REAL(KIND=dp), DIMENSION(3, -nmax:nmax)            :: w_assign
     974             :       REAL(KIND=dp), DIMENSION(3, 0:nmax-1)              :: deltal
     975             :       REAL(KIND=dp), DIMENSION(3, 1:nmax)                :: f_assign
     976             : 
     977     8303613 :       IF (n > nmax) THEN
     978           0 :          CPABORT("nmax value too small")
     979             :       END IF
     980             :       ! calculate the assignment function values and
     981             :       ! the charges on the grid (small box)
     982             : 
     983     8303613 :       deltal(1, 0) = 1.0_dp
     984     8303613 :       deltal(2, 0) = 1.0_dp
     985     8303613 :       deltal(3, 0) = 1.0_dp
     986    43715362 :       DO l = 1, n - 1
     987    35411749 :          deltal(1, l) = deltal(1, l - 1)*delta(1)
     988    35411749 :          deltal(2, l) = deltal(2, l - 1)*delta(2)
     989    43715362 :          deltal(3, l) = deltal(3, l - 1)*delta(3)
     990             :       END DO
     991             : 
     992     8303613 :       w_assign = 0.0_dp
     993    52018975 :       DO j = -(n - 1), n - 1, 2
     994   289971463 :          DO l = 0, n - 1
     995   237952488 :             w_assign(1, j) = w_assign(1, j) + coeff(j, l)*deltal(1, l)
     996   237952488 :             w_assign(2, j) = w_assign(2, j) + coeff(j, l)*deltal(2, l)
     997   281667850 :             w_assign(3, j) = w_assign(3, j) + coeff(j, l)*deltal(3, l)
     998             :          END DO
     999             :       END DO
    1000    52018975 :       DO i = 1, n
    1001    43715362 :          j = n + 1 - 2*i
    1002    43715362 :          f_assign(1, i) = w_assign(1, j)
    1003    43715362 :          f_assign(2, i) = w_assign(2, j)
    1004    52018975 :          f_assign(3, i) = w_assign(3, j)
    1005             :       END DO
    1006             : 
    1007    52018975 :       DO i3 = 1, n
    1008    43715362 :          r3 = q*f_assign(3, i3)
    1009   289971463 :          DO i2 = 1, n
    1010   237952488 :             r2 = r3*f_assign(2, i2)
    1011  1612935782 :             DO i1 = 1, n
    1012  1569220420 :                rhos(i1, i2, i3) = r2*f_assign(1, i1)
    1013             :             END DO
    1014             :          END DO
    1015             :       END DO
    1016             : 
    1017     8303613 :    END SUBROUTINE spme_get_patch
    1018             : 
    1019             : END MODULE spme
    1020             : 

Generated by: LCOV version 1.15