LCOV - code coverage report
Current view: top level - src - pme.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 208 304 68.4 %
Date: 2024-12-21 06:28:57 Functions: 3 3 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \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        1818 :    SUBROUTINE pme_evaluate(ewald_env, ewald_pw, box, particle_set, vg_coulomb, &
      94        1818 :                            fg_coulomb, pv_g, shell_particle_set, core_particle_set, &
      95        1818 :                            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        7272 :       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       65448 :       TYPE(realspace_grid_type), DIMENSION(3)            :: drpot
     129             :       TYPE(realspace_grid_type), POINTER                 :: rden, rpot
     130             :       TYPE(structure_factor_type)                        :: exp_igr
     131             : 
     132        1818 :       CALL timeset(routineN, handle)
     133        1818 :       NULLIFY (poisson_env, rden)
     134        1818 :       CALL cite_reference(Darden1993)
     135        1818 :       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        1818 :                         poisson_env=poisson_env, dg=dg)
     139             : 
     140        1818 :       grid_b => pw_big_pool%pw_grid
     141        1818 :       grid_s => pw_small_pool%pw_grid
     142             : 
     143        1818 :       CALL dg_get(dg, dg_rho0=dg_rho0)
     144             : 
     145        1818 :       npart = SIZE(particle_set)
     146             : 
     147        1818 :       CALL structure_factor_init(exp_igr)
     148             : 
     149        1818 :       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        1818 :                                         allocate_centre=.TRUE.)
     160             :       END IF
     161             : 
     162        1818 :       CALL pw_small_pool%create_pw(rhos1)
     163        1818 :       CALL pw_small_pool%create_pw(rhos2)
     164             : 
     165       38178 :       ALLOCATE (rden)
     166        1818 :       CALL rs_grid_create(rden, rs_desc)
     167        1818 :       CALL rs_grid_set_box(grid_b, rs=rden)
     168        1818 :       CALL rs_grid_zero(rden)
     169             : 
     170        1818 :       CPASSERT(ASSOCIATED(box))
     171             : 
     172        1818 :       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        1818 :       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        1818 :       ipart = 0
     183       29400 :       DO
     184             : 
     185       14700 :          CALL set_list(particle_set, npart, exp_igr%centre, p1, rden, ipart, exp_igr%core_centre)
     186       14700 :          CALL set_list(particle_set, npart, exp_igr%centre, p2, rden, ipart, exp_igr%core_centre)
     187       14700 :          IF (p1 == 0 .AND. p2 == 0) EXIT
     188             : 
     189       12882 :          is1_core = (particle_set(p1)%shell_index /= 0)
     190       12882 :          IF (p2 /= 0) THEN
     191       11757 :             is2_core = (particle_set(p2)%shell_index /= 0)
     192             :          ELSE
     193        1125 :             is2_core = .FALSE.
     194             :          END IF
     195             : 
     196             :          ! calculate function on small boxes (we use double packing in FFT)
     197       14700 :          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       12882 :                            rhos1, rhos2, charges=charges)
     216             :             ! add boxes to real space grid (big box)
     217       12882 :             CALL dg_sum_patch(rden, rhos1, exp_igr%centre(:, p1))
     218       12882 :             IF (p2 /= 0) CALL dg_sum_patch(rden, rhos2, exp_igr%centre(:, p2))
     219             :          END IF
     220             : 
     221             :       END DO
     222        1818 :       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        1818 :       CALL pw_big_pool%create_pw(rhob_r)
     238        1818 :       CALL transfer_rs2pw(rden, rhob_r)
     239             : 
     240             :       !-------------- ELECTROSTATIC CALCULATION -----------
     241             : 
     242             :       ! allocate intermediate arrays
     243        7272 :       DO i = 1, 3
     244        7272 :          CALL pw_big_pool%create_pw(dphi_g(i))
     245             :       END DO
     246        1818 :       CALL pw_big_pool%create_pw(phi_r)
     247             : 
     248        1818 :       CALL pw_poisson_solve(poisson_env, rhob_r, vg_coulomb, phi_r, dphi_g, h_stress)
     249             : 
     250             :       ! atomic energies
     251        1818 :       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        1818 :       CALL pw_big_pool%give_back_pw(phi_r)
     281             : 
     282             :       !---------- END OF ELECTROSTATIC CALCULATION --------
     283             : 
     284             :       !------------- STRESS TENSOR CALCULATION ------------
     285             : 
     286        1818 :       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        7272 :       DO i = 1, 3
     301        5454 :          CALL rs_grid_create(drpot(i), rs_desc)
     302        5454 :          CALL rs_grid_set_box(grid_b, rs=drpot(i))
     303        5454 :          CALL pw_transfer(dphi_g(i), rhob_r)
     304        5454 :          CALL pw_big_pool%give_back_pw(dphi_g(i))
     305        7272 :          CALL transfer_pw2rs(drpot(i), rhob_r)
     306             :       END DO
     307             : 
     308        1818 :       CALL pw_big_pool%give_back_pw(rhob_r)
     309             : 
     310             :       !----------------- FORCE CALCULATION ----------------
     311             : 
     312             :       ! initialize the forces
     313        1818 :       IF (PRESENT(fg_coulomb)) THEN
     314      199026 :          fg_coulomb = 0.0_dp
     315        1818 :          dvols = rhos1%pw_grid%dvol
     316             : 
     317        1818 :          ipart = 0
     318       29400 :          DO
     319             : 
     320       14700 :             CALL set_list(particle_set, npart, exp_igr%centre, p1, rden, ipart, exp_igr%core_centre)
     321       14700 :             CALL set_list(particle_set, npart, exp_igr%centre, p2, rden, ipart, exp_igr%core_centre)
     322       14700 :             IF (p1 == 0 .AND. p2 == 0) EXIT
     323             : 
     324       12882 :             is1_core = (particle_set(p1)%shell_index /= 0)
     325       12882 :             IF (p2 /= 0) THEN
     326       11757 :                is2_core = (particle_set(p2)%shell_index /= 0)
     327             :             ELSE
     328        1125 :                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       12882 :                                  is1_core=is1_core, is2_core=is2_core, charges=charges)
     335             : 
     336             :             ! sum boxes on real space grids (big box)
     337       12882 :             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       12882 :                CALL dg_sum_patch_force_3d(drpot, rhos1, exp_igr%centre(:, p1), fat)
     348       12882 :                fg_coulomb(1, p1) = fg_coulomb(1, p1) - fat(1)*dvols
     349       12882 :                fg_coulomb(2, p1) = fg_coulomb(2, p1) - fat(2)*dvols
     350       12882 :                fg_coulomb(3, p1) = fg_coulomb(3, p1) - fat(3)*dvols
     351             :             END IF
     352       14700 :             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       12882 :             ELSEIF (p2 /= 0) THEN
     362       11757 :                CALL dg_sum_patch_force_3d(drpot, rhos2, exp_igr%centre(:, p2), fat)
     363       11757 :                fg_coulomb(1, p2) = fg_coulomb(1, p2) - fat(1)*dvols
     364       11757 :                fg_coulomb(2, p2) = fg_coulomb(2, p2) - fat(2)*dvols
     365       11757 :                fg_coulomb(3, p2) = fg_coulomb(3, p2) - fat(3)*dvols
     366             :             END IF
     367             : 
     368             :          END DO
     369             :       END IF
     370        1818 :       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        1818 :       CALL rs_grid_release(rden)
     403        1818 :       DEALLOCATE (rden)
     404        7272 :       DO i = 1, 3
     405        7272 :          CALL rs_grid_release(drpot(i))
     406             :       END DO
     407             : 
     408        1818 :       CALL pw_small_pool%give_back_pw(rhos1)
     409        1818 :       CALL pw_small_pool%give_back_pw(rhos2)
     410        1818 :       CALL structure_factor_deallocate(exp_igr)
     411             : 
     412        1818 :       CALL timestop(handle)
     413             : 
     414       29088 :    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       13084 :    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       13084 :       COMPLEX(KIND=dp), DIMENSION(:), POINTER            :: ex1, ex2, ey1, ey2, ez1, ez2
     455       13084 :       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       13084 :       NULLIFY (shell)
     466       13084 :       use_charge_array = .FALSE.
     467       13084 :       IF (PRESENT(charges)) use_charge_array = ASSOCIATED(charges)
     468       13084 :       my_is1_core = .FALSE.
     469       13084 :       my_is2_core = .FALSE.
     470       13084 :       IF (PRESENT(is1_core)) my_is1_core = is1_core
     471       13084 :       IF (PRESENT(is2_core)) my_is2_core = is2_core
     472       13084 :       IF (my_is1_core .OR. my_is2_core) THEN
     473           0 :          CPASSERT(PRESENT(core_particle_set))
     474             :       END IF
     475       13084 :       my_is1_shell = .FALSE.
     476       13084 :       my_is2_shell = .FALSE.
     477       13084 :       IF (PRESENT(is1_shell)) my_is1_shell = is1_shell
     478       13084 :       IF (PRESENT(is2_shell)) my_is2_shell = is2_shell
     479       13084 :       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       13084 :       CALL dg_get(dg, dg_rho0=dg_rho0)
     484       13084 :       rho0 => dg_rho0%density
     485             : 
     486       13084 :       IF (my_is1_core) THEN
     487           0 :          r1 = core_particle_set(particle_set(p1)%shell_index)%r
     488             :       ELSE
     489       52336 :          r1 = particle_set(p1)%r
     490             :       END IF
     491       13084 :       atomic_kind => particle_set(p1)%atomic_kind
     492       13084 :       IF (my_is1_core) THEN
     493           0 :          CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     494           0 :          q1 = shell%charge_core
     495       13084 :       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       13084 :          CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q1)
     500             :       END IF
     501       13084 :       IF (use_charge_array) q1 = charges(p1)
     502             : 
     503       13084 :       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       13084 :       ELSEIF (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       13084 :          center1 => exp_igr%centre(:, p1)
     515       13084 :          ex1 => exp_igr%ex(:, p1)
     516       13084 :          ey1 => exp_igr%ey(:, p1)
     517       13084 :          ez1 => exp_igr%ez(:, p1)
     518             :       END IF
     519             : 
     520       13084 :       CPASSERT(ASSOCIATED(box))
     521             : 
     522             :       CALL dg_get_strucfac(box%hmat, r1, grid_s%npts, grid_b%npts, center1, &
     523       13084 :                            exp_igr%lb, ex1, ey1, ez1)
     524             : 
     525       13084 :       IF (p2 /= 0) THEN
     526       11858 :          IF (my_is2_core) THEN
     527           0 :             r2 = core_particle_set(particle_set(p2)%shell_index)%r
     528             :          ELSE
     529       47432 :             r2 = particle_set(p2)%r
     530             :          END IF
     531       11858 :          atomic_kind => particle_set(p2)%atomic_kind
     532       11858 :          IF (my_is2_core) THEN
     533           0 :             CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     534           0 :             q2 = shell%charge_core
     535       11858 :          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       11858 :             CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q2)
     540             :          END IF
     541       11858 :          IF (use_charge_array) q2 = charges(p2)
     542             : 
     543       11858 :          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       11858 :          ELSEIF (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       11858 :             center2 => exp_igr%centre(:, p2)
     555       11858 :             ex2 => exp_igr%ex(:, p2)
     556       11858 :             ey2 => exp_igr%ey(:, p2)
     557       11858 :             ez2 => exp_igr%ez(:, p2)
     558             :          END IF
     559             :          CALL dg_get_strucfac(box%hmat, r2, grid_s%npts, grid_b%npts, center2, &
     560       11858 :                               exp_igr%lb, ex2, ey2, ez2)
     561             :       END IF
     562             : 
     563       13084 :       IF (p2 == 0) THEN
     564        1226 :          CALL dg_get_patch(rho0, rhos1, q1, ex1, ey1, ez1)
     565             :       ELSE
     566       11858 :          CALL dg_get_patch(rho0, rhos1, rhos2, q1, q2, ex1, ey1, ez1, ex2, ey2, ez2)
     567             :       END IF
     568             : 
     569       13084 :    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       12882 :    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       12882 :       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       12882 :       NULLIFY (shell)
     607       12882 :       use_charge_array = .FALSE.
     608       12882 :       IF (PRESENT(charges)) use_charge_array = ASSOCIATED(charges)
     609       12882 :       my_is1_core = .FALSE.
     610       12882 :       my_is2_core = .FALSE.
     611       12882 :       IF (PRESENT(is1_core)) my_is1_core = is1_core
     612       12882 :       IF (PRESENT(is2_core)) my_is2_core = is2_core
     613       12882 :       my_is1_shell = .FALSE.
     614       12882 :       my_is2_shell = .FALSE.
     615       12882 :       IF (PRESENT(is1_shell)) my_is1_shell = is1_shell
     616       12882 :       IF (PRESENT(is2_shell)) my_is2_shell = is2_shell
     617             : 
     618       12882 :       CALL dg_get(dg, dg_rho0=dg_rho0)
     619       12882 :       rho0 => dg_rho0%density
     620             : 
     621       12882 :       atomic_kind => particle_set(p1)%atomic_kind
     622       12882 :       IF (my_is1_core) THEN
     623           0 :          CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     624           0 :          q1 = shell%charge_core
     625       12882 :       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       12882 :          CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q1)
     630             :       END IF
     631       12882 :       IF (use_charge_array) q1 = charges(p1)
     632       12882 :       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       12882 :       ELSEIF (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       12882 :          ex1 => exp_igr%ex(:, p1)
     642       12882 :          ey1 => exp_igr%ey(:, p1)
     643       12882 :          ez1 => exp_igr%ez(:, p1)
     644             :       END IF
     645             : 
     646       12882 :       IF (p2 /= 0) THEN
     647       11757 :          atomic_kind => particle_set(p2)%atomic_kind
     648       11757 :          IF (my_is2_core) THEN
     649           0 :             CALL get_atomic_kind(atomic_kind=atomic_kind, shell=shell)
     650           0 :             q2 = shell%charge_core
     651       11757 :          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       11757 :             CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q2)
     656             :          END IF
     657       11757 :          IF (use_charge_array) q2 = charges(p2)
     658       11757 :          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       11757 :          ELSEIF (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       11757 :             ex2 => exp_igr%ex(:, p2)
     668       11757 :             ey2 => exp_igr%ey(:, p2)
     669       11757 :             ez2 => exp_igr%ez(:, p2)
     670             :          END IF
     671             :       END IF
     672             : 
     673       12882 :       IF (p2 == 0) THEN
     674        1125 :          CALL dg_get_patch(rho0, rhos1, q1, ex1, ey1, ez1)
     675             :       ELSE
     676             :          CALL dg_get_patch(rho0, rhos1, rhos2, q1, q2, &
     677       11757 :                            ex1, ey1, ez1, ex2, ey2, ez2)
     678             :       END IF
     679             : 
     680       12882 :    END SUBROUTINE get_patch_again
     681             : 
     682             : END MODULE pme
     683             : 

Generated by: LCOV version 1.15