LCOV - code coverage report
Current view: top level - src/pw - dgs.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:e7e05ae) Lines: 431 447 96.4 %
Date: 2024-04-18 06:59:28 Functions: 26 26 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 (15-Mar-2001) : Update small grid when cell changes
      11             : !>                          with dg_grid_change
      12             : ! **************************************************************************************************
      13             : MODULE dgs
      14             : 
      15             :    USE fft_tools,                       ONLY: BWFFT,&
      16             :                                               FFT_RADIX_CLOSEST,&
      17             :                                               FFT_RADIX_NEXT_ODD,&
      18             :                                               fft3d,&
      19             :                                               fft_radix_operations
      20             :    USE kinds,                           ONLY: dp
      21             :    USE mathconstants,                   ONLY: z_one,&
      22             :                                               z_zero
      23             :    USE mathlib,                         ONLY: det_3x3,&
      24             :                                               inv_3x3
      25             :    USE pw_grid_info,                    ONLY: pw_find_cutoff
      26             :    USE pw_grid_types,                   ONLY: HALFSPACE,&
      27             :                                               pw_grid_type
      28             :    USE pw_grids,                        ONLY: pw_grid_change,&
      29             :                                               pw_grid_setup
      30             :    USE pw_methods,                      ONLY: pw_copy,&
      31             :                                               pw_multiply_with,&
      32             :                                               pw_zero
      33             :    USE pw_types,                        ONLY: pw_c3d_rs_type,&
      34             :                                               pw_r3d_rs_type
      35             :    USE realspace_grid_types,            ONLY: realspace_grid_type
      36             :    USE structure_factors,               ONLY: structure_factor_evaluate
      37             : #include "../base/base_uses.f90"
      38             : 
      39             :    IMPLICIT NONE
      40             : 
      41             :    PRIVATE
      42             : 
      43             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dgs'
      44             : 
      45             :    PUBLIC :: dg_get_patch
      46             :    PUBLIC :: dg_pme_grid_setup, &
      47             :              dg_sum_patch, dg_sum_patch_force_3d, dg_sum_patch_force_1d, &
      48             :              dg_get_strucfac, dg_grid_change
      49             : 
      50             :    INTERFACE dg_sum_patch
      51             :       MODULE PROCEDURE dg_sum_patch_coef, dg_sum_patch_arr
      52             :    END INTERFACE
      53             : 
      54             :    INTERFACE dg_sum_patch_force_3d
      55             :       MODULE PROCEDURE dg_sum_patch_force_coef_3d, dg_sum_patch_force_arr_3d
      56             :    END INTERFACE
      57             : 
      58             :    INTERFACE dg_sum_patch_force_1d
      59             :       MODULE PROCEDURE dg_sum_patch_force_coef_1d, dg_sum_patch_force_arr_1d
      60             :    END INTERFACE
      61             : 
      62             :    INTERFACE dg_get_patch
      63             :       MODULE PROCEDURE dg_get_patch_1, dg_get_patch_2
      64             :    END INTERFACE
      65             : 
      66             :    INTERFACE dg_add_patch
      67             :       MODULE PROCEDURE dg_add_patch_simple, dg_add_patch_folded
      68             :    END INTERFACE
      69             : 
      70             :    INTERFACE dg_int_patch_3d
      71             :       MODULE PROCEDURE dg_int_patch_simple_3d, dg_int_patch_folded_3d
      72             :    END INTERFACE
      73             : 
      74             :    INTERFACE dg_int_patch_1d
      75             :       MODULE PROCEDURE dg_int_patch_simple_1d, dg_int_patch_folded_1d
      76             :    END INTERFACE
      77             : 
      78             : CONTAINS
      79             : 
      80             : ! **************************************************************************************************
      81             : !> \brief ...
      82             : !> \param b_cell_hmat ...
      83             : !> \param npts_s ...
      84             : !> \param cutoff_radius ...
      85             : !> \param grid_s ...
      86             : !> \param grid_b ...
      87             : !> \param grid_ref ...
      88             : !> \param rs_dims ...
      89             : !> \param iounit ...
      90             : !> \param fft_usage ...
      91             : ! **************************************************************************************************
      92          86 :    SUBROUTINE dg_pme_grid_setup(b_cell_hmat, npts_s, cutoff_radius, grid_s, grid_b, &
      93             :                                 grid_ref, rs_dims, iounit, fft_usage)
      94             : 
      95             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: b_cell_hmat
      96             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: npts_s
      97             :       REAL(KIND=dp), INTENT(IN)                          :: cutoff_radius
      98             :       TYPE(pw_grid_type), POINTER                        :: grid_s, grid_b
      99             :       TYPE(pw_grid_type), INTENT(IN), OPTIONAL           :: grid_ref
     100             :       INTEGER, DIMENSION(2), INTENT(in), OPTIONAL        :: rs_dims
     101             :       INTEGER, INTENT(IN), OPTIONAL                      :: iounit
     102             :       LOGICAL, INTENT(IN), OPTIONAL                      :: fft_usage
     103             : 
     104             :       INTEGER, DIMENSION(2, 3)                           :: bo
     105             :       REAL(KIND=dp)                                      :: cutoff, ecut
     106             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: s_cell_hmat, unit_cell_hmat
     107             : 
     108          86 :       CALL dg_find_cutoff(b_cell_hmat, npts_s, cutoff_radius, grid_s, grid_b, cutoff)
     109             : 
     110          86 :       ecut = 0.5_dp*cutoff*cutoff
     111         860 :       bo = grid_b%bounds
     112          86 :       IF (PRESENT(grid_ref)) THEN
     113             :          CALL pw_grid_setup(b_cell_hmat, grid_b, bounds=bo, cutoff=ecut, spherical=.TRUE., &
     114           0 :                             ref_grid=grid_ref, rs_dims=rs_dims, iounit=iounit, fft_usage=fft_usage)
     115             :       ELSE
     116             :          CALL pw_grid_setup(b_cell_hmat, grid_b, bounds=bo, cutoff=ecut, spherical=.TRUE., &
     117          86 :                             rs_dims=rs_dims, iounit=iounit, fft_usage=fft_usage)
     118             :       END IF
     119             : 
     120          86 :       CALL dg_find_basis(grid_b%npts, b_cell_hmat, unit_cell_hmat)
     121             : 
     122          86 :       CALL dg_set_cell(grid_s%npts, unit_cell_hmat, s_cell_hmat)
     123             : 
     124         860 :       bo = grid_s%bounds
     125          86 :       CALL pw_grid_setup(s_cell_hmat, grid_s, bounds=bo, cutoff=ecut, iounit=iounit, fft_usage=fft_usage)
     126             : 
     127          86 :    END SUBROUTINE dg_pme_grid_setup
     128             : 
     129             : ! **************************************************************************************************
     130             : !> \brief Calculate the lengths of the cell vectors a, b, and c
     131             : !> \param cell_hmat ...
     132             : !> \return ...
     133             : !> \par History 01.2014 copied from cell_types::get_cell()
     134             : !> \author Ole Schuett
     135             : ! **************************************************************************************************
     136          86 :    PURE FUNCTION get_cell_lengths(cell_hmat) RESULT(abc)
     137             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: cell_hmat
     138             :       REAL(KIND=dp), DIMENSION(3)                        :: abc
     139             : 
     140             :       abc(1) = SQRT(cell_hmat(1, 1)*cell_hmat(1, 1) + &
     141             :                     cell_hmat(2, 1)*cell_hmat(2, 1) + &
     142          86 :                     cell_hmat(3, 1)*cell_hmat(3, 1))
     143             :       abc(2) = SQRT(cell_hmat(1, 2)*cell_hmat(1, 2) + &
     144             :                     cell_hmat(2, 2)*cell_hmat(2, 2) + &
     145          86 :                     cell_hmat(3, 2)*cell_hmat(3, 2))
     146             :       abc(3) = SQRT(cell_hmat(1, 3)*cell_hmat(1, 3) + &
     147             :                     cell_hmat(2, 3)*cell_hmat(2, 3) + &
     148          86 :                     cell_hmat(3, 3)*cell_hmat(3, 3))
     149          86 :    END FUNCTION get_cell_lengths
     150             : 
     151             : ! **************************************************************************************************
     152             : !> \brief ...
     153             : !> \param b_cell_hmat ...
     154             : !> \param npts_s ...
     155             : !> \param cutoff_radius ...
     156             : !> \param grid_s ...
     157             : !> \param grid_b ...
     158             : !> \param cutoff ...
     159             : ! **************************************************************************************************
     160          86 :    SUBROUTINE dg_find_cutoff(b_cell_hmat, npts_s, cutoff_radius, grid_s, &
     161             :                              grid_b, cutoff)
     162             : 
     163             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: b_cell_hmat
     164             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: npts_s
     165             :       REAL(KIND=dp), INTENT(IN)                          :: cutoff_radius
     166             :       TYPE(pw_grid_type), POINTER                        :: grid_s, grid_b
     167             :       REAL(KIND=dp), INTENT(OUT)                         :: cutoff
     168             : 
     169             :       INTEGER                                            :: nout(3)
     170             :       REAL(KIND=dp)                                      :: b_cell_deth, cell_lengths(3), dr(3)
     171             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: b_cell_h_inv
     172             : 
     173          86 :       b_cell_deth = ABS(det_3x3(b_cell_hmat))
     174          86 :       IF (b_cell_deth < 1.0E-10_dp) THEN
     175             :          CALL cp_abort(__LOCATION__, &
     176             :                        "An invalid set of cell vectors was specified. "// &
     177           0 :                        "The determinant det(h) is too small")
     178             :       END IF
     179          86 :       b_cell_h_inv = inv_3x3(b_cell_hmat)
     180             : 
     181             :       CALL fft_radix_operations(npts_s(1), nout(1), &
     182          86 :                                 operation=FFT_RADIX_NEXT_ODD)
     183             :       CALL fft_radix_operations(npts_s(1), nout(2), &
     184          86 :                                 operation=FFT_RADIX_NEXT_ODD)
     185             :       CALL fft_radix_operations(npts_s(1), nout(3), &
     186          86 :                                 operation=FFT_RADIX_NEXT_ODD)
     187             : 
     188          86 :       cell_lengths = get_cell_lengths(b_cell_hmat)
     189             : 
     190          86 :       CALL dg_get_spacing(nout, cutoff_radius, dr)
     191          86 :       CALL dg_find_radix(dr, cell_lengths, grid_b%npts)
     192             : 
     193             : ! In-line code to set grid_b % npts = npts_s if necessary
     194          86 :       IF (nout(1) > grid_b%npts(1)) THEN
     195           4 :          grid_b%npts(1) = nout(1)
     196           4 :          dr(1) = cell_lengths(1)/REAL(nout(1), KIND=dp)
     197             :       END IF
     198          86 :       IF (nout(2) > grid_b%npts(2)) THEN
     199           4 :          grid_b%npts(2) = nout(2)
     200           4 :          dr(2) = cell_lengths(2)/REAL(nout(2), KIND=dp)
     201             :       END IF
     202          86 :       IF (nout(3) > grid_b%npts(3)) THEN
     203           4 :          grid_b%npts(3) = nout(3)
     204             :          dr(3) = cell_lengths(3)/REAL(nout(3), KIND=dp)
     205             :       END IF
     206             : 
     207             : ! big grid bounds
     208         344 :       grid_b%bounds(1, :) = -grid_b%npts/2
     209         344 :       grid_b%bounds(2, :) = +(grid_b%npts - 1)/2
     210          86 :       grid_b%grid_span = HALFSPACE
     211             : ! small grid bounds
     212         344 :       grid_s%bounds(1, :) = -nout(:)/2
     213         344 :       grid_s%bounds(2, :) = (+nout(:) - 1)/2
     214          86 :       grid_s%grid_span = HALFSPACE
     215         344 :       grid_s%npts = nout
     216             : 
     217          86 :       cutoff = pw_find_cutoff(grid_b%npts, b_cell_h_inv)
     218             : 
     219          86 :    END SUBROUTINE dg_find_cutoff
     220             : 
     221             : ! **************************************************************************************************
     222             : !> \brief ...
     223             : !> \param npts ...
     224             : !> \param cutoff_radius ...
     225             : !> \param dr ...
     226             : ! **************************************************************************************************
     227          86 :    SUBROUTINE dg_get_spacing(npts, cutoff_radius, dr)
     228             : 
     229             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: npts
     230             :       REAL(KIND=dp), INTENT(IN)                          :: cutoff_radius
     231             :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: dr
     232             : 
     233         344 :       dr(:) = cutoff_radius/(REAL(npts(:), KIND=dp)/2.0_dp)
     234             : 
     235          86 :    END SUBROUTINE dg_get_spacing
     236             : 
     237             : ! **************************************************************************************************
     238             : !> \brief ...
     239             : !> \param b_cell_hmat ...
     240             : !> \param grid_b ...
     241             : !> \param grid_s ...
     242             : ! **************************************************************************************************
     243          86 :    SUBROUTINE dg_grid_change(b_cell_hmat, grid_b, grid_s)
     244             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: b_cell_hmat
     245             :       TYPE(pw_grid_type), POINTER                        :: grid_b, grid_s
     246             : 
     247             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: s_cell_hmat, unit_cell_hmat
     248             : 
     249          86 :       CALL dg_find_basis(grid_b%npts, b_cell_hmat, unit_cell_hmat)
     250          86 :       CALL dg_set_cell(grid_s%npts, unit_cell_hmat, s_cell_hmat)
     251          86 :       CALL pw_grid_change(s_cell_hmat, grid_s)
     252          86 :    END SUBROUTINE dg_grid_change
     253             : 
     254             : ! **************************************************************************************************
     255             : !> \brief ...
     256             : !> \param dr ...
     257             : !> \param cell_lengths ...
     258             : !> \param npts ...
     259             : ! **************************************************************************************************
     260          86 :    SUBROUTINE dg_find_radix(dr, cell_lengths, npts)
     261             : 
     262             :       REAL(KIND=dp), INTENT(INOUT)                       :: dr(3)
     263             :       REAL(KIND=dp), INTENT(IN)                          :: cell_lengths(3)
     264             :       INTEGER, DIMENSION(:), INTENT(OUT)                 :: npts
     265             : 
     266             :       INTEGER, DIMENSION(3)                              :: nin
     267             : 
     268         344 :       nin(:) = NINT(cell_lengths(:)/dr(:))
     269             :       CALL fft_radix_operations(nin(1), npts(1), &
     270          86 :                                 operation=FFT_RADIX_CLOSEST)
     271             :       CALL fft_radix_operations(nin(2), npts(2), &
     272          86 :                                 operation=FFT_RADIX_CLOSEST)
     273             :       CALL fft_radix_operations(nin(3), npts(3), &
     274          86 :                                 operation=FFT_RADIX_CLOSEST)
     275         344 :       dr(:) = cell_lengths(:)/REAL(npts(:), KIND=dp)
     276             : 
     277          86 :    END SUBROUTINE dg_find_radix
     278             : 
     279             : ! **************************************************************************************************
     280             : !> \brief ...
     281             : !> \param npts ...
     282             : !> \param cell_hmat ...
     283             : !> \param unit_cell_hmat ...
     284             : ! **************************************************************************************************
     285         172 :    PURE SUBROUTINE dg_find_basis(npts, cell_hmat, unit_cell_hmat)
     286             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: npts
     287             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: cell_hmat
     288             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(OUT)        :: unit_cell_hmat
     289             : 
     290             :       INTEGER                                            :: i
     291             : 
     292         688 :       DO i = 1, 3
     293        2236 :          unit_cell_hmat(:, i) = cell_hmat(:, i)/REAL(npts(:), KIND=dp)
     294             :       END DO
     295             : 
     296         172 :    END SUBROUTINE dg_find_basis
     297             : 
     298             : !! Calculation of the basis on the mesh 'box'
     299             : 
     300             : ! **************************************************************************************************
     301             : !> \brief ...
     302             : !> \param npts ...
     303             : !> \param unit_cell_hmat ...
     304             : !> \param cell_hmat ...
     305             : ! **************************************************************************************************
     306         172 :    PURE SUBROUTINE dg_set_cell(npts, unit_cell_hmat, cell_hmat)
     307             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: npts
     308             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: unit_cell_hmat
     309             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(OUT)        :: cell_hmat
     310             : 
     311             : ! computing the unit vector along a, b, c and scaling it to length dr:
     312             : 
     313         688 :       cell_hmat(:, 1) = unit_cell_hmat(:, 1)*npts(1)
     314         688 :       cell_hmat(:, 2) = unit_cell_hmat(:, 2)*npts(2)
     315         688 :       cell_hmat(:, 3) = unit_cell_hmat(:, 3)*npts(3)
     316             : 
     317         172 :    END SUBROUTINE dg_set_cell
     318             : 
     319             : ! **************************************************************************************************
     320             : !> \brief ...
     321             : !> \param cell_hmat ...
     322             : !> \param r ...
     323             : !> \param npts_s ...
     324             : !> \param npts_b ...
     325             : !> \param centre ...
     326             : !> \param lb ...
     327             : !> \param ex ...
     328             : !> \param ey ...
     329             : !> \param ez ...
     330             : ! **************************************************************************************************
     331       26760 :    SUBROUTINE dg_get_strucfac(cell_hmat, r, npts_s, npts_b, centre, lb, ex, ey, ez)
     332             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: cell_hmat
     333             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: r
     334             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: npts_s, npts_b
     335             :       INTEGER, INTENT(OUT)                               :: centre(3)
     336             :       INTEGER, INTENT(IN)                                :: lb(3)
     337             :       COMPLEX(KIND=dp), DIMENSION(lb(1):), INTENT(OUT)   :: ex
     338             :       COMPLEX(KIND=dp), DIMENSION(lb(2):), INTENT(OUT)   :: ey
     339             :       COMPLEX(KIND=dp), DIMENSION(lb(3):), INTENT(OUT)   :: ez
     340             : 
     341             :       REAL(KIND=dp)                                      :: delta(3)
     342             : 
     343       26760 :       CALL dg_get_delta(cell_hmat, r, npts_s, npts_b, centre, delta)
     344             : 
     345       26760 :       CALL structure_factor_evaluate(delta, lb, ex, ey, ez)
     346             : 
     347       26760 :    END SUBROUTINE dg_get_strucfac
     348             : 
     349             : ! **************************************************************************************************
     350             : !> \brief ...
     351             : !> \param cell_hmat ...
     352             : !> \param r ...
     353             : !> \param npts_s ...
     354             : !> \param npts_b ...
     355             : !> \param centre ...
     356             : !> \param delta ...
     357             : ! **************************************************************************************************
     358       26760 :    SUBROUTINE dg_get_delta(cell_hmat, r, npts_s, npts_b, centre, delta)
     359             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: cell_hmat
     360             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: r
     361             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: npts_s, npts_b
     362             :       INTEGER, DIMENSION(:), INTENT(OUT)                 :: centre
     363             :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: delta
     364             : 
     365             :       REAL(KIND=dp)                                      :: cell_deth
     366             :       REAL(KIND=dp), DIMENSION(3)                        :: grid_i, s
     367             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: cell_h_inv
     368             : 
     369       26760 :       cell_deth = ABS(det_3x3(cell_hmat))
     370       26760 :       IF (cell_deth < 1.0E-10_dp) THEN
     371             :          CALL cp_abort(__LOCATION__, &
     372             :                        "An invalid set of cell vectors was specified. "// &
     373           0 :                        "The determinant det(h) is too small")
     374             :       END IF
     375             : 
     376       26760 :       cell_h_inv = inv_3x3(cell_hmat)
     377             : 
     378             : ! compute the scaled coordinate of atomi
     379      347880 :       s = MATMUL(cell_h_inv, r)
     380      107040 :       s = s - NINT(s)
     381             : 
     382             : ! find the continuous ``grid'' point (on big grid)
     383      107040 :       grid_i(1:3) = REAL(npts_b(1:3), KIND=dp)*s(1:3)
     384             : 
     385             : ! find the closest grid point (on big grid)
     386      107040 :       centre(:) = NINT(grid_i(:))
     387             : 
     388             : ! find the distance vector
     389      107040 :       delta(:) = (grid_i(:) - centre(:))/REAL(npts_s(:), KIND=dp)
     390             : 
     391      107040 :       centre(:) = centre(:) + npts_b(:)/2
     392      107040 :       centre(:) = MODULO(centre(:), npts_b(:))
     393      107040 :       centre(:) = centre(:) - npts_b(:)/2
     394             : 
     395       26760 :    END SUBROUTINE dg_get_delta
     396             : 
     397             : ! **************************************************************************************************
     398             : !> \brief ...
     399             : !> \param rs ...
     400             : !> \param rhos ...
     401             : !> \param center ...
     402             : ! **************************************************************************************************
     403       24639 :    PURE SUBROUTINE dg_sum_patch_coef(rs, rhos, center)
     404             : 
     405             :       TYPE(realspace_grid_type), INTENT(INOUT)           :: rs
     406             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rhos
     407             :       INTEGER, DIMENSION(3), INTENT(IN)                  :: center
     408             : 
     409             :       INTEGER                                            :: i, ia, ii
     410             :       INTEGER, DIMENSION(3)                              :: nc
     411             :       LOGICAL                                            :: folded
     412             : 
     413       24639 :       folded = .FALSE.
     414             : 
     415      616464 :       DO i = rhos%pw_grid%bounds(1, 1), rhos%pw_grid%bounds(2, 1)
     416      591825 :          ia = i - rhos%pw_grid%bounds(1, 1) + 1
     417      591825 :          ii = center(1) + i - rs%lb_local(1)
     418      616464 :          IF (ii < 0) THEN
     419       24659 :             rs%px(ia) = ii + rs%npts_local(1) + 1
     420       24659 :             folded = .TRUE.
     421      567166 :          ELSEIF (ii >= rs%npts_local(1)) THEN
     422       19957 :             rs%px(ia) = ii - rs%npts_local(1) + 1
     423       19957 :             folded = .TRUE.
     424             :          ELSE
     425      547209 :             rs%px(ia) = ii + 1
     426             :          END IF
     427             :       END DO
     428      616464 :       DO i = rhos%pw_grid%bounds(1, 2), rhos%pw_grid%bounds(2, 2)
     429      591825 :          ia = i - rhos%pw_grid%bounds(1, 2) + 1
     430      591825 :          ii = center(2) + i - rs%lb_local(2)
     431      616464 :          IF (ii < 0) THEN
     432        6199 :             rs%py(ia) = ii + rs%npts_local(2) + 1
     433        6199 :             folded = .TRUE.
     434      585626 :          ELSEIF (ii >= rs%npts_local(2)) THEN
     435        7161 :             rs%py(ia) = ii - rs%npts_local(2) + 1
     436        7161 :             folded = .TRUE.
     437             :          ELSE
     438      578465 :             rs%py(ia) = ii + 1
     439             :          END IF
     440             :       END DO
     441      616464 :       DO i = rhos%pw_grid%bounds(1, 3), rhos%pw_grid%bounds(2, 3)
     442      591825 :          ia = i - rhos%pw_grid%bounds(1, 3) + 1
     443      591825 :          ii = center(3) + i - rs%lb_local(3)
     444      616464 :          IF (ii < 0) THEN
     445       25463 :             rs%pz(ia) = ii + rs%npts_local(3) + 1
     446       25463 :             folded = .TRUE.
     447      566362 :          ELSEIF (ii >= rs%npts_local(3)) THEN
     448        4783 :             rs%pz(ia) = ii - rs%npts_local(3) + 1
     449        4783 :             folded = .TRUE.
     450             :          ELSE
     451      561579 :             rs%pz(ia) = ii + 1
     452             :          END IF
     453             :       END DO
     454             : 
     455       24639 :       IF (folded) THEN
     456             :          CALL dg_add_patch(rs%r, rhos%array, rhos%pw_grid%npts, &
     457       13854 :                            rs%px, rs%py, rs%pz)
     458             :       ELSE
     459       10785 :          nc(1) = rs%px(1) - 1
     460       10785 :          nc(2) = rs%py(1) - 1
     461       10785 :          nc(3) = rs%pz(1) - 1
     462       10785 :          CALL dg_add_patch(rs%r, rhos%array, rhos%pw_grid%npts, nc)
     463             :       END IF
     464             : 
     465       24639 :    END SUBROUTINE dg_sum_patch_coef
     466             : 
     467             : ! **************************************************************************************************
     468             : !> \brief ...
     469             : !> \param rs ...
     470             : !> \param rhos ...
     471             : !> \param center ...
     472             : ! **************************************************************************************************
     473     4118932 :    PURE SUBROUTINE dg_sum_patch_arr(rs, rhos, center)
     474             : 
     475             :       TYPE(realspace_grid_type), INTENT(INOUT)           :: rs
     476             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: rhos
     477             :       INTEGER, DIMENSION(3), INTENT(IN)                  :: center
     478             : 
     479             :       INTEGER                                            :: i, ia, ii
     480             :       INTEGER, DIMENSION(3)                              :: lb, nc, ns, ub
     481             :       LOGICAL                                            :: folded
     482             : 
     483     4118932 :       ns(1) = SIZE(rhos, 1)
     484     4118932 :       ns(2) = SIZE(rhos, 2)
     485     4118932 :       ns(3) = SIZE(rhos, 3)
     486    16475728 :       lb = -(ns - 1)/2
     487    16475728 :       ub = lb + ns - 1
     488     4118932 :       folded = .FALSE.
     489             : 
     490    25849816 :       DO i = lb(1), ub(1)
     491    21730884 :          ia = i - lb(1) + 1
     492    21730884 :          ii = center(1) + i - rs%lb_local(1)
     493    25849816 :          IF (ii < 0) THEN
     494      347113 :             rs%px(ia) = ii + rs%npts_local(1) + 1
     495      347113 :             folded = .TRUE.
     496    21383771 :          ELSEIF (ii >= rs%npts_local(1)) THEN
     497      740749 :             rs%px(ia) = ii - rs%npts_local(1) + 1
     498      740749 :             folded = .TRUE.
     499             :          ELSE
     500    20643022 :             rs%px(ia) = ii + 1
     501             :          END IF
     502             :       END DO
     503    25849816 :       DO i = lb(2), ub(2)
     504    21730884 :          ia = i - lb(2) + 1
     505    21730884 :          ii = center(2) + i - rs%lb_local(2)
     506    25849816 :          IF (ii < 0) THEN
     507      279893 :             rs%py(ia) = ii + rs%npts_local(2) + 1
     508      279893 :             folded = .TRUE.
     509    21450991 :          ELSEIF (ii >= rs%npts_local(2)) THEN
     510      619056 :             rs%py(ia) = ii - rs%npts_local(2) + 1
     511      619056 :             folded = .TRUE.
     512             :          ELSE
     513    20831935 :             rs%py(ia) = ii + 1
     514             :          END IF
     515             :       END DO
     516    25849816 :       DO i = lb(3), ub(3)
     517    21730884 :          ia = i - lb(3) + 1
     518    21730884 :          ii = center(3) + i - rs%lb_local(3)
     519    25849816 :          IF (ii < 0) THEN
     520      282165 :             rs%pz(ia) = ii + rs%npts_local(3) + 1
     521      282165 :             folded = .TRUE.
     522    21448719 :          ELSEIF (ii >= rs%npts_local(3)) THEN
     523      754186 :             rs%pz(ia) = ii - rs%npts_local(3) + 1
     524      754186 :             folded = .TRUE.
     525             :          ELSE
     526    20694533 :             rs%pz(ia) = ii + 1
     527             :          END IF
     528             :       END DO
     529             : 
     530     4118932 :       IF (folded) THEN
     531     1501360 :          CALL dg_add_patch(rs%r, rhos, ns, rs%px, rs%py, rs%pz)
     532             :       ELSE
     533     2617572 :          nc(1) = rs%px(1) - 1
     534     2617572 :          nc(2) = rs%py(1) - 1
     535     2617572 :          nc(3) = rs%pz(1) - 1
     536     2617572 :          CALL dg_add_patch(rs%r, rhos, ns, nc)
     537             :       END IF
     538             : 
     539     4118932 :    END SUBROUTINE dg_sum_patch_arr
     540             : 
     541             : ! **************************************************************************************************
     542             : !> \brief ...
     543             : !> \param drpot ...
     544             : !> \param rhos ...
     545             : !> \param center ...
     546             : !> \param force ...
     547             : ! **************************************************************************************************
     548     3996379 :    PURE SUBROUTINE dg_sum_patch_force_arr_3d(drpot, rhos, center, force)
     549             : 
     550             :       TYPE(realspace_grid_type), DIMENSION(:), &
     551             :          INTENT(INOUT)                                   :: drpot
     552             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: rhos
     553             :       INTEGER, DIMENSION(3), INTENT(IN)                  :: center
     554             :       REAL(KIND=dp), DIMENSION(3), INTENT(OUT)           :: force
     555             : 
     556             :       INTEGER                                            :: i, ia, ii
     557             :       INTEGER, DIMENSION(3)                              :: lb, nc, ns, ub
     558             :       LOGICAL                                            :: folded
     559             : 
     560     3996379 :       ns(1) = SIZE(rhos, 1)
     561     3996379 :       ns(2) = SIZE(rhos, 2)
     562     3996379 :       ns(3) = SIZE(rhos, 3)
     563    15985516 :       lb = -(ns - 1)/2
     564    15985516 :       ub = lb + ns - 1
     565     3996379 :       folded = .FALSE.
     566             : 
     567    25017257 :       DO i = lb(1), ub(1)
     568    21020878 :          ia = i - lb(1) + 1
     569    21020878 :          ii = center(1) + i - drpot(1)%lb_local(1)
     570    25017257 :          IF (ii < 0) THEN
     571      337633 :             drpot(1)%px(ia) = ii + drpot(1)%npts_local(1) + 1
     572      337633 :             folded = .TRUE.
     573    20683245 :          ELSEIF (ii >= drpot(1)%npts_local(1)) THEN
     574      719074 :             drpot(1)%px(ia) = ii - drpot(1)%npts_local(1) + 1
     575      719074 :             folded = .TRUE.
     576             :          ELSE
     577    19964171 :             drpot(1)%px(ia) = ii + 1
     578             :          END IF
     579             :       END DO
     580    25017257 :       DO i = lb(2), ub(2)
     581    21020878 :          ia = i - lb(2) + 1
     582    21020878 :          ii = center(2) + i - drpot(1)%lb_local(2)
     583    25017257 :          IF (ii < 0) THEN
     584      268608 :             drpot(1)%py(ia) = ii + drpot(1)%npts_local(2) + 1
     585      268608 :             folded = .TRUE.
     586    20752270 :          ELSEIF (ii >= drpot(1)%npts_local(2)) THEN
     587      601620 :             drpot(1)%py(ia) = ii - drpot(1)%npts_local(2) + 1
     588      601620 :             folded = .TRUE.
     589             :          ELSE
     590    20150650 :             drpot(1)%py(ia) = ii + 1
     591             :          END IF
     592             :       END DO
     593    25017257 :       DO i = lb(3), ub(3)
     594    21020878 :          ia = i - lb(3) + 1
     595    21020878 :          ii = center(3) + i - drpot(1)%lb_local(3)
     596    25017257 :          IF (ii < 0) THEN
     597      275524 :             drpot(1)%pz(ia) = ii + drpot(1)%npts_local(3) + 1
     598      275524 :             folded = .TRUE.
     599    20745354 :          ELSEIF (ii >= drpot(1)%npts_local(3)) THEN
     600      739832 :             drpot(1)%pz(ia) = ii - drpot(1)%npts_local(3) + 1
     601      739832 :             folded = .TRUE.
     602             :          ELSE
     603    20005522 :             drpot(1)%pz(ia) = ii + 1
     604             :          END IF
     605             :       END DO
     606             : 
     607     3996379 :       IF (folded) THEN
     608             :          CALL dg_int_patch_3d(drpot(1)%r, drpot(2)%r, &
     609             :                               drpot(3)%r, rhos, force, ns, &
     610     1463606 :                               drpot(1)%px, drpot(1)%py, drpot(1)%pz)
     611             :       ELSE
     612     2532773 :          nc(1) = drpot(1)%px(1) - 1
     613     2532773 :          nc(2) = drpot(1)%py(1) - 1
     614     2532773 :          nc(3) = drpot(1)%pz(1) - 1
     615             :          CALL dg_int_patch_3d(drpot(1)%r, drpot(2)%r, &
     616     2532773 :                               drpot(3)%r, rhos, force, ns, nc)
     617             :       END IF
     618             : 
     619     3996379 :    END SUBROUTINE dg_sum_patch_force_arr_3d
     620             : 
     621             : ! **************************************************************************************************
     622             : !> \brief ...
     623             : !> \param drpot ...
     624             : !> \param rhos ...
     625             : !> \param center ...
     626             : !> \param force ...
     627             : ! **************************************************************************************************
     628      151042 :    PURE SUBROUTINE dg_sum_patch_force_arr_1d(drpot, rhos, center, force)
     629             : 
     630             :       TYPE(realspace_grid_type), INTENT(INOUT)           :: drpot
     631             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: rhos
     632             :       INTEGER, DIMENSION(3), INTENT(IN)                  :: center
     633             :       REAL(KIND=dp), INTENT(OUT)                         :: force
     634             : 
     635             :       INTEGER                                            :: i, ia, ii
     636             :       INTEGER, DIMENSION(3)                              :: lb, nc, ns, ub
     637             :       LOGICAL                                            :: folded
     638             : 
     639      151042 :       ns(1) = SIZE(rhos, 1)
     640      151042 :       ns(2) = SIZE(rhos, 2)
     641      151042 :       ns(3) = SIZE(rhos, 3)
     642      604168 :       lb = -(ns - 1)/2
     643      604168 :       ub = lb + ns - 1
     644      151042 :       folded = .FALSE.
     645             : 
     646     1055828 :       DO i = lb(1), ub(1)
     647      904786 :          ia = i - lb(1) + 1
     648      904786 :          ii = center(1) + i - drpot%lb_local(1)
     649     1055828 :          IF (ii < 0) THEN
     650       12954 :             drpot%px(ia) = ii + drpot%npts_local(1) + 1
     651       12954 :             folded = .TRUE.
     652      891832 :          ELSEIF (ii >= drpot%desc%npts(1)) THEN
     653       26900 :             drpot%px(ia) = ii - drpot%npts_local(1) + 1
     654       26900 :             folded = .TRUE.
     655             :          ELSE
     656      864932 :             drpot%px(ia) = ii + 1
     657             :          END IF
     658             :       END DO
     659     1055828 :       DO i = lb(2), ub(2)
     660      904786 :          ia = i - lb(2) + 1
     661      904786 :          ii = center(2) + i - drpot%lb_local(2)
     662     1055828 :          IF (ii < 0) THEN
     663       16060 :             drpot%py(ia) = ii + drpot%npts_local(2) + 1
     664       16060 :             folded = .TRUE.
     665      888726 :          ELSEIF (ii >= drpot%desc%npts(2)) THEN
     666       21850 :             drpot%py(ia) = ii - drpot%npts_local(2) + 1
     667       21850 :             folded = .TRUE.
     668             :          ELSE
     669      866876 :             drpot%py(ia) = ii + 1
     670             :          END IF
     671             :       END DO
     672     1055828 :       DO i = lb(3), ub(3)
     673      904786 :          ia = i - lb(3) + 1
     674      904786 :          ii = center(3) + i - drpot%lb_local(3)
     675     1055828 :          IF (ii < 0) THEN
     676        8898 :             drpot%pz(ia) = ii + drpot%npts_local(3) + 1
     677        8898 :             folded = .TRUE.
     678      895888 :          ELSEIF (ii >= drpot%desc%npts(3)) THEN
     679       20730 :             drpot%pz(ia) = ii - drpot%npts_local(3) + 1
     680       20730 :             folded = .TRUE.
     681             :          ELSE
     682      875158 :             drpot%pz(ia) = ii + 1
     683             :          END IF
     684             :       END DO
     685             : 
     686      151042 :       IF (folded) THEN
     687             :          CALL dg_int_patch_1d(drpot%r, rhos, force, ns, &
     688       48560 :                               drpot%px, drpot%py, drpot%pz)
     689             :       ELSE
     690      102482 :          nc(1) = drpot%px(1) - 1
     691      102482 :          nc(2) = drpot%py(1) - 1
     692      102482 :          nc(3) = drpot%pz(1) - 1
     693      102482 :          CALL dg_int_patch_1d(drpot%r, rhos, force, ns, nc)
     694             :       END IF
     695             : 
     696      151042 :    END SUBROUTINE dg_sum_patch_force_arr_1d
     697             : 
     698             : ! **************************************************************************************************
     699             : !> \brief ...
     700             : !> \param drpot ...
     701             : !> \param rhos ...
     702             : !> \param center ...
     703             : !> \param force ...
     704             : ! **************************************************************************************************
     705       24639 :    PURE SUBROUTINE dg_sum_patch_force_coef_3d(drpot, rhos, center, force)
     706             : 
     707             :       TYPE(realspace_grid_type), DIMENSION(:), &
     708             :          INTENT(INOUT)                                   :: drpot
     709             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rhos
     710             :       INTEGER, DIMENSION(3), INTENT(IN)                  :: center
     711             :       REAL(KIND=dp), DIMENSION(3), INTENT(OUT)           :: force
     712             : 
     713             :       INTEGER                                            :: i, ia, ii
     714             :       INTEGER, DIMENSION(3)                              :: nc
     715             :       LOGICAL                                            :: folded
     716             : 
     717       24639 :       folded = .FALSE.
     718             : 
     719      616464 :       DO i = rhos%pw_grid%bounds(1, 1), rhos%pw_grid%bounds(2, 1)
     720      591825 :          ia = i - rhos%pw_grid%bounds(1, 1) + 1
     721      591825 :          ii = center(1) + i - drpot(1)%lb_local(1)
     722      616464 :          IF (ii < 0) THEN
     723       24659 :             drpot(1)%px(ia) = ii + drpot(1)%desc%npts(1) + 1
     724       24659 :             folded = .TRUE.
     725      567166 :          ELSEIF (ii >= drpot(1)%desc%npts(1)) THEN
     726       19957 :             drpot(1)%px(ia) = ii - drpot(1)%desc%npts(1) + 1
     727       19957 :             folded = .TRUE.
     728             :          ELSE
     729      547209 :             drpot(1)%px(ia) = ii + 1
     730             :          END IF
     731             :       END DO
     732      616464 :       DO i = rhos%pw_grid%bounds(1, 2), rhos%pw_grid%bounds(2, 2)
     733      591825 :          ia = i - rhos%pw_grid%bounds(1, 2) + 1
     734      591825 :          ii = center(2) + i - drpot(1)%lb_local(2)
     735      616464 :          IF (ii < 0) THEN
     736        6199 :             drpot(1)%py(ia) = ii + drpot(1)%desc%npts(2) + 1
     737        6199 :             folded = .TRUE.
     738      585626 :          ELSEIF (ii >= drpot(1)%desc%npts(2)) THEN
     739        7161 :             drpot(1)%py(ia) = ii - drpot(1)%desc%npts(2) + 1
     740        7161 :             folded = .TRUE.
     741             :          ELSE
     742      578465 :             drpot(1)%py(ia) = ii + 1
     743             :          END IF
     744             :       END DO
     745      616464 :       DO i = rhos%pw_grid%bounds(1, 3), rhos%pw_grid%bounds(2, 3)
     746      591825 :          ia = i - rhos%pw_grid%bounds(1, 3) + 1
     747      591825 :          ii = center(3) + i - drpot(1)%lb_local(3)
     748      616464 :          IF (ii < 0) THEN
     749       25463 :             drpot(1)%pz(ia) = ii + drpot(1)%desc%npts(3) + 1
     750       25463 :             folded = .TRUE.
     751      566362 :          ELSEIF (ii >= drpot(1)%desc%npts(3)) THEN
     752        4783 :             drpot(1)%pz(ia) = ii - drpot(1)%desc%npts(3) + 1
     753        4783 :             folded = .TRUE.
     754             :          ELSE
     755      561579 :             drpot(1)%pz(ia) = ii + 1
     756             :          END IF
     757             :       END DO
     758             : 
     759       24639 :       IF (folded) THEN
     760             :          CALL dg_int_patch_3d(drpot(1)%r, drpot(2)%r, &
     761             :                               drpot(3)%r, rhos%array, force, rhos%pw_grid%npts, &
     762       13854 :                               drpot(1)%px, drpot(1)%py, drpot(1)%pz)
     763             :       ELSE
     764       10785 :          nc(1) = drpot(1)%px(1) - 1
     765       10785 :          nc(2) = drpot(1)%py(1) - 1
     766       10785 :          nc(3) = drpot(1)%pz(1) - 1
     767             :          CALL dg_int_patch_3d(drpot(1)%r, drpot(2)%r, &
     768       10785 :                               drpot(3)%r, rhos%array, force, rhos%pw_grid%npts, nc)
     769             :       END IF
     770             : 
     771       24639 :    END SUBROUTINE dg_sum_patch_force_coef_3d
     772             : 
     773             : ! **************************************************************************************************
     774             : !> \brief ...
     775             : !> \param drpot ...
     776             : !> \param rhos ...
     777             : !> \param center ...
     778             : !> \param force ...
     779             : ! **************************************************************************************************
     780        2121 :    PURE SUBROUTINE dg_sum_patch_force_coef_1d(drpot, rhos, center, force)
     781             : 
     782             :       TYPE(realspace_grid_type), INTENT(INOUT)           :: drpot
     783             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rhos
     784             :       INTEGER, DIMENSION(3), INTENT(IN)                  :: center
     785             :       REAL(KIND=dp), INTENT(OUT)                         :: force
     786             : 
     787             :       INTEGER                                            :: i, ia, ii
     788             :       INTEGER, DIMENSION(3)                              :: nc
     789             :       LOGICAL                                            :: folded
     790             : 
     791        2121 :       folded = .FALSE.
     792             : 
     793       33936 :       DO i = rhos%pw_grid%bounds(1, 1), rhos%pw_grid%bounds(2, 1)
     794       31815 :          ia = i - rhos%pw_grid%bounds(1, 1) + 1
     795       31815 :          ii = center(1) + i - drpot%lb_local(1)
     796       33936 :          IF (ii < 0) THEN
     797           0 :             drpot%px(ia) = ii + drpot%desc%npts(1) + 1
     798           0 :             folded = .TRUE.
     799       31815 :          ELSEIF (ii >= drpot%desc%npts(1)) THEN
     800           0 :             drpot%px(ia) = ii - drpot%desc%npts(1) + 1
     801           0 :             folded = .TRUE.
     802             :          ELSE
     803       31815 :             drpot%px(ia) = ii + 1
     804             :          END IF
     805             :       END DO
     806       33936 :       DO i = rhos%pw_grid%bounds(1, 2), rhos%pw_grid%bounds(2, 2)
     807       31815 :          ia = i - rhos%pw_grid%bounds(1, 2) + 1
     808       31815 :          ii = center(2) + i - drpot%lb_local(2)
     809       33936 :          IF (ii < 0) THEN
     810           0 :             drpot%py(ia) = ii + drpot%desc%npts(2) + 1
     811           0 :             folded = .TRUE.
     812       31815 :          ELSEIF (ii >= drpot%desc%npts(2)) THEN
     813           0 :             drpot%py(ia) = ii - drpot%desc%npts(2) + 1
     814           0 :             folded = .TRUE.
     815             :          ELSE
     816       31815 :             drpot%py(ia) = ii + 1
     817             :          END IF
     818             :       END DO
     819       33936 :       DO i = rhos%pw_grid%bounds(1, 3), rhos%pw_grid%bounds(2, 3)
     820       31815 :          ia = i - rhos%pw_grid%bounds(1, 3) + 1
     821       31815 :          ii = center(3) + i - drpot%lb_local(3)
     822       33936 :          IF (ii < 0) THEN
     823           0 :             drpot%pz(ia) = ii + drpot%desc%npts(3) + 1
     824           0 :             folded = .TRUE.
     825       31815 :          ELSEIF (ii >= drpot%desc%npts(3)) THEN
     826           0 :             drpot%pz(ia) = ii - drpot%desc%npts(3) + 1
     827           0 :             folded = .TRUE.
     828             :          ELSE
     829       31815 :             drpot%pz(ia) = ii + 1
     830             :          END IF
     831             :       END DO
     832             : 
     833        2121 :       IF (folded) THEN
     834             :          CALL dg_int_patch_1d(drpot%r, rhos%array, force, &
     835           0 :                               rhos%pw_grid%npts, drpot%px, drpot%py, drpot%pz)
     836             :       ELSE
     837        2121 :          nc(1) = drpot%px(1) - 1
     838        2121 :          nc(2) = drpot%py(1) - 1
     839        2121 :          nc(3) = drpot%pz(1) - 1
     840        2121 :          CALL dg_int_patch_1d(drpot%r, rhos%array, force, rhos%pw_grid%npts, nc)
     841             :       END IF
     842             : 
     843        2121 :    END SUBROUTINE dg_sum_patch_force_coef_1d
     844             : 
     845             : ! **************************************************************************************************
     846             : !> \brief ...
     847             : !> \param rho0 ...
     848             : !> \param rhos1 ...
     849             : !> \param charge1 ...
     850             : !> \param ex1 ...
     851             : !> \param ey1 ...
     852             : !> \param ez1 ...
     853             : ! **************************************************************************************************
     854        2957 :    SUBROUTINE dg_get_patch_1(rho0, rhos1, charge1, ex1, ey1, ez1)
     855             : 
     856             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho0
     857             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: rhos1
     858             :       REAL(KIND=dp), INTENT(IN)                          :: charge1
     859             :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(IN)         :: ex1, ey1, ez1
     860             : 
     861             :       COMPLEX(KIND=dp)                                   :: za, zb
     862             :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: zs
     863             :       INTEGER                                            :: nd(3)
     864             :       TYPE(pw_c3d_rs_type)                               :: cd
     865             : 
     866       11828 :       nd = rhos1%pw_grid%npts
     867             : 
     868        8871 :       ALLOCATE (zs(nd(1)*nd(2)))
     869     1487482 :       zs = 0.0_dp
     870        2957 :       CALL cd%create(rho0%pw_grid)
     871        2957 :       CALL pw_zero(cd)
     872             : 
     873        2957 :       za = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
     874        2957 :       zb = CMPLX(charge1, 0.0_dp, KIND=dp)
     875        2957 :       CALL rankup(nd, za, cd%array, zb, ex1, ey1, ez1, zs)
     876        2957 :       CALL pw_multiply_with(cd, rho0)
     877        2957 :       CALL fft3d(BWFFT, nd, cd%array)
     878        2957 :       CALL pw_copy(cd, rhos1)
     879             : 
     880        2957 :       DEALLOCATE (zs)
     881        2957 :       CALL cd%release()
     882             : 
     883        2957 :    END SUBROUTINE dg_get_patch_1
     884             : 
     885             : ! **************************************************************************************************
     886             : !> \brief ...
     887             : !> \param rho0 ...
     888             : !> \param rhos1 ...
     889             : !> \param rhos2 ...
     890             : !> \param charge1 ...
     891             : !> \param charge2 ...
     892             : !> \param ex1 ...
     893             : !> \param ey1 ...
     894             : !> \param ez1 ...
     895             : !> \param ex2 ...
     896             : !> \param ey2 ...
     897             : !> \param ez2 ...
     898             : ! **************************************************************************************************
     899       24221 :    SUBROUTINE dg_get_patch_2(rho0, rhos1, rhos2, charge1, charge2, &
     900       24221 :                              ex1, ey1, ez1, ex2, ey2, ez2)
     901             : 
     902             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho0
     903             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: rhos1, rhos2
     904             :       REAL(KIND=dp), INTENT(IN)                          :: charge1, charge2
     905             :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(IN)         :: ex1, ey1, ez1, ex2, ey2, ez2
     906             : 
     907             :       COMPLEX(KIND=dp)                                   :: za, zb
     908             :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: zs
     909             :       INTEGER                                            :: nd(3)
     910             :       TYPE(pw_c3d_rs_type)                               :: cd
     911             : 
     912       96884 :       nd = rhos1%pw_grid%npts
     913             : 
     914       72663 :       ALLOCATE (zs(nd(1)*nd(2)))
     915    13953946 :       zs = 0.0_dp
     916       24221 :       CALL cd%create(rhos1%pw_grid)
     917       24221 :       CALL pw_zero(cd)
     918             : 
     919       24221 :       za = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
     920       24221 :       zb = CMPLX(charge2, 0.0_dp, KIND=dp)
     921       24221 :       CALL rankup(nd, za, cd%array, zb, ex2, ey2, ez2, zs)
     922       24221 :       za = CMPLX(0.0_dp, 1.0_dp, KIND=dp)
     923       24221 :       zb = CMPLX(charge1, 0.0_dp, KIND=dp)
     924       24221 :       CALL rankup(nd, za, cd%array, zb, ex1, ey1, ez1, zs)
     925       24221 :       CALL pw_multiply_with(cd, rho0)
     926       24221 :       CALL fft3d(BWFFT, nd, cd%array)
     927       24221 :       CALL copy_cri(cd%array, rhos1%array, rhos2%array)
     928             : 
     929       24221 :       DEALLOCATE (zs)
     930       24221 :       CALL cd%release()
     931             : 
     932       24221 :    END SUBROUTINE dg_get_patch_2
     933             : 
     934             : ! **************************************************************************************************
     935             : !> \brief ...
     936             : !> \param rb ...
     937             : !> \param rs ...
     938             : !> \param ns ...
     939             : !> \param nc ...
     940             : ! **************************************************************************************************
     941     2628357 :    PURE SUBROUTINE dg_add_patch_simple(rb, rs, ns, nc)
     942             : 
     943             :       REAL(KIND=dp), INTENT(INOUT)                       :: rb(:, :, :)
     944             :       REAL(KIND=dp), INTENT(IN)                          :: rs(:, :, :)
     945             :       INTEGER, INTENT(IN)                                :: ns(3), nc(3)
     946             : 
     947             :       INTEGER                                            :: i, ii, j, jj, k, kk
     948             : 
     949    16475405 :       DO k = 1, ns(3)
     950    13847048 :          kk = nc(3) + k
     951    96100545 :          DO j = 1, ns(2)
     952    79625140 :             jj = nc(2) + j
     953   662659466 :             DO i = 1, ns(1)
     954   569187278 :                ii = nc(1) + i
     955   648812418 :                rb(ii, jj, kk) = rb(ii, jj, kk) + rs(i, j, k)
     956             :             END DO
     957             :          END DO
     958             :       END DO
     959             : 
     960     2628357 :    END SUBROUTINE dg_add_patch_simple
     961             : 
     962             : ! **************************************************************************************************
     963             : !> \brief ...
     964             : !> \param rb ...
     965             : !> \param rs ...
     966             : !> \param ns ...
     967             : !> \param px ...
     968             : !> \param py ...
     969             : !> \param pz ...
     970             : ! **************************************************************************************************
     971     1515214 :    PURE SUBROUTINE dg_add_patch_folded(rb, rs, ns, px, py, pz)
     972             : 
     973             :       REAL(KIND=dp), INTENT(INOUT)                       :: rb(:, :, :)
     974             :       REAL(KIND=dp), INTENT(IN)                          :: rs(:, :, :)
     975             :       INTEGER, INTENT(IN)                                :: ns(:)
     976             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: px, py, pz
     977             : 
     978             :       INTEGER                                            :: i, ii, j, jj, k, kk
     979             : 
     980     9990875 :       DO k = 1, ns(3)
     981     8475661 :          kk = pz(k)
     982    63296468 :          DO j = 1, ns(2)
     983    53305593 :             jj = py(j)
     984   511883315 :             DO i = 1, ns(1)
     985   450102061 :                ii = px(i)
     986   503407654 :                rb(ii, jj, kk) = rb(ii, jj, kk) + rs(i, j, k)
     987             :             END DO
     988             :          END DO
     989             :       END DO
     990             : 
     991     1515214 :    END SUBROUTINE dg_add_patch_folded
     992             : 
     993             : ! **************************************************************************************************
     994             : !> \brief ...
     995             : !> \param rbx ...
     996             : !> \param rby ...
     997             : !> \param rbz ...
     998             : !> \param rs ...
     999             : !> \param f ...
    1000             : !> \param ns ...
    1001             : !> \param nc ...
    1002             : ! **************************************************************************************************
    1003     2543558 :    PURE SUBROUTINE dg_int_patch_simple_3d(rbx, rby, rbz, rs, f, ns, nc)
    1004             : 
    1005             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: rbx, rby, rbz, rs
    1006             :       REAL(KIND=dp), DIMENSION(3), INTENT(OUT)           :: f
    1007             :       INTEGER, INTENT(IN)                                :: ns(3), nc(3)
    1008             : 
    1009             :       INTEGER                                            :: i, ii, j, jj, k, kk
    1010             :       REAL(KIND=dp)                                      :: s
    1011             : 
    1012     2543558 :       f = 0.0_dp
    1013    15899944 :       DO k = 1, ns(3)
    1014    13356386 :          kk = nc(3) + k
    1015    92637338 :          DO j = 1, ns(2)
    1016    76737394 :             jj = nc(2) + j
    1017   641979824 :             DO i = 1, ns(1)
    1018   551886044 :                ii = nc(1) + i
    1019   551886044 :                s = rs(i, j, k)
    1020   551886044 :                f(1) = f(1) + s*rbx(ii, jj, kk)
    1021   551886044 :                f(2) = f(2) + s*rby(ii, jj, kk)
    1022   628623438 :                f(3) = f(3) + s*rbz(ii, jj, kk)
    1023             :             END DO
    1024             :          END DO
    1025             :       END DO
    1026             : 
    1027     2543558 :    END SUBROUTINE dg_int_patch_simple_3d
    1028             : 
    1029             : ! **************************************************************************************************
    1030             : !> \brief ...
    1031             : !> \param rb ...
    1032             : !> \param rs ...
    1033             : !> \param f ...
    1034             : !> \param ns ...
    1035             : !> \param nc ...
    1036             : ! **************************************************************************************************
    1037      104603 :    PURE SUBROUTINE dg_int_patch_simple_1d(rb, rs, f, ns, nc)
    1038             : 
    1039             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: rb, rs
    1040             :       REAL(KIND=dp), INTENT(OUT)                         :: f
    1041             :       INTEGER, INTENT(IN)                                :: ns(3), nc(3)
    1042             : 
    1043             :       INTEGER                                            :: i, ii, j, jj, k, kk
    1044             :       REAL(KIND=dp)                                      :: s
    1045             : 
    1046      104603 :       f = 0.0_dp
    1047      747109 :       DO k = 1, ns(3)
    1048      642506 :          kk = nc(3) + k
    1049     4951541 :          DO j = 1, ns(2)
    1050     4204432 :             jj = nc(2) + j
    1051    35333540 :             DO i = 1, ns(1)
    1052    30486602 :                ii = nc(1) + i
    1053    30486602 :                s = rs(i, j, k)
    1054    34691034 :                f = f + s*rb(ii, jj, kk)
    1055             :             END DO
    1056             :          END DO
    1057             :       END DO
    1058             : 
    1059      104603 :    END SUBROUTINE dg_int_patch_simple_1d
    1060             : 
    1061             : ! **************************************************************************************************
    1062             : !> \brief ...
    1063             : !> \param rbx ...
    1064             : !> \param rby ...
    1065             : !> \param rbz ...
    1066             : !> \param rs ...
    1067             : !> \param f ...
    1068             : !> \param ns ...
    1069             : !> \param px ...
    1070             : !> \param py ...
    1071             : !> \param pz ...
    1072             : ! **************************************************************************************************
    1073     1477460 :    PURE SUBROUTINE dg_int_patch_folded_3d(rbx, rby, rbz, rs, f, ns, px, py, pz)
    1074             : 
    1075             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: rbx, rby, rbz, rs
    1076             :       REAL(KIND=dp), DIMENSION(3), INTENT(INOUT)         :: f
    1077             :       INTEGER, INTENT(IN)                                :: ns(3)
    1078             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: px, py, pz
    1079             : 
    1080             :       INTEGER                                            :: i, ii, j, jj, k, kk
    1081             :       REAL(KIND=dp)                                      :: s
    1082             : 
    1083     1477460 :       f = 0.0_dp
    1084     9733777 :       DO k = 1, ns(3)
    1085     8256317 :          kk = pz(k)
    1086    61736616 :          DO j = 1, ns(2)
    1087    52002839 :             jj = py(j)
    1088   502438587 :             DO i = 1, ns(1)
    1089   442179431 :                ii = px(i)
    1090   442179431 :                s = rs(i, j, k)
    1091   442179431 :                f(1) = f(1) + s*rbx(ii, jj, kk)
    1092   442179431 :                f(2) = f(2) + s*rby(ii, jj, kk)
    1093   494182270 :                f(3) = f(3) + s*rbz(ii, jj, kk)
    1094             :             END DO
    1095             :          END DO
    1096             :       END DO
    1097             : 
    1098     1477460 :    END SUBROUTINE dg_int_patch_folded_3d
    1099             : 
    1100             : ! **************************************************************************************************
    1101             : !> \brief ...
    1102             : !> \param rb ...
    1103             : !> \param rs ...
    1104             : !> \param f ...
    1105             : !> \param ns ...
    1106             : !> \param px ...
    1107             : !> \param py ...
    1108             : !> \param pz ...
    1109             : ! **************************************************************************************************
    1110       48560 :    PURE SUBROUTINE dg_int_patch_folded_1d(rb, rs, f, ns, px, py, pz)
    1111             : 
    1112             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: rb, rs
    1113             :       REAL(KIND=dp), INTENT(INOUT)                       :: f
    1114             :       INTEGER, INTENT(IN)                                :: ns(3)
    1115             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: px, py, pz
    1116             : 
    1117             :       INTEGER                                            :: i, ii, j, jj, k, kk
    1118             :       REAL(KIND=dp)                                      :: s
    1119             : 
    1120       48560 :       f = 0.0_dp
    1121      342655 :       DO k = 1, ns(3)
    1122      294095 :          kk = pz(k)
    1123     2177954 :          DO j = 1, ns(2)
    1124     1835299 :             jj = py(j)
    1125    13941857 :             DO i = 1, ns(1)
    1126    11812463 :                ii = px(i)
    1127    11812463 :                s = rs(i, j, k)
    1128    13647762 :                f = f + s*rb(ii, jj, kk)
    1129             :             END DO
    1130             :          END DO
    1131             :       END DO
    1132             : 
    1133       48560 :    END SUBROUTINE dg_int_patch_folded_1d
    1134             : 
    1135             : ! **************************************************************************************************
    1136             : !> \brief ...
    1137             : !> \param n ...
    1138             : !> \param za ...
    1139             : !> \param cmat ...
    1140             : !> \param zb ...
    1141             : !> \param ex ...
    1142             : !> \param ey ...
    1143             : !> \param ez ...
    1144             : !> \param scr ...
    1145             : ! **************************************************************************************************
    1146       51399 :    SUBROUTINE rankup(n, za, cmat, zb, ex, ey, ez, scr)
    1147             : !
    1148             : ! cmat(i,j,k) <- za * cmat(i,j,k) + ex(i) * ey(j) * ez(k)
    1149             : !
    1150             : 
    1151             :       INTEGER, DIMENSION(3), INTENT(IN)                  :: n
    1152             :       COMPLEX(KIND=dp), INTENT(IN)                       :: za
    1153             :       COMPLEX(KIND=dp), DIMENSION(:, :, :), &
    1154             :          INTENT(INOUT)                                   :: cmat
    1155             :       COMPLEX(KIND=dp), INTENT(IN)                       :: zb
    1156             :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(IN)         :: ex, ey, ez
    1157             :       COMPLEX(KIND=dp), DIMENSION(:), INTENT(INOUT)      :: scr
    1158             : 
    1159             :       INTEGER                                            :: n2, n3
    1160             : 
    1161       51399 :       n2 = n(1)*n(2)
    1162       51399 :       n3 = n2*n(3)
    1163    29395374 :       scr(1:n2) = z_zero
    1164       51399 :       CALL zgeru(n(1), n(2), zb, ex, 1, ey, 1, scr, n(1))
    1165       51399 :       CALL zscal(n3, za, cmat, 1)
    1166       51399 :       CALL zgeru(n2, n(3), z_one, scr, 1, ez, 1, cmat, n2)
    1167             : 
    1168       51399 :    END SUBROUTINE rankup
    1169             : 
    1170             : ! **************************************************************************************************
    1171             : !> \brief Copy a the real and imag. parts of a complex 3D array into two real arrays
    1172             : !> \param z the complex array
    1173             : !> \param r1 the real array for the real part
    1174             : !> \param r2 the real array for the imaginary part
    1175             : ! **************************************************************************************************
    1176       24221 :    SUBROUTINE copy_cri(z, r1, r2)
    1177             : !
    1178             : ! r1 = real ( z )
    1179             : ! r2 = imag ( z )
    1180             : !
    1181             : 
    1182             :       COMPLEX(KIND=dp), INTENT(IN)                       :: z(:, :, :)
    1183             :       REAL(KIND=dp), INTENT(INOUT)                       :: r1(:, :, :), r2(:, :, :)
    1184             : 
    1185       24221 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE), SHARED(r1,r2,z)
    1186             :       r1(:, :, :) = REAL(z(:, :, :), KIND=dp)
    1187             :       r2(:, :, :) = AIMAG(z(:, :, :))
    1188             : !$OMP END PARALLEL WORKSHARE
    1189             : 
    1190       24221 :    END SUBROUTINE copy_cri
    1191             : 
    1192             : END MODULE dgs

Generated by: LCOV version 1.15