LCOV - code coverage report
Current view: top level - src - pme.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:92574dc) Lines: 68.4 % 304 208
Test Date: 2026-09-24 01:27:39 Functions: 100.0 % 3 3

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \par History
      10              : !>      JGH (21-Mar-2001) : Complete rewrite
      11              : !> \author CJM and APSI
      12              : ! **************************************************************************************************
      13              : MODULE pme
      14              : 
      15              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      16              :                                               get_atomic_kind
      17              :    USE atprop_types,                    ONLY: atprop_type
      18              :    USE bibliography,                    ONLY: cite_reference,&
      19              :                                               darden1993
      20              :    USE cell_types,                      ONLY: cell_type
      21              :    USE dg_rho0_types,                   ONLY: dg_rho0_type
      22              :    USE dg_types,                        ONLY: dg_get,&
      23              :                                               dg_type
      24              :    USE dgs,                             ONLY: dg_get_patch,&
      25              :                                               dg_get_strucfac,&
      26              :                                               dg_sum_patch,&
      27              :                                               dg_sum_patch_force_1d,&
      28              :                                               dg_sum_patch_force_3d
      29              :    USE ewald_environment_types,         ONLY: ewald_env_get,&
      30              :                                               ewald_environment_type
      31              :    USE ewald_pw_types,                  ONLY: ewald_pw_get,&
      32              :                                               ewald_pw_type
      33              :    USE kinds,                           ONLY: dp
      34              :    USE mathconstants,                   ONLY: fourpi
      35              :    USE message_passing,                 ONLY: mp_comm_type
      36              :    USE particle_types,                  ONLY: particle_type
      37              :    USE pme_tools,                       ONLY: get_center,&
      38              :                                               set_list
      39              :    USE pw_grid_types,                   ONLY: pw_grid_type
      40              :    USE pw_methods,                      ONLY: pw_integral_a2b,&
      41              :                                               pw_transfer
      42              :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
      43              :    USE pw_poisson_types,                ONLY: 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              :    USE structure_factor_types,          ONLY: structure_factor_type
      57              :    USE structure_factors,               ONLY: structure_factor_allocate,&
      58              :                                               structure_factor_deallocate,&
      59              :                                               structure_factor_init
      60              : #include "./base/base_uses.f90"
      61              : 
      62              :    IMPLICIT NONE
      63              : 
      64              :    PRIVATE
      65              :    PUBLIC :: pme_evaluate
      66              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pme'
      67              : 
      68              : CONTAINS
      69              : 
      70              : ! **************************************************************************************************
      71              : !> \brief ...
      72              : !> \param ewald_env ...
      73              : !> \param ewald_pw ...
      74              : !> \param box ...
      75              : !> \param particle_set ...
      76              : !> \param vg_coulomb ...
      77              : !> \param fg_coulomb ...
      78              : !> \param pv_g ...
      79              : !> \param shell_particle_set ...
      80              : !> \param core_particle_set ...
      81              : !> \param fgshell_coulomb ...
      82              : !> \param fgcore_coulomb ...
      83              : !> \param use_virial ...
      84              : !> \param charges ...
      85              : !> \param atprop ...
      86              : !> \par History
      87              : !>      JGH (15-Mar-2001) : New electrostatic calculation and pressure tensor
      88              : !>      JGH (21-Mar-2001) : Complete rewrite
      89              : !>      JGH (21-Mar-2001) : Introduced real space density type for future
      90              : !>                          parallelisation
      91              : !> \author CJM and APSI
      92              : ! **************************************************************************************************
      93         2242 :    SUBROUTINE pme_evaluate(ewald_env, ewald_pw, box, particle_set, vg_coulomb, &
      94         2242 :                            fg_coulomb, pv_g, shell_particle_set, core_particle_set, &
      95         2242 :                            fgshell_coulomb, fgcore_coulomb, use_virial, charges, atprop)
      96              :       TYPE(ewald_environment_type), POINTER              :: ewald_env
      97              :       TYPE(ewald_pw_type), POINTER                       :: ewald_pw
      98              :       TYPE(cell_type), POINTER                           :: box
      99              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     100              :       REAL(KIND=dp), INTENT(OUT)                         :: vg_coulomb
     101              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT), &
     102              :          OPTIONAL                                        :: fg_coulomb, pv_g
     103              :       TYPE(particle_type), DIMENSION(:), OPTIONAL, &
     104              :          POINTER                                         :: shell_particle_set, core_particle_set
     105              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT), &
     106              :          OPTIONAL                                        :: fgshell_coulomb, fgcore_coulomb
     107              :       LOGICAL, INTENT(IN)                                :: use_virial
     108              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: charges
     109              :       TYPE(atprop_type), POINTER                         :: atprop
     110              : 
     111              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'pme_evaluate'
     112              : 
     113              :       INTEGER                                            :: handle, i, ipart, j, npart, nshell, p1, &
     114              :                                                             p2
     115              :       LOGICAL                                            :: is1_core, is2_core
     116              :       REAL(KIND=dp)                                      :: alpha, dvols, fat1, ffa
     117              :       REAL(KIND=dp), DIMENSION(3)                        :: fat
     118              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: f_stress, h_stress
     119              :       TYPE(dg_rho0_type), POINTER                        :: dg_rho0
     120              :       TYPE(dg_type), POINTER                             :: dg
     121              :       TYPE(mp_comm_type)                                 :: group
     122         8968 :       TYPE(pw_c1d_gs_type), DIMENSION(3)                 :: dphi_g
     123              :       TYPE(pw_grid_type), POINTER                        :: grid_b, grid_s
     124              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     125              :       TYPE(pw_pool_type), POINTER                        :: pw_big_pool, pw_small_pool
     126              :       TYPE(pw_r3d_rs_type)                               :: phi_r, rhob_r, rhos1, rhos2
     127              :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
     128        80712 :       TYPE(realspace_grid_type), DIMENSION(3)            :: drpot
     129              :       TYPE(realspace_grid_type), POINTER                 :: rden, rpot
     130              :       TYPE(structure_factor_type)                        :: exp_igr
     131              : 
     132         2242 :       CALL timeset(routineN, handle)
     133         2242 :       NULLIFY (poisson_env, rden)
     134         2242 :       CALL cite_reference(Darden1993)
     135         2242 :       CALL ewald_env_get(ewald_env, alpha=alpha, group=group)
     136              :       CALL ewald_pw_get(ewald_pw, pw_big_pool=pw_big_pool, &
     137              :                         pw_small_pool=pw_small_pool, rs_desc=rs_desc, &
     138         2242 :                         poisson_env=poisson_env, dg=dg)
     139              : 
     140         2242 :       grid_b => pw_big_pool%pw_grid
     141         2242 :       grid_s => pw_small_pool%pw_grid
     142              : 
     143         2242 :       CALL dg_get(dg, dg_rho0=dg_rho0)
     144              : 
     145         2242 :       npart = SIZE(particle_set)
     146              : 
     147         2242 :       CALL structure_factor_init(exp_igr)
     148              : 
     149         2242 :       IF (PRESENT(shell_particle_set)) THEN
     150            0 :          CPASSERT(ASSOCIATED(shell_particle_set))
     151            0 :          CPASSERT(ASSOCIATED(core_particle_set))
     152            0 :          nshell = SIZE(shell_particle_set)
     153              :          CALL structure_factor_allocate(grid_s%bounds, npart, exp_igr, &
     154              :                                         allocate_centre=.TRUE., allocate_shell_e=.TRUE., &
     155            0 :                                         allocate_shell_centre=.TRUE., nshell=nshell)
     156              : 
     157              :       ELSE
     158              :          CALL structure_factor_allocate(grid_s%bounds, npart, exp_igr, &
     159         2242 :                                         allocate_centre=.TRUE.)
     160              :       END IF
     161              : 
     162         2242 :       CALL pw_small_pool%create_pw(rhos1)
     163         2242 :       CALL pw_small_pool%create_pw(rhos2)
     164              : 
     165        47082 :       ALLOCATE (rden)
     166         2242 :       CALL rs_grid_create(rden, rs_desc)
     167         2242 :       CALL rs_grid_set_box(grid_b, rs=rden)
     168         2242 :       CALL rs_grid_zero(rden)
     169              : 
     170         2242 :       CPASSERT(ASSOCIATED(box))
     171              : 
     172         2242 :       IF (rden%desc%parallel .AND. rden%desc%distributed) THEN
     173            0 :          CALL get_center(particle_set, box, exp_igr%centre, exp_igr%delta, grid_b%npts, 1)
     174              :       END IF
     175         2242 :       IF (PRESENT(shell_particle_set) .AND. rden%desc%parallel .AND. rden%desc%distributed) THEN
     176            0 :          CALL get_center(shell_particle_set, box, exp_igr%shell_centre, exp_igr%shell_delta, grid_b%npts, 1)
     177            0 :          CALL get_center(core_particle_set, box, exp_igr%core_centre, exp_igr%core_delta, grid_b%npts, 1)
     178              :       END IF
     179              : 
     180              :       !-------------- DENSITY CALCULATION ----------------
     181              : 
     182         2242 :       ipart = 0
     183        42968 :       DO
     184              : 
     185        21484 :          CALL set_list(particle_set, npart, exp_igr%centre, p1, rden, ipart, exp_igr%core_centre)
     186        21484 :          CALL set_list(particle_set, npart, exp_igr%centre, p2, rden, ipart, exp_igr%core_centre)
     187        21484 :          IF (p1 == 0 .AND. p2 == 0) EXIT
     188              : 
     189        19242 :          is1_core = (particle_set(p1)%shell_index /= 0)
     190        19242 :          IF (p2 /= 0) THEN
     191        17905 :             is2_core = (particle_set(p2)%shell_index /= 0)
     192              :          ELSE
     193         1337 :             is2_core = .FALSE.
     194              :          END IF
     195              : 
     196              :          ! calculate function on small boxes (we use double packing in FFT)
     197        21484 :          IF (is1_core .OR. is2_core) THEN
     198              :             CALL get_patch(dg, particle_set, exp_igr, box, p1, p2, grid_b, grid_s, &
     199              :                            rhos1, rhos2, is1_core=is1_core, is2_core=is2_core, &
     200            0 :                            core_particle_set=core_particle_set, charges=charges)
     201              : 
     202              :             ! add boxes to real space grid (big box)
     203            0 :             IF (is1_core) THEN
     204            0 :                CALL dg_sum_patch(rden, rhos1, exp_igr%core_centre(:, particle_set(p1)%shell_index))
     205              :             ELSE
     206            0 :                CALL dg_sum_patch(rden, rhos1, exp_igr%centre(:, p1))
     207              :             END IF
     208            0 :             IF (p2 /= 0 .AND. is2_core) THEN
     209            0 :                CALL dg_sum_patch(rden, rhos2, exp_igr%core_centre(:, particle_set(p2)%shell_index))
     210            0 :             ELSE IF (p2 /= 0) THEN
     211            0 :                CALL dg_sum_patch(rden, rhos2, exp_igr%centre(:, p2))
     212              :             END IF
     213              :          ELSE
     214              :             CALL get_patch(dg, particle_set, exp_igr, box, p1, p2, grid_b, grid_s, &
     215        19242 :                            rhos1, rhos2, charges=charges)
     216              :             ! add boxes to real space grid (big box)
     217        19242 :             CALL dg_sum_patch(rden, rhos1, exp_igr%centre(:, p1))
     218        19242 :             IF (p2 /= 0) CALL dg_sum_patch(rden, rhos2, exp_igr%centre(:, p2))
     219              :          END IF
     220              : 
     221              :       END DO
     222         2242 :       IF (PRESENT(shell_particle_set)) THEN
     223            0 :          ipart = 0
     224            0 :          DO
     225            0 :             CALL set_list(shell_particle_set, nshell, exp_igr%shell_centre, p1, rpot, ipart)
     226            0 :             CALL set_list(shell_particle_set, nshell, exp_igr%shell_centre, p2, rpot, ipart)
     227            0 :             IF (p1 == 0 .AND. p2 == 0) EXIT
     228              :             ! calculate function on small boxes (we use double packing in FFT)
     229              :             CALL get_patch(dg, shell_particle_set, exp_igr, box, p1, p2, grid_b, grid_s, &
     230            0 :                            rhos1, rhos2, is1_shell=.TRUE., is2_shell=.TRUE., charges=charges)
     231              :             ! add boxes to real space grid (big box)
     232            0 :             CALL dg_sum_patch(rpot, rhos1, exp_igr%shell_centre(:, p1))
     233            0 :             IF (p2 /= 0) CALL dg_sum_patch(rpot, rhos2, exp_igr%shell_centre(:, p2))
     234              :          END DO
     235              :       END IF
     236              : 
     237         2242 :       CALL pw_big_pool%create_pw(rhob_r)
     238         2242 :       CALL transfer_rs2pw(rden, rhob_r)
     239              : 
     240              :       !-------------- ELECTROSTATIC CALCULATION -----------
     241              : 
     242              :       ! allocate intermediate arrays
     243         8968 :       DO i = 1, 3
     244         8968 :          CALL pw_big_pool%create_pw(dphi_g(i))
     245              :       END DO
     246         2242 :       CALL pw_big_pool%create_pw(phi_r)
     247              : 
     248         2242 :       CALL pw_poisson_solve(poisson_env, rhob_r, vg_coulomb, phi_r, dphi_g, h_stress)
     249              : 
     250              :       ! atomic energies
     251         2242 :       IF (atprop%energy) THEN
     252          202 :          dvols = rhos1%pw_grid%dvol
     253         4242 :          ALLOCATE (rpot)
     254          202 :          CALL rs_grid_create(rpot, rs_desc)
     255          202 :          CALL transfer_pw2rs(rpot, phi_r)
     256          202 :          ipart = 0
     257          808 :          DO
     258          404 :             CALL set_list(particle_set, npart, exp_igr%centre, p1, rden, ipart, exp_igr%core_centre)
     259          404 :             CALL set_list(particle_set, npart, exp_igr%centre, p2, rden, ipart, exp_igr%core_centre)
     260          404 :             IF (p1 == 0 .AND. p2 == 0) EXIT
     261              :             ! integrate box and potential
     262              :             CALL get_patch(dg, particle_set, exp_igr, box, p1, p2, grid_b, grid_s, &
     263          202 :                            rhos1, rhos2, charges=charges)
     264              :             ! add boxes to real space grid (big box)
     265          202 :             CALL dg_sum_patch_force_1d(rpot, rhos1, exp_igr%centre(:, p1), fat1)
     266          202 :             IF (atprop%energy) THEN
     267          202 :                atprop%atener(p1) = atprop%atener(p1) + 0.5_dp*fat1*dvols
     268              :             END IF
     269          404 :             IF (p2 /= 0) THEN
     270          101 :                CALL dg_sum_patch_force_1d(rpot, rhos2, exp_igr%centre(:, p2), fat1)
     271          101 :                IF (atprop%energy) THEN
     272          101 :                   atprop%atener(p2) = atprop%atener(p2) + 0.5_dp*fat1*dvols
     273              :                END IF
     274              :             END IF
     275              :          END DO
     276          202 :          CALL rs_grid_release(rpot)
     277          202 :          DEALLOCATE (rpot)
     278              :       END IF
     279              : 
     280         2242 :       CALL pw_big_pool%give_back_pw(phi_r)
     281              : 
     282              :       !---------- END OF ELECTROSTATIC CALCULATION --------
     283              : 
     284              :       !------------- STRESS TENSOR CALCULATION ------------
     285              : 
     286         2242 :       IF ((use_virial) .AND. (PRESENT(pv_g))) THEN
     287          808 :          DO i = 1, 3
     288         2020 :             DO j = i, 3
     289         1212 :                f_stress(i, j) = pw_integral_a2b(dphi_g(i), dphi_g(j))
     290         1818 :                f_stress(j, i) = f_stress(i, j)
     291              :             END DO
     292              :          END DO
     293          202 :          ffa = (1.0_dp/fourpi)*(0.5_dp/dg_rho0%zet(1))**2
     294         2626 :          f_stress = -ffa*f_stress
     295         2626 :          pv_g = h_stress + f_stress
     296              :       END IF
     297              : 
     298              :       !--------END OF STRESS TENSOR CALCULATION -----------
     299              : 
     300         8968 :       DO i = 1, 3
     301         6726 :          CALL rs_grid_create(drpot(i), rs_desc)
     302         6726 :          CALL rs_grid_set_box(grid_b, rs=drpot(i))
     303         6726 :          CALL pw_transfer(dphi_g(i), rhob_r)
     304         6726 :          CALL pw_big_pool%give_back_pw(dphi_g(i))
     305         8968 :          CALL transfer_pw2rs(drpot(i), rhob_r)
     306              :       END DO
     307              : 
     308         2242 :       CALL pw_big_pool%give_back_pw(rhob_r)
     309              : 
     310              :       !----------------- FORCE CALCULATION ----------------
     311              : 
     312              :       ! initialize the forces
     313         2242 :       IF (PRESENT(fg_coulomb)) THEN
     314       299514 :          fg_coulomb = 0.0_dp
     315         2242 :          dvols = rhos1%pw_grid%dvol
     316              : 
     317         2242 :          ipart = 0
     318        42968 :          DO
     319              : 
     320        21484 :             CALL set_list(particle_set, npart, exp_igr%centre, p1, rden, ipart, exp_igr%core_centre)
     321        21484 :             CALL set_list(particle_set, npart, exp_igr%centre, p2, rden, ipart, exp_igr%core_centre)
     322        21484 :             IF (p1 == 0 .AND. p2 == 0) EXIT
     323              : 
     324        19242 :             is1_core = (particle_set(p1)%shell_index /= 0)
     325        19242 :             IF (p2 /= 0) THEN
     326        17905 :                is2_core = (particle_set(p2)%shell_index /= 0)
     327              :             ELSE
     328         1337 :                is2_core = .FALSE.
     329              :             END IF
     330              : 
     331              :             ! calculate function on small boxes (we use double packing in FFT)
     332              : 
     333              :             CALL get_patch_again(dg, particle_set, exp_igr, p1, p2, rhos1, rhos2, &
     334        19242 :                                  is1_core=is1_core, is2_core=is2_core, charges=charges)
     335              : 
     336              :             ! sum boxes on real space grids (big box)
     337        19242 :             IF (is1_core) THEN
     338              :                CALL dg_sum_patch_force_3d(drpot, rhos1, &
     339            0 :                                           exp_igr%core_centre(:, particle_set(p1)%shell_index), fat)
     340              :                fgcore_coulomb(1, particle_set(p1)%shell_index) = &
     341            0 :                   fgcore_coulomb(1, particle_set(p1)%shell_index) - fat(1)*dvols
     342              :                fgcore_coulomb(2, particle_set(p1)%shell_index) = &
     343            0 :                   fgcore_coulomb(2, particle_set(p1)%shell_index) - fat(2)*dvols
     344              :                fgcore_coulomb(3, particle_set(p1)%shell_index) = &
     345            0 :                   fgcore_coulomb(3, particle_set(p1)%shell_index) - fat(3)*dvols
     346              :             ELSE
     347        19242 :                CALL dg_sum_patch_force_3d(drpot, rhos1, exp_igr%centre(:, p1), fat)
     348        19242 :                fg_coulomb(1, p1) = fg_coulomb(1, p1) - fat(1)*dvols
     349        19242 :                fg_coulomb(2, p1) = fg_coulomb(2, p1) - fat(2)*dvols
     350        19242 :                fg_coulomb(3, p1) = fg_coulomb(3, p1) - fat(3)*dvols
     351              :             END IF
     352        21484 :             IF (p2 /= 0 .AND. is2_core) THEN
     353              :                CALL dg_sum_patch_force_3d(drpot, rhos1, &
     354            0 :                                           exp_igr%core_centre(:, particle_set(p2)%shell_index), fat)
     355              :                fgcore_coulomb(1, particle_set(p2)%shell_index) = &
     356            0 :                   fgcore_coulomb(1, particle_set(p2)%shell_index) - fat(1)*dvols
     357              :                fgcore_coulomb(2, particle_set(p2)%shell_index) = &
     358            0 :                   fgcore_coulomb(2, particle_set(p2)%shell_index) - fat(2)*dvols
     359              :                fgcore_coulomb(3, particle_set(p2)%shell_index) = &
     360            0 :                   fgcore_coulomb(3, particle_set(p2)%shell_index) - fat(3)*dvols
     361        19242 :             ELSE IF (p2 /= 0) THEN
     362        17905 :                CALL dg_sum_patch_force_3d(drpot, rhos2, exp_igr%centre(:, p2), fat)
     363        17905 :                fg_coulomb(1, p2) = fg_coulomb(1, p2) - fat(1)*dvols
     364        17905 :                fg_coulomb(2, p2) = fg_coulomb(2, p2) - fat(2)*dvols
     365        17905 :                fg_coulomb(3, p2) = fg_coulomb(3, p2) - fat(3)*dvols
     366              :             END IF
     367              : 
     368              :          END DO
     369              :       END IF
     370         2242 :       IF (PRESENT(fgshell_coulomb)) THEN
     371            0 :          fgshell_coulomb = 0.0_dp
     372            0 :          dvols = rhos1%pw_grid%dvol
     373              : 
     374            0 :          ipart = 0
     375            0 :          DO
     376            0 :             CALL set_list(shell_particle_set, nshell, exp_igr%shell_centre, p1, rden, ipart)
     377            0 :             CALL set_list(shell_particle_set, nshell, exp_igr%shell_centre, p2, rden, ipart)
     378            0 :             IF (p1 == 0 .AND. p2 == 0) EXIT
     379              : 
     380              :             ! calculate function on small boxes (we use double packing in FFT)
     381              :             CALL get_patch_again(dg, shell_particle_set, exp_igr, p1, p2, rhos1, rhos2, &
     382            0 :                                  is1_shell=.TRUE., is2_shell=.TRUE., charges=charges)
     383              : 
     384              :             ! sum boxes on real space grids (big box)
     385            0 :             CALL dg_sum_patch_force_3d(drpot, rhos1, exp_igr%shell_centre(:, p1), fat)
     386            0 :             fgshell_coulomb(1, p1) = fgshell_coulomb(1, p1) - fat(1)*dvols
     387            0 :             fgshell_coulomb(2, p1) = fgshell_coulomb(2, p1) - fat(2)*dvols
     388            0 :             fgshell_coulomb(3, p1) = fgshell_coulomb(3, p1) - fat(3)*dvols
     389            0 :             IF (p2 /= 0) THEN
     390            0 :                CALL dg_sum_patch_force_3d(drpot, rhos2, exp_igr%shell_centre(:, p2), fat)
     391            0 :                fgshell_coulomb(1, p2) = fgshell_coulomb(1, p2) - fat(1)*dvols
     392            0 :                fgshell_coulomb(2, p2) = fgshell_coulomb(2, p2) - fat(2)*dvols
     393            0 :                fgshell_coulomb(3, p2) = fgshell_coulomb(3, p2) - fat(3)*dvols
     394              :             END IF
     395              :          END DO
     396              : 
     397              :       END IF
     398              :       !--------------END OF FORCE CALCULATION -------------
     399              : 
     400              :       !------------------CLEANING UP ----------------------
     401              : 
     402         2242 :       CALL rs_grid_release(rden)
     403         2242 :       DEALLOCATE (rden)
     404         8968 :       DO i = 1, 3
     405         8968 :          CALL rs_grid_release(drpot(i))
     406              :       END DO
     407              : 
     408         2242 :       CALL pw_small_pool%give_back_pw(rhos1)
     409         2242 :       CALL pw_small_pool%give_back_pw(rhos2)
     410         2242 :       CALL structure_factor_deallocate(exp_igr)
     411              : 
     412         2242 :       CALL timestop(handle)
     413              : 
     414        35872 :    END SUBROUTINE pme_evaluate
     415              : 
     416              : ! **************************************************************************************************
     417              : !> \brief Calculates local density in a small box
     418              : !> \param dg ...
     419              : !> \param particle_set ...
     420              : !> \param exp_igr ...
     421              : !> \param box ...
     422              : !> \param p1 ...
     423              : !> \param p2 ...
     424              : !> \param grid_b ...
     425              : !> \param grid_s ...
     426              : !> \param rhos1 ...
     427              : !> \param rhos2 ...
     428              : !> \param is1_core ...
     429              : !> \param is2_core ...
     430              : !> \param is1_shell ...
     431              : !> \param is2_shell ...
     432              : !> \param core_particle_set ...
     433              : !> \param charges ...
     434              : !> \par History
     435              : !>      JGH (23-Mar-2001) : Switch to integer from particle list pointers
     436              : !> \author JGH (21-Mar-2001)
     437              : ! **************************************************************************************************
     438        19444 :    SUBROUTINE get_patch(dg, particle_set, exp_igr, box, p1, p2, &
     439              :                         grid_b, grid_s, rhos1, rhos2, is1_core, is2_core, is1_shell, &
     440              :                         is2_shell, core_particle_set, charges)
     441              : 
     442              :       TYPE(dg_type), POINTER                             :: dg
     443              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     444              :       TYPE(structure_factor_type)                        :: exp_igr
     445              :       TYPE(cell_type), POINTER                           :: box
     446              :       INTEGER, INTENT(IN)                                :: p1, p2
     447              :       TYPE(pw_grid_type), INTENT(IN)                     :: grid_b, grid_s
     448              :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: rhos1, rhos2
     449              :       LOGICAL, OPTIONAL                                  :: is1_core, is2_core, is1_shell, is2_shell
     450              :       TYPE(particle_type), DIMENSION(:), OPTIONAL, &
     451              :          POINTER                                         :: core_particle_set
     452              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: charges
     453              : 
     454        19444 :       COMPLEX(KIND=dp), DIMENSION(:), POINTER            :: ex1, ex2, ey1, ey2, ez1, ez2
     455        19444 :       INTEGER, DIMENSION(:), POINTER                     :: center1, center2
     456              :       LOGICAL                                            :: my_is1_core, my_is1_shell, my_is2_core, &
     457              :                                                             my_is2_shell, use_charge_array
     458              :       REAL(KIND=dp)                                      :: q1, q2
     459              :       REAL(KIND=dp), DIMENSION(3)                        :: r1, r2
     460              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     461              :       TYPE(dg_rho0_type), POINTER                        :: dg_rho0
     462              :       TYPE(pw_r3d_rs_type), POINTER                      :: rho0
     463              :       TYPE(shell_kind_type), POINTER                     :: shell
     464              : 
     465        19444 :       NULLIFY (shell)
     466        19444 :       use_charge_array = .FALSE.
     467        19444 :       IF (PRESENT(charges)) use_charge_array = ASSOCIATED(charges)
     468        19444 :       my_is1_core = .FALSE.
     469        19444 :       my_is2_core = .FALSE.
     470        19444 :       IF (PRESENT(is1_core)) my_is1_core = is1_core
     471        19444 :       IF (PRESENT(is2_core)) my_is2_core = is2_core
     472        19444 :       IF (my_is1_core .OR. my_is2_core) THEN
     473            0 :          CPASSERT(PRESENT(core_particle_set))
     474              :       END IF
     475        19444 :       my_is1_shell = .FALSE.
     476        19444 :       my_is2_shell = .FALSE.
     477        19444 :       IF (PRESENT(is1_shell)) my_is1_shell = is1_shell
     478        19444 :       IF (PRESENT(is2_shell)) my_is2_shell = is2_shell
     479        19444 :       IF (my_is1_core .AND. my_is1_shell) THEN
     480            0 :          CPABORT("Shell-model: cannot be core and shell simultaneously")
     481              :       END IF
     482              : 
     483        19444 :       CALL dg_get(dg, dg_rho0=dg_rho0)
     484        19444 :       rho0 => dg_rho0%density
     485              : 
     486        19444 :       IF (my_is1_core) THEN
     487            0 :          r1 = core_particle_set(particle_set(p1)%shell_index)%r
     488              :       ELSE
     489        77776 :          r1 = particle_set(p1)%r
     490              :       END IF
     491        19444 :       atomic_kind => particle_set(p1)%atomic_kind
     492        19444 :       IF (my_is1_core) THEN
     493            0 :          CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     494            0 :          q1 = shell%charge_core
     495        19444 :       ELSE IF (my_is1_shell) THEN
     496            0 :          CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     497            0 :          q1 = shell%charge_shell
     498              :       ELSE
     499        19444 :          CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q1)
     500              :       END IF
     501        19444 :       IF (use_charge_array) q1 = charges(p1)
     502              : 
     503        19444 :       IF (my_is1_shell) THEN
     504            0 :          center1 => exp_igr%shell_centre(:, p1)
     505            0 :          ex1 => exp_igr%shell_ex(:, p1)
     506            0 :          ey1 => exp_igr%shell_ey(:, p1)
     507            0 :          ez1 => exp_igr%shell_ez(:, p1)
     508        19444 :       ELSE IF (my_is1_core) THEN
     509            0 :          center1 => exp_igr%core_centre(:, particle_set(p1)%shell_index)
     510            0 :          ex1 => exp_igr%core_ex(:, particle_set(p1)%shell_index)
     511            0 :          ey1 => exp_igr%core_ey(:, particle_set(p1)%shell_index)
     512            0 :          ez1 => exp_igr%core_ez(:, particle_set(p1)%shell_index)
     513              :       ELSE
     514        19444 :          center1 => exp_igr%centre(:, p1)
     515        19444 :          ex1 => exp_igr%ex(:, p1)
     516        19444 :          ey1 => exp_igr%ey(:, p1)
     517        19444 :          ez1 => exp_igr%ez(:, p1)
     518              :       END IF
     519              : 
     520        19444 :       CPASSERT(ASSOCIATED(box))
     521              : 
     522              :       CALL dg_get_strucfac(box%hmat, r1, grid_s%npts, grid_b%npts, center1, &
     523        19444 :                            exp_igr%lb, ex1, ey1, ez1)
     524              : 
     525        19444 :       IF (p2 /= 0) THEN
     526        18006 :          IF (my_is2_core) THEN
     527            0 :             r2 = core_particle_set(particle_set(p2)%shell_index)%r
     528              :          ELSE
     529        72024 :             r2 = particle_set(p2)%r
     530              :          END IF
     531        18006 :          atomic_kind => particle_set(p2)%atomic_kind
     532        18006 :          IF (my_is2_core) THEN
     533            0 :             CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     534            0 :             q2 = shell%charge_core
     535        18006 :          ELSE IF (my_is2_shell) THEN
     536            0 :             CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     537            0 :             q2 = shell%charge_shell
     538              :          ELSE
     539        18006 :             CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q2)
     540              :          END IF
     541        18006 :          IF (use_charge_array) q2 = charges(p2)
     542              : 
     543        18006 :          IF (my_is2_shell) THEN
     544            0 :             center2 => exp_igr%shell_centre(:, p2)
     545            0 :             ex2 => exp_igr%shell_ex(:, p2)
     546            0 :             ey2 => exp_igr%shell_ey(:, p2)
     547            0 :             ez2 => exp_igr%shell_ez(:, p2)
     548        18006 :          ELSE IF (my_is2_core) THEN
     549            0 :             center2 => exp_igr%core_centre(:, particle_set(p2)%shell_index)
     550            0 :             ex2 => exp_igr%core_ex(:, particle_set(p2)%shell_index)
     551            0 :             ey2 => exp_igr%core_ey(:, particle_set(p2)%shell_index)
     552            0 :             ez2 => exp_igr%core_ez(:, particle_set(p2)%shell_index)
     553              :          ELSE
     554        18006 :             center2 => exp_igr%centre(:, p2)
     555        18006 :             ex2 => exp_igr%ex(:, p2)
     556        18006 :             ey2 => exp_igr%ey(:, p2)
     557        18006 :             ez2 => exp_igr%ez(:, p2)
     558              :          END IF
     559              :          CALL dg_get_strucfac(box%hmat, r2, grid_s%npts, grid_b%npts, center2, &
     560        18006 :                               exp_igr%lb, ex2, ey2, ez2)
     561              :       END IF
     562              : 
     563        19444 :       IF (p2 == 0) THEN
     564         1438 :          CALL dg_get_patch(rho0, rhos1, q1, ex1, ey1, ez1)
     565              :       ELSE
     566        18006 :          CALL dg_get_patch(rho0, rhos1, rhos2, q1, q2, ex1, ey1, ez1, ex2, ey2, ez2)
     567              :       END IF
     568              : 
     569        19444 :    END SUBROUTINE get_patch
     570              : 
     571              : ! **************************************************************************************************
     572              : !> \brief ...
     573              : !> \param dg ...
     574              : !> \param particle_set ...
     575              : !> \param exp_igr ...
     576              : !> \param p1 ...
     577              : !> \param p2 ...
     578              : !> \param rhos1 ...
     579              : !> \param rhos2 ...
     580              : !> \param is1_core ...
     581              : !> \param is2_core ...
     582              : !> \param is1_shell ...
     583              : !> \param is2_shell ...
     584              : !> \param charges ...
     585              : ! **************************************************************************************************
     586        19242 :    SUBROUTINE get_patch_again(dg, particle_set, exp_igr, p1, p2, rhos1, rhos2, is1_core, &
     587              :                               is2_core, is1_shell, is2_shell, charges)
     588              : 
     589              :       TYPE(dg_type), POINTER                             :: dg
     590              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     591              :       TYPE(structure_factor_type)                        :: exp_igr
     592              :       INTEGER, INTENT(IN)                                :: p1, p2
     593              :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: rhos1, rhos2
     594              :       LOGICAL, OPTIONAL                                  :: is1_core, is2_core, is1_shell, is2_shell
     595              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: charges
     596              : 
     597        19242 :       COMPLEX(KIND=dp), DIMENSION(:), POINTER            :: ex1, ex2, ey1, ey2, ez1, ez2
     598              :       LOGICAL                                            :: my_is1_core, my_is1_shell, my_is2_core, &
     599              :                                                             my_is2_shell, use_charge_array
     600              :       REAL(KIND=dp)                                      :: q1, q2
     601              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     602              :       TYPE(dg_rho0_type), POINTER                        :: dg_rho0
     603              :       TYPE(pw_r3d_rs_type), POINTER                      :: rho0
     604              :       TYPE(shell_kind_type), POINTER                     :: shell
     605              : 
     606        19242 :       NULLIFY (shell)
     607        19242 :       use_charge_array = .FALSE.
     608        19242 :       IF (PRESENT(charges)) use_charge_array = ASSOCIATED(charges)
     609        19242 :       my_is1_core = .FALSE.
     610        19242 :       my_is2_core = .FALSE.
     611        19242 :       IF (PRESENT(is1_core)) my_is1_core = is1_core
     612        19242 :       IF (PRESENT(is2_core)) my_is2_core = is2_core
     613        19242 :       my_is1_shell = .FALSE.
     614        19242 :       my_is2_shell = .FALSE.
     615        19242 :       IF (PRESENT(is1_shell)) my_is1_shell = is1_shell
     616        19242 :       IF (PRESENT(is2_shell)) my_is2_shell = is2_shell
     617              : 
     618        19242 :       CALL dg_get(dg, dg_rho0=dg_rho0)
     619        19242 :       rho0 => dg_rho0%density
     620              : 
     621        19242 :       atomic_kind => particle_set(p1)%atomic_kind
     622        19242 :       IF (my_is1_core) THEN
     623            0 :          CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     624            0 :          q1 = shell%charge_core
     625        19242 :       ELSE IF (my_is1_shell) THEN
     626            0 :          CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     627            0 :          q1 = shell%charge_shell
     628              :       ELSE
     629        19242 :          CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q1)
     630              :       END IF
     631        19242 :       IF (use_charge_array) q1 = charges(p1)
     632        19242 :       IF (my_is1_core) THEN
     633            0 :          ex1 => exp_igr%core_ex(:, particle_set(p1)%shell_index)
     634            0 :          ey1 => exp_igr%core_ey(:, particle_set(p1)%shell_index)
     635            0 :          ez1 => exp_igr%core_ez(:, particle_set(p1)%shell_index)
     636        19242 :       ELSE IF (my_is1_shell) THEN
     637            0 :          ex1 => exp_igr%shell_ex(:, p1)
     638            0 :          ey1 => exp_igr%shell_ey(:, p1)
     639            0 :          ez1 => exp_igr%shell_ez(:, p1)
     640              :       ELSE
     641        19242 :          ex1 => exp_igr%ex(:, p1)
     642        19242 :          ey1 => exp_igr%ey(:, p1)
     643        19242 :          ez1 => exp_igr%ez(:, p1)
     644              :       END IF
     645              : 
     646        19242 :       IF (p2 /= 0) THEN
     647        17905 :          atomic_kind => particle_set(p2)%atomic_kind
     648        17905 :          IF (my_is2_core) THEN
     649            0 :             CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     650            0 :             q2 = shell%charge_core
     651        17905 :          ELSE IF (my_is2_shell) THEN
     652            0 :             CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     653            0 :             q2 = shell%charge_shell
     654              :          ELSE
     655        17905 :             CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q2)
     656              :          END IF
     657        17905 :          IF (use_charge_array) q2 = charges(p2)
     658        17905 :          IF (my_is2_core) THEN
     659            0 :             ex2 => exp_igr%core_ex(:, particle_set(p2)%shell_index)
     660            0 :             ey2 => exp_igr%core_ey(:, particle_set(p2)%shell_index)
     661            0 :             ez2 => exp_igr%core_ez(:, particle_set(p2)%shell_index)
     662        17905 :          ELSE IF (my_is2_shell) THEN
     663            0 :             ex2 => exp_igr%shell_ex(:, p2)
     664            0 :             ey2 => exp_igr%shell_ey(:, p2)
     665            0 :             ez2 => exp_igr%shell_ez(:, p2)
     666              :          ELSE
     667        17905 :             ex2 => exp_igr%ex(:, p2)
     668        17905 :             ey2 => exp_igr%ey(:, p2)
     669        17905 :             ez2 => exp_igr%ez(:, p2)
     670              :          END IF
     671              :       END IF
     672              : 
     673        19242 :       IF (p2 == 0) THEN
     674         1337 :          CALL dg_get_patch(rho0, rhos1, q1, ex1, ey1, ez1)
     675              :       ELSE
     676              :          CALL dg_get_patch(rho0, rhos1, rhos2, q1, q2, &
     677        17905 :                            ex1, ey1, ez1, ex2, ey2, ez2)
     678              :       END IF
     679              : 
     680        19242 :    END SUBROUTINE get_patch_again
     681              : 
     682              : END MODULE pme
     683              : 
        

Generated by: LCOV version 2.0-1