LCOV - code coverage report
Current view: top level - src/pw - ps_wavelet_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 94.8 % 402 381
Test Date: 2026-07-25 06:35:44 Functions: 100.0 % 16 16

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Definition and initialisation of the ps_wavelet data type.
      10              : !> \history 01.2014 Renamed from ps_wavelet_types to disentangle dependencies (Ole Schuett)
      11              : !> \author Florian Schiffmann (09.2007,fschiff)
      12              : ! **************************************************************************************************
      13              : MODULE ps_wavelet_methods
      14              : 
      15              :    USE bibliography,                    ONLY: Genovese2006,&
      16              :                                               Genovese2007,&
      17              :                                               cite_reference
      18              :    USE kinds,                           ONLY: dp
      19              :    USE ps_wavelet_kernel,               ONLY: createKernel
      20              :    USE ps_wavelet_types,                ONLY: WAVELET0D,&
      21              :                                               WAVELET2D,&
      22              :                                               ps_wavelet_release,&
      23              :                                               ps_wavelet_type
      24              :    USE ps_wavelet_util,                 ONLY: F_FFT_dimensions,&
      25              :                                               PSolver,&
      26              :                                               P_FFT_dimensions,&
      27              :                                               S_FFT_dimensions
      28              :    USE pw_grid_types,                   ONLY: pw_grid_type
      29              :    USE pw_poisson_types,                ONLY: pw_poisson_parameter_type
      30              :    USE pw_types,                        ONLY: pw_r3d_rs_type
      31              :    USE util,                            ONLY: get_limit
      32              : #include "../base/base_uses.f90"
      33              : 
      34              :    IMPLICIT NONE
      35              : 
      36              :    PRIVATE
      37              : 
      38              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ps_wavelet_methods'
      39              : 
      40              : ! *** Public data types ***
      41              : 
      42              :    PUBLIC :: ps_wavelet_create, &
      43              :              cp2k_distribution_to_z_slices, &
      44              :              z_slices_to_cp2k_distribution, &
      45              :              ps_wavelet_solve
      46              : 
      47              : CONTAINS
      48              : 
      49              : ! **************************************************************************************************
      50              : !> \brief creates the ps_wavelet_type which is needed for the link to
      51              : !>      the Poisson Solver of Luigi Genovese
      52              : !> \param poisson_params ...
      53              : !> \param wavelet wavelet to create
      54              : !> \param pw_grid the grid that is used to create the wavelet kernel
      55              : !> \author Flroian Schiffmann
      56              : ! **************************************************************************************************
      57          856 :    SUBROUTINE ps_wavelet_create(poisson_params, wavelet, pw_grid)
      58              :       TYPE(pw_poisson_parameter_type), INTENT(IN)        :: poisson_params
      59              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
      60              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
      61              : 
      62              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'ps_wavelet_create'
      63              : 
      64              :       INTEGER                                            :: handle
      65              :       REAL(KIND=dp)                                      :: hx, hy, hz
      66              : 
      67          856 :       CALL timeset(routineN, handle)
      68              : 
      69          856 :       CALL cite_reference(Genovese2006)
      70          856 :       CALL cite_reference(Genovese2007)
      71              : 
      72          856 :       IF (ASSOCIATED(wavelet)) THEN
      73            0 :          CALL ps_wavelet_release(wavelet)
      74              :          NULLIFY (wavelet)
      75              :       END IF
      76              : 
      77         7704 :       ALLOCATE (wavelet)
      78              : 
      79              :       NULLIFY (wavelet%karray, wavelet%rho_z_sliced)
      80              : 
      81          856 :       wavelet%geocode = poisson_params%wavelet_geocode
      82          856 :       wavelet%method = poisson_params%wavelet_method
      83          856 :       wavelet%special_dimension = poisson_params%wavelet_special_dimension
      84          856 :       wavelet%itype_scf = poisson_params%wavelet_scf_type
      85          856 :       wavelet%datacode = "D"
      86              : 
      87          856 :       CALL set_wavelet_axis(wavelet)
      88          856 :       hx = pw_grid%dr(wavelet%axis(1))
      89          856 :       hy = pw_grid%dr(wavelet%axis(2))
      90          856 :       hz = pw_grid%dr(wavelet%axis(3))
      91              : 
      92          856 :       IF (poisson_params%wavelet_method == WAVELET0D) THEN
      93          524 :          IF (hx /= hy) THEN
      94            0 :             CPABORT("Poisson solver for non cubic cells not yet implemented")
      95              :          END IF
      96          524 :          IF (hz /= hy) THEN
      97            0 :             CPABORT("Poisson solver for non cubic cells not yet implemented")
      98              :          END IF
      99              :       END IF
     100              : 
     101          856 :       CALL RS_z_slice_distribution(wavelet, pw_grid)
     102              : 
     103          856 :       CALL timestop(handle)
     104          856 :    END SUBROUTINE ps_wavelet_create
     105              : 
     106              : ! **************************************************************************************************
     107              : !> \brief ...
     108              : !> \param wavelet ...
     109              : !> \param pw_grid ...
     110              : ! **************************************************************************************************
     111          856 :    SUBROUTINE RS_z_slice_distribution(wavelet, pw_grid)
     112              : 
     113              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
     114              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     115              : 
     116              :       CHARACTER(len=*), PARAMETER :: routineN = 'RS_z_slice_distribution'
     117              : 
     118              :       CHARACTER(LEN=1)                                   :: geocode
     119              :       INTEGER                                            :: handle, iproc, m1, m2, m3, md1, md2, &
     120              :                                                             md3, n1, n2, n3, nd1, nd2, nd3, nproc, &
     121              :                                                             nx, ny, nz, z_dim
     122              :       REAL(KIND=dp)                                      :: hx, hy, hz
     123              : 
     124          856 :       CALL timeset(routineN, handle)
     125         2568 :       nproc = PRODUCT(pw_grid%para%group%num_pe_cart)
     126          856 :       iproc = pw_grid%para%group%mepos
     127          856 :       geocode = wavelet%geocode
     128          856 :       CALL get_wavelet_grid(wavelet, pw_grid, nx, ny, nz, hx, hy, hz)
     129              : 
     130              :       !calculate Dimensions for the z-distributed density and for the kernel
     131              : 
     132          856 :       IF (geocode == 'P') THEN
     133          326 :          CALL P_FFT_dimensions(nx, ny, nz, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
     134          530 :       ELSE IF (geocode == 'S') THEN
     135            6 :          CALL S_FFT_dimensions(nx, ny, nz, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
     136          524 :       ELSE IF (geocode == 'F') THEN
     137          524 :          CALL F_FFT_dimensions(nx, ny, nz, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
     138              :       END IF
     139              : 
     140          856 :       wavelet%PS_grid(1) = md1
     141          856 :       wavelet%PS_grid(2) = md3
     142          856 :       wavelet%PS_grid(3) = md2
     143          856 :       z_dim = md2/nproc
     144              :       !!!!!!!!!      indices y and z are interchanged    !!!!!!!
     145         4280 :       ALLOCATE (wavelet%rho_z_sliced(md1, md3, z_dim))
     146              : 
     147              :       CALL createKernel(geocode, nx, ny, nz, hx, hy, hz, wavelet%itype_scf, iproc, nproc, wavelet%karray, &
     148          856 :                         pw_grid%para%group)
     149              : 
     150          856 :       CALL timestop(handle)
     151         1712 :    END SUBROUTINE RS_z_slice_distribution
     152              : 
     153              : ! **************************************************************************************************
     154              : !> \brief ...
     155              : !> \param density ...
     156              : !> \param wavelet ...
     157              : !> \param pw_grid ...
     158              : ! **************************************************************************************************
     159        33295 :    SUBROUTINE cp2k_distribution_to_z_slices(density, wavelet, pw_grid)
     160              : 
     161              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: density
     162              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
     163              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     164              : 
     165              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp2k_distribution_to_z_slices'
     166              : 
     167              :       INTEGER                                            :: dest, handle, i, ii, iproc, j, k, l, &
     168              :                                                             local_z_dim, loz, m, m2, md2, nproc, &
     169              :                                                             should_warn
     170        33295 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: rcount, rdispl, scount, sdispl, tmp
     171              :       INTEGER, DIMENSION(2)                              :: cart_pos, lox, loy
     172              :       INTEGER, DIMENSION(3)                              :: lb, ub
     173              :       REAL(KIND=dp)                                      :: max_val_low, max_val_up
     174        33295 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rbuf, sbuf
     175              : 
     176        33295 :       CALL timeset(routineN, handle)
     177              : 
     178        33295 :       CPASSERT(ASSOCIATED(wavelet))
     179              : 
     180        33295 :       IF (.NOT. wavelet_axis_is_identity(wavelet)) THEN
     181           36 :          CALL warn_density_edges(density, wavelet, pw_grid)
     182           36 :          CALL cp2k_distribution_to_z_slices_permuted(density, wavelet, pw_grid)
     183           36 :          CALL timestop(handle)
     184           36 :          RETURN
     185              :       END IF
     186              : 
     187        99777 :       nproc = PRODUCT(pw_grid%para%group%num_pe_cart)
     188        33259 :       iproc = pw_grid%para%group%mepos
     189        33259 :       md2 = wavelet%PS_grid(3)
     190        33259 :       m2 = pw_grid%npts(3)
     191       133036 :       lb(:) = pw_grid%bounds_local(1, :)
     192       133036 :       ub(:) = pw_grid%bounds_local(2, :)
     193        33259 :       local_z_dim = MAX((md2/nproc), 1)
     194              : 
     195       199554 :       ALLOCATE (sbuf(PRODUCT(pw_grid%npts_local)))
     196       199554 :       ALLOCATE (rbuf(PRODUCT(wavelet%PS_grid)/nproc))
     197       232813 :       ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), tmp(nproc))
     198              : 
     199    956352052 :       rbuf = 0.0_dp
     200        33259 :       ii = 1
     201       982922 :       DO k = lb(3), ub(3)
     202     34523189 :          DO j = lb(2), ub(2)
     203    968147046 :             DO i = lb(1), ub(1)
     204    933657116 :                sbuf(ii) = density%array(i, j, k)
     205    967197383 :                ii = ii + 1
     206              :             END DO
     207              :          END DO
     208              :       END DO
     209              : 
     210        33259 :       should_warn = 0
     211        33259 :       IF (wavelet%geocode == 'S' .OR. wavelet%geocode == 'F') THEN
     212        15936 :          max_val_low = 0._dp
     213        15936 :          max_val_up = 0._dp
     214     17108942 :          IF (lb(2) == pw_grid%bounds(1, 2)) max_val_low = MAXVAL(ABS(density%array(:, lb(2), :)))
     215     17108942 :          IF (ub(2) == pw_grid%bounds(2, 2)) max_val_up = MAXVAL(ABS(density%array(:, ub(2), :)))
     216        15936 :          IF (max_val_low >= 0.0001_dp) should_warn = 1
     217        15936 :          IF (max_val_up >= 0.0001_dp) should_warn = 1
     218        15936 :          IF (wavelet%geocode == 'F') THEN
     219        15918 :             max_val_low = 0._dp
     220        15918 :             max_val_up = 0._dp
     221     16898574 :             IF (lb(1) == pw_grid%bounds(1, 1)) max_val_low = MAXVAL(ABS(density%array(lb(1), :, :)))
     222     16898574 :             IF (ub(1) == pw_grid%bounds(2, 1)) max_val_up = MAXVAL(ABS(density%array(ub(1), :, :)))
     223        15918 :             IF (max_val_low >= 0.0001_dp) should_warn = 1
     224        15918 :             IF (max_val_up >= 0.0001_dp) should_warn = 1
     225        15918 :             max_val_low = 0._dp
     226        15918 :             max_val_up = 0._dp
     227     17081708 :             IF (lb(3) == pw_grid%bounds(1, 3)) max_val_low = MAXVAL(ABS(density%array(:, :, lb(3))))
     228     17081708 :             IF (ub(3) == pw_grid%bounds(2, 3)) max_val_up = MAXVAL(ABS(density%array(:, :, ub(3))))
     229        15918 :             IF (max_val_low >= 0.0001_dp) should_warn = 1
     230        15918 :             IF (max_val_up >= 0.0001_dp) should_warn = 1
     231              :          END IF
     232              :       END IF
     233              : 
     234        33259 :       CALL pw_grid%para%group%max(should_warn)
     235        33259 :       IF (should_warn > 0 .AND. iproc == 0) THEN
     236         4544 :          CPWARN("Density non-zero on the edges of the unit cell: wrong results in WAVELET solver")
     237              :       END IF
     238        79694 :       DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
     239       126129 :          DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
     240       139305 :             cart_pos = [i, j]
     241        46435 :             CALL pw_grid%para%group%rank_cart(cart_pos, dest)
     242        46435 :             IF ((ub(1) >= lb(1)) .AND. (ub(2) >= lb(2))) THEN
     243        46435 :                IF (dest*local_z_dim <= m2) THEN
     244        46435 :                   IF ((dest + 1)*local_z_dim <= m2) THEN
     245        41822 :                      scount(dest + 1) = ABS((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*local_z_dim)
     246              :                   ELSE
     247         4613 :                      scount(dest + 1) = ABS((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*MOD(m2, local_z_dim))
     248              :                   END IF
     249              :                ELSE
     250            0 :                   scount(dest + 1) = 0
     251              :                END IF
     252              :             ELSE
     253            0 :                scount(dest + 1) = 0
     254              :             END IF
     255        46435 :             lox = get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), i)
     256        46435 :             loy = get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), j)
     257        92870 :             IF ((lox(2) >= lox(1)) .AND. (loy(2) >= loy(1))) THEN
     258        46435 :                IF (iproc*local_z_dim <= m2) THEN
     259        46435 :                   IF ((iproc + 1)*local_z_dim <= m2) THEN
     260        41822 :                      rcount(dest + 1) = ABS((lox(2) - lox(1) + 1)*(loy(2) - loy(1) + 1)*local_z_dim)
     261              :                   ELSE
     262         4613 :                      rcount(dest + 1) = ABS((lox(2) - lox(1) + 1)*(loy(2) - loy(1) + 1)*MOD(m2, local_z_dim))
     263              :                   END IF
     264              :                ELSE
     265            0 :                   rcount(dest + 1) = 0
     266              :                END IF
     267              :             ELSE
     268            0 :                rcount(dest + 1) = 0
     269              :             END IF
     270              : 
     271              :          END DO
     272              :       END DO
     273        33259 :       sdispl(1) = 0
     274        33259 :       rdispl(1) = 0
     275        46435 :       DO i = 2, nproc
     276        13176 :          sdispl(i) = sdispl(i - 1) + scount(i - 1)
     277        46435 :          rdispl(i) = rdispl(i - 1) + rcount(i - 1)
     278              :       END DO
     279   2846327961 :       CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
     280              :       !!!! and now, how to put the right cubes to the right position!!!!!!
     281              : 
     282    980841882 :       wavelet%rho_z_sliced = 0.0_dp
     283              : 
     284        79694 :       DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
     285       126129 :          DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
     286       139305 :             cart_pos = [i, j]
     287        46435 :             CALL pw_grid%para%group%rank_cart(cart_pos, dest)
     288              : 
     289        46435 :             lox = get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), i)
     290        46435 :             loy = get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), j)
     291        92870 :             IF (iproc*local_z_dim <= m2) THEN
     292        46435 :                IF ((iproc + 1)*local_z_dim <= m2) THEN
     293              :                   loz = local_z_dim
     294              :                ELSE
     295         4613 :                   loz = MOD(m2, local_z_dim)
     296              :                END IF
     297        46435 :                ii = 1
     298       996098 :                DO k = 1, loz
     299     34536365 :                   DO l = loy(1), loy(2)
     300    968147046 :                      DO m = lox(1), lox(2)
     301    933657116 :                         wavelet%rho_z_sliced(m, l, k) = rbuf(ii + rdispl(dest + 1))
     302    967197383 :                         ii = ii + 1
     303              :                      END DO
     304              :                   END DO
     305              :                END DO
     306              :             END IF
     307              :          END DO
     308              :       END DO
     309              : 
     310        33259 :       DEALLOCATE (sbuf, rbuf, scount, sdispl, rcount, rdispl, tmp)
     311              : 
     312        33259 :       CALL timestop(handle)
     313              : 
     314        66590 :    END SUBROUTINE cp2k_distribution_to_z_slices
     315              : 
     316              : ! **************************************************************************************************
     317              : !> \brief ...
     318              : !> \param density ...
     319              : !> \param wavelet ...
     320              : !> \param pw_grid ...
     321              : ! **************************************************************************************************
     322        33295 :    SUBROUTINE z_slices_to_cp2k_distribution(density, wavelet, pw_grid)
     323              : 
     324              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: density
     325              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
     326              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     327              : 
     328              :       INTEGER                                            :: dest, i, ii, iproc, j, k, l, &
     329              :                                                             local_z_dim, loz, m, m2, md2, nproc
     330        33295 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: rcount, rdispl, scount, sdispl, tmp
     331              :       INTEGER, DIMENSION(2)                              :: cart_pos, lox, loy, min_x, min_y
     332              :       INTEGER, DIMENSION(3)                              :: lb, ub
     333        33295 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rbuf, sbuf
     334              : 
     335            0 :       CPASSERT(ASSOCIATED(wavelet))
     336              : 
     337        33295 :       IF (.NOT. wavelet_axis_is_identity(wavelet)) THEN
     338           36 :          CALL z_slices_to_cp2k_distribution_permuted(density, wavelet, pw_grid)
     339           36 :          RETURN
     340              :       END IF
     341              : 
     342        99777 :       nproc = PRODUCT(pw_grid%para%group%num_pe_cart)
     343        33259 :       iproc = pw_grid%para%group%mepos
     344        33259 :       md2 = wavelet%PS_grid(3)
     345        33259 :       m2 = pw_grid%npts(3)
     346              : 
     347       133036 :       lb(:) = pw_grid%bounds_local(1, :)
     348       133036 :       ub(:) = pw_grid%bounds_local(2, :)
     349              : 
     350        33259 :       local_z_dim = MAX((md2/nproc), 1)
     351              : 
     352       199554 :       ALLOCATE (rbuf(PRODUCT(pw_grid%npts_local)))
     353       199554 :       ALLOCATE (sbuf(PRODUCT(wavelet%PS_grid)/nproc))
     354       232813 :       ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), tmp(nproc))
     355        33259 :       scount = 0
     356        33259 :       rcount = 0
     357    933690375 :       rbuf = 0.0_dp
     358        33259 :       ii = 1
     359        33259 :       IF (iproc*local_z_dim <= m2) THEN
     360        33259 :          IF ((iproc + 1)*local_z_dim <= m2) THEN
     361              :             loz = local_z_dim
     362              :          ELSE
     363         2816 :             loz = MOD(m2, local_z_dim)
     364              :          END IF
     365              :       ELSE
     366              :          loz = 0
     367              :       END IF
     368              : 
     369        33259 :       min_x = get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), 0)
     370        33259 :       min_y = get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), 0)
     371        79694 :       DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
     372       126129 :          DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
     373       139305 :             cart_pos = [i, j]
     374        46435 :             CALL pw_grid%para%group%rank_cart(cart_pos, dest)
     375        46435 :             IF ((ub(1) >= lb(1)) .AND. (ub(2) >= lb(2))) THEN
     376        46435 :                IF (dest*local_z_dim <= m2) THEN
     377        46435 :                   IF ((dest + 1)*local_z_dim <= m2) THEN
     378        41822 :                      rcount(dest + 1) = ABS((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*local_z_dim)
     379              :                   ELSE
     380         4613 :                      rcount(dest + 1) = ABS((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*MOD(m2, local_z_dim))
     381              :                   END IF
     382              :                ELSE
     383            0 :                   rcount(dest + 1) = 0
     384              :                END IF
     385              :             ELSE
     386            0 :                rcount(dest + 1) = 0
     387              :             END IF
     388        46435 :             lox = get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), i)
     389        46435 :             loy = get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), j)
     390        92870 :             IF ((lox(2) >= lox(1)) .AND. (loy(2) >= loy(1))) THEN
     391        46435 :                scount(dest + 1) = ABS((lox(2) - lox(1) + 1)*(loy(2) - loy(1) + 1)*loz)
     392       996098 :                DO k = lox(1) - min_x(1) + 1, lox(2) - min_x(1) + 1
     393     34536365 :                   DO l = loy(1) - min_y(1) + 1, loy(2) - min_y(1) + 1
     394    968147046 :                      DO m = 1, loz
     395    933657116 :                         sbuf(ii) = wavelet%rho_z_sliced(k, l, m)
     396    967197383 :                         ii = ii + 1
     397              :                      END DO
     398              :                   END DO
     399              :                END DO
     400              :             ELSE
     401            0 :                scount(dest + 1) = 0
     402              :             END IF
     403              :          END DO
     404              :       END DO
     405        33259 :       sdispl(1) = 0
     406        33259 :       rdispl(1) = 0
     407        46435 :       DO i = 2, nproc
     408        13176 :          sdispl(i) = sdispl(i - 1) + scount(i - 1)
     409        46435 :          rdispl(i) = rdispl(i - 1) + rcount(i - 1)
     410              :       END DO
     411   2823666284 :       CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
     412              : 
     413              :       !!!! and now, how to put the right cubes to the right position!!!!!!
     414              : 
     415        79694 :       DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
     416       126129 :          DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
     417       139305 :             cart_pos = [i, j]
     418        46435 :             CALL pw_grid%para%group%rank_cart(cart_pos, dest)
     419        92870 :             IF (dest*local_z_dim <= m2) THEN
     420        46435 :                IF ((dest + 1)*local_z_dim <= m2) THEN
     421              :                   loz = local_z_dim
     422              :                ELSE
     423         4613 :                   loz = MOD(m2, local_z_dim)
     424              :                END IF
     425        46435 :                ii = 1
     426        46435 :                IF (lb(3) + (dest*local_z_dim) <= ub(3)) THEN
     427       996098 :                   DO m = lb(1), ub(1)
     428     34536365 :                      DO l = lb(2), ub(2)
     429    968147046 :                         DO k = lb(3) + (dest*local_z_dim), lb(3) + (dest*local_z_dim) + loz - 1
     430    933657116 :                            density%array(m, l, k) = rbuf(ii + rdispl(dest + 1))
     431    967197383 :                            ii = ii + 1
     432              :                         END DO
     433              :                      END DO
     434              :                   END DO
     435              :                END IF
     436              :             END IF
     437              :          END DO
     438              :       END DO
     439        33259 :       DEALLOCATE (sbuf, rbuf, scount, sdispl, rcount, rdispl, tmp)
     440              : 
     441        66590 :    END SUBROUTINE z_slices_to_cp2k_distribution
     442              : 
     443              : ! **************************************************************************************************
     444              : !> \brief Set the internal Wavelet solver axes for the requested boundary conditions.
     445              : !> \param wavelet ...
     446              : ! **************************************************************************************************
     447          856 :    SUBROUTINE set_wavelet_axis(wavelet)
     448              : 
     449              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
     450              : 
     451         3424 :       wavelet%axis = [1, 2, 3]
     452              : 
     453          856 :       IF (wavelet%method == WAVELET2D) THEN
     454            6 :          SELECT CASE (wavelet%special_dimension)
     455              :          CASE (1)
     456            8 :             wavelet%axis = [2, 1, 3]
     457              :          CASE (2)
     458            8 :             wavelet%axis = [1, 2, 3]
     459              :          CASE (3)
     460            8 :             wavelet%axis = [1, 3, 2]
     461              :          CASE DEFAULT
     462            6 :             CPABORT("Invalid isolated dimension for WAVELET 2D")
     463              :          END SELECT
     464              :       END IF
     465              : 
     466          856 :    END SUBROUTINE set_wavelet_axis
     467              : 
     468              : ! **************************************************************************************************
     469              : !> \brief Return grid sizes and spacings in the internal Wavelet solver axes.
     470              : !> \param wavelet ...
     471              : !> \param pw_grid ...
     472              : !> \param nx ...
     473              : !> \param ny ...
     474              : !> \param nz ...
     475              : !> \param hx ...
     476              : !> \param hy ...
     477              : !> \param hz ...
     478              : ! **************************************************************************************************
     479        34151 :    SUBROUTINE get_wavelet_grid(wavelet, pw_grid, nx, ny, nz, hx, hy, hz)
     480              : 
     481              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
     482              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     483              :       INTEGER, INTENT(OUT)                               :: nx, ny, nz
     484              :       REAL(KIND=dp), INTENT(OUT)                         :: hx, hy, hz
     485              : 
     486        34151 :       nx = pw_grid%npts(wavelet%axis(1))
     487        34151 :       ny = pw_grid%npts(wavelet%axis(2))
     488        34151 :       nz = pw_grid%npts(wavelet%axis(3))
     489        34151 :       hx = pw_grid%dr(wavelet%axis(1))
     490        34151 :       hy = pw_grid%dr(wavelet%axis(2))
     491        34151 :       hz = pw_grid%dr(wavelet%axis(3))
     492              : 
     493        34151 :    END SUBROUTINE get_wavelet_grid
     494              : 
     495              : ! **************************************************************************************************
     496              : !> \brief Return whether CP2K and internal Wavelet solver axes are identical.
     497              : !> \param wavelet ...
     498              : !> \return ...
     499              : ! **************************************************************************************************
     500        66590 :    FUNCTION wavelet_axis_is_identity(wavelet) RESULT(is_identity)
     501              : 
     502              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
     503              :       LOGICAL                                            :: is_identity
     504              : 
     505       266180 :       is_identity = ALL(wavelet%axis == [1, 2, 3])
     506              : 
     507        66590 :    END FUNCTION wavelet_axis_is_identity
     508              : 
     509              : ! **************************************************************************************************
     510              : !> \brief Warn if the density is non-zero at isolated Wavelet cell edges.
     511              : !> \param density ...
     512              : !> \param wavelet ...
     513              : !> \param pw_grid ...
     514              : ! **************************************************************************************************
     515           36 :    SUBROUTINE warn_density_edges(density, wavelet, pw_grid)
     516              : 
     517              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: density
     518              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
     519              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     520              : 
     521              :       INTEGER                                            :: idir, iproc, should_warn
     522              : 
     523           36 :       should_warn = 0
     524           36 :       iproc = pw_grid%para%group%mepos
     525              : 
     526           36 :       IF (wavelet%geocode == 'S') THEN
     527           36 :          CALL update_edge_warning(density, pw_grid, wavelet%special_dimension, should_warn)
     528            0 :       ELSE IF (wavelet%geocode == 'F') THEN
     529            0 :          DO idir = 1, 3
     530            0 :             CALL update_edge_warning(density, pw_grid, idir, should_warn)
     531              :          END DO
     532              :       END IF
     533              : 
     534           36 :       CALL pw_grid%para%group%max(should_warn)
     535           36 :       IF (should_warn > 0 .AND. iproc == 0) THEN
     536            0 :          CPWARN("Density non-zero on the edges of the unit cell: wrong results in WAVELET solver")
     537              :       END IF
     538              : 
     539           36 :    END SUBROUTINE warn_density_edges
     540              : 
     541              : ! **************************************************************************************************
     542              : !> \brief Update the density edge warning for one real-space direction.
     543              : !> \param density ...
     544              : !> \param pw_grid ...
     545              : !> \param direction ...
     546              : !> \param should_warn ...
     547              : ! **************************************************************************************************
     548           36 :    SUBROUTINE update_edge_warning(density, pw_grid, direction, should_warn)
     549              : 
     550              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: density
     551              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     552              :       INTEGER, INTENT(IN)                                :: direction
     553              :       INTEGER, INTENT(INOUT)                             :: should_warn
     554              : 
     555              :       INTEGER, DIMENSION(3)                              :: lb, ub
     556              :       REAL(KIND=dp)                                      :: max_val_low, max_val_up
     557              : 
     558          144 :       lb(:) = pw_grid%bounds_local(1, :)
     559          144 :       ub(:) = pw_grid%bounds_local(2, :)
     560          144 :       IF (.NOT. ALL(ub >= lb)) RETURN
     561              : 
     562           36 :       max_val_low = 0._dp
     563           36 :       max_val_up = 0._dp
     564           54 :       SELECT CASE (direction)
     565              :       CASE (1)
     566        26748 :          IF (lb(1) == pw_grid%bounds(1, 1)) max_val_low = MAXVAL(ABS(density%array(lb(1), :, :)))
     567        26748 :          IF (ub(1) == pw_grid%bounds(2, 1)) max_val_up = MAXVAL(ABS(density%array(ub(1), :, :)))
     568              :       CASE (2)
     569            0 :          IF (lb(2) == pw_grid%bounds(1, 2)) max_val_low = MAXVAL(ABS(density%array(:, lb(2), :)))
     570            0 :          IF (ub(2) == pw_grid%bounds(2, 2)) max_val_up = MAXVAL(ABS(density%array(:, ub(2), :)))
     571              :       CASE (3)
     572        27234 :          IF (lb(3) == pw_grid%bounds(1, 3)) max_val_low = MAXVAL(ABS(density%array(:, :, lb(3))))
     573        27234 :          IF (ub(3) == pw_grid%bounds(2, 3)) max_val_up = MAXVAL(ABS(density%array(:, :, ub(3))))
     574              :       CASE DEFAULT
     575           36 :          CPABORT("Invalid WAVELET isolated dimension")
     576              :       END SELECT
     577              : 
     578           36 :       IF (max_val_low >= 0.0001_dp) should_warn = 1
     579           36 :       IF (max_val_up >= 0.0001_dp) should_warn = 1
     580              : 
     581              :    END SUBROUTINE update_edge_warning
     582              : 
     583              : ! **************************************************************************************************
     584              : !> \brief Convert counts into zero-based displacements for all-to-all communication.
     585              : !> \param counts ...
     586              : !> \param displacements ...
     587              : ! **************************************************************************************************
     588          144 :    SUBROUTINE set_displacements(counts, displacements)
     589              : 
     590              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: counts
     591              :       INTEGER, DIMENSION(:), INTENT(OUT)                 :: displacements
     592              : 
     593              :       INTEGER                                            :: i
     594              : 
     595          144 :       displacements(1) = 0
     596          288 :       DO i = 2, SIZE(counts)
     597          288 :          displacements(i) = displacements(i - 1) + counts(i - 1)
     598              :       END DO
     599              : 
     600          144 :    END SUBROUTINE set_displacements
     601              : 
     602              : ! **************************************************************************************************
     603              : !> \brief Return the distributed grid owner of a compact one-based grid index.
     604              : !> \param index ...
     605              : !> \param npts ...
     606              : !> \param nparts ...
     607              : !> \return ...
     608              : ! **************************************************************************************************
     609     11337408 :    FUNCTION grid_owner(index, npts, nparts) RESULT(owner)
     610              : 
     611              :       INTEGER, INTENT(IN)                                :: index, npts, nparts
     612              :       INTEGER                                            :: owner
     613              : 
     614              :       INTEGER                                            :: ipart
     615              :       INTEGER, DIMENSION(2)                              :: limits
     616              : 
     617     14171760 :       DO ipart = 0, nparts - 1
     618     14171760 :          limits = get_limit(npts, nparts, ipart)
     619     14171760 :          IF (index >= limits(1) .AND. index <= limits(2)) THEN
     620     11337408 :             owner = ipart
     621              :             RETURN
     622              :          END IF
     623              :       END DO
     624            0 :       CPABORT("Grid index outside distributed bounds")
     625              : 
     626            0 :    END FUNCTION grid_owner
     627              : 
     628              : ! **************************************************************************************************
     629              : !> \brief Return the Wavelet z-slice owner of a compact one-based grid index.
     630              : !> \param index ...
     631              : !> \param local_z_dim ...
     632              : !> \param nproc ...
     633              : !> \return ...
     634              : ! **************************************************************************************************
     635      5668704 :    FUNCTION z_slice_owner(index, local_z_dim, nproc) RESULT(owner)
     636              : 
     637              :       INTEGER, INTENT(IN)                                :: index, local_z_dim, nproc
     638              :       INTEGER                                            :: owner
     639              : 
     640      5668704 :       owner = MIN((index - 1)/local_z_dim, nproc - 1)
     641              : 
     642      5668704 :    END FUNCTION z_slice_owner
     643              : 
     644              : ! **************************************************************************************************
     645              : !> \brief Return the CP2K real-space rank owning a real-space x/y grid point.
     646              : !> \param ix ...
     647              : !> \param iy ...
     648              : !> \param pw_grid ...
     649              : !> \return ...
     650              : ! **************************************************************************************************
     651      5668704 :    FUNCTION cp2k_rank_owner(ix, iy, pw_grid) RESULT(rank)
     652              : 
     653              :       INTEGER, INTENT(IN)                                :: ix, iy
     654              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     655              :       INTEGER                                            :: rank
     656              : 
     657              :       INTEGER, DIMENSION(2)                              :: cart_pos
     658              : 
     659              :       cart_pos(1) = grid_owner(ix - pw_grid%bounds(1, 1) + 1, pw_grid%npts(1), &
     660      5668704 :                                pw_grid%para%group%num_pe_cart(1))
     661              :       cart_pos(2) = grid_owner(iy - pw_grid%bounds(1, 2) + 1, pw_grid%npts(2), &
     662      5668704 :                                pw_grid%para%group%num_pe_cart(2))
     663      5668704 :       CALL pw_grid%para%group%rank_cart(cart_pos, rank)
     664              : 
     665      5668704 :    END FUNCTION cp2k_rank_owner
     666              : 
     667              : ! **************************************************************************************************
     668              : !> \brief Transfer a CP2K real-space grid into a permuted Wavelet z-sliced layout.
     669              : !> \param density ...
     670              : !> \param wavelet ...
     671              : !> \param pw_grid ...
     672              : ! **************************************************************************************************
     673           36 :    SUBROUTINE cp2k_distribution_to_z_slices_permuted(density, wavelet, pw_grid)
     674              : 
     675              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: density
     676              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
     677              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     678              : 
     679              :       INTEGER                                            :: dest, i, idir, ii, j, k, local_z_dim, &
     680              :                                                             md2, nproc, nrecv, nsend
     681              :       INTEGER, ALLOCATABLE, DIMENSION(:) :: coord_rbuf, coord_rcount, coord_rdispl, coord_sbuf, &
     682           36 :          coord_scount, coord_sdispl, rcount, rdispl, scount, sdispl, send_pos
     683              :       INTEGER, DIMENSION(3)                              :: lb, q, u, ub
     684              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: rbuf, sbuf
     685              : 
     686          108 :       nproc = PRODUCT(pw_grid%para%group%num_pe_cart)
     687           36 :       md2 = wavelet%PS_grid(3)
     688           36 :       local_z_dim = MAX(md2/nproc, 1)
     689          144 :       lb(:) = pw_grid%bounds_local(1, :)
     690          144 :       ub(:) = pw_grid%bounds_local(2, :)
     691              : 
     692          252 :       ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), send_pos(nproc))
     693           36 :       scount = 0
     694         1980 :       DO k = lb(3), ub(3)
     695       106956 :          DO j = lb(2), ub(2)
     696      2941272 :             DO i = lb(1), ub(1)
     697     11337408 :                u = [i, j, k]
     698     11337408 :                DO idir = 1, 3
     699     11337408 :                   q(idir) = u(wavelet%axis(idir)) - pw_grid%bounds(1, wavelet%axis(idir)) + 1
     700              :                END DO
     701      2834352 :                dest = z_slice_owner(q(3), local_z_dim, nproc)
     702      2939328 :                scount(dest + 1) = scount(dest + 1) + 1
     703              :             END DO
     704              :          END DO
     705              :       END DO
     706              : 
     707           36 :       CALL pw_grid%para%group%alltoall(scount, rcount, 1)
     708           36 :       CALL set_displacements(scount, sdispl)
     709           36 :       CALL set_displacements(rcount, rdispl)
     710          108 :       nsend = SUM(scount)
     711          108 :       nrecv = SUM(rcount)
     712              : 
     713          180 :       ALLOCATE (sbuf(MAX(nsend, 1)), rbuf(MAX(nrecv, 1)))
     714          180 :       ALLOCATE (coord_sbuf(MAX(3*nsend, 1)), coord_rbuf(MAX(3*nrecv, 1)))
     715          180 :       ALLOCATE (coord_scount(nproc), coord_sdispl(nproc), coord_rcount(nproc), coord_rdispl(nproc))
     716          108 :       coord_scount(:) = 3*scount(:)
     717          108 :       coord_rcount(:) = 3*rcount(:)
     718          108 :       coord_sdispl(:) = 3*sdispl(:)
     719          108 :       coord_rdispl(:) = 3*rdispl(:)
     720          108 :       send_pos(:) = sdispl(:) + 1
     721              : 
     722         1980 :       DO k = lb(3), ub(3)
     723       106956 :          DO j = lb(2), ub(2)
     724      2941272 :             DO i = lb(1), ub(1)
     725     11337408 :                u = [i, j, k]
     726     11337408 :                DO idir = 1, 3
     727     11337408 :                   q(idir) = u(wavelet%axis(idir)) - pw_grid%bounds(1, wavelet%axis(idir)) + 1
     728              :                END DO
     729      2834352 :                dest = z_slice_owner(q(3), local_z_dim, nproc)
     730      2834352 :                ii = send_pos(dest + 1)
     731      2834352 :                sbuf(ii) = density%array(i, j, k)
     732      2834352 :                coord_sbuf(3*ii - 2) = q(1)
     733      2834352 :                coord_sbuf(3*ii - 1) = q(2)
     734      2834352 :                coord_sbuf(3*ii) = q(3)
     735      2939328 :                send_pos(dest + 1) = ii + 1
     736              :             END DO
     737              :          END DO
     738              :       END DO
     739              : 
     740           36 :       CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
     741              :       CALL pw_grid%para%group%alltoall(coord_sbuf, coord_scount, coord_sdispl, &
     742           36 :                                        coord_rbuf, coord_rcount, coord_rdispl)
     743              : 
     744      2887848 :       wavelet%rho_z_sliced = 0.0_dp
     745      2834388 :       DO ii = 1, nrecv
     746      2834352 :          q(1) = coord_rbuf(3*ii - 2)
     747      2834352 :          q(2) = coord_rbuf(3*ii - 1)
     748      2834352 :          q(3) = coord_rbuf(3*ii)
     749      2834388 :          wavelet%rho_z_sliced(q(1), q(2), q(3) - pw_grid%para%group%mepos*local_z_dim) = rbuf(ii)
     750              :       END DO
     751              : 
     752            0 :       DEALLOCATE (sbuf, rbuf, coord_sbuf, coord_rbuf, coord_scount, coord_sdispl, coord_rcount, &
     753           36 :                   coord_rdispl, scount, sdispl, rcount, rdispl, send_pos)
     754              : 
     755           36 :    END SUBROUTINE cp2k_distribution_to_z_slices_permuted
     756              : 
     757              : ! **************************************************************************************************
     758              : !> \brief Transfer a permuted Wavelet z-sliced layout back to a CP2K real-space grid.
     759              : !> \param density ...
     760              : !> \param wavelet ...
     761              : !> \param pw_grid ...
     762              : ! **************************************************************************************************
     763           36 :    SUBROUTINE z_slices_to_cp2k_distribution_permuted(density, wavelet, pw_grid)
     764              : 
     765              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: density
     766              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
     767              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     768              : 
     769              :       INTEGER                                            :: dest, i, idir, ii, j, k, local_z, &
     770              :                                                             local_z_dim, md2, n1, n2, n3, nproc, &
     771              :                                                             nrecv, nsend, z_end, z_start
     772           36 :       INTEGER, ALLOCATABLE, DIMENSION(:) :: coord_rbuf, coord_rcount, coord_rdispl, coord_sbuf, &
     773           36 :          coord_scount, coord_sdispl, rcount, rdispl, scount, sdispl, send_pos
     774              :       INTEGER, DIMENSION(3)                              :: lb, q, u, ub
     775           36 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: rbuf, sbuf
     776              : 
     777          108 :       nproc = PRODUCT(pw_grid%para%group%num_pe_cart)
     778           36 :       md2 = wavelet%PS_grid(3)
     779           36 :       local_z_dim = MAX(md2/nproc, 1)
     780           36 :       n1 = pw_grid%npts(wavelet%axis(1))
     781           36 :       n2 = pw_grid%npts(wavelet%axis(2))
     782           36 :       n3 = pw_grid%npts(wavelet%axis(3))
     783           36 :       z_start = pw_grid%para%group%mepos*local_z_dim + 1
     784           36 :       z_end = MIN((pw_grid%para%group%mepos + 1)*local_z_dim, n3)
     785          144 :       lb(:) = pw_grid%bounds_local(1, :)
     786          144 :       ub(:) = pw_grid%bounds_local(2, :)
     787              : 
     788          252 :       ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), send_pos(nproc))
     789           36 :       scount = 0
     790         1008 :       DO k = z_start, z_end
     791        53496 :          DO j = 1, n2
     792      2887812 :             DO i = 1, n1
     793     11337408 :                q = [i, j, k]
     794     11337408 :                DO idir = 1, 3
     795     11337408 :                   u(wavelet%axis(idir)) = q(idir) + pw_grid%bounds(1, wavelet%axis(idir)) - 1
     796              :                END DO
     797      2834352 :                dest = cp2k_rank_owner(u(1), u(2), pw_grid)
     798      2886840 :                scount(dest + 1) = scount(dest + 1) + 1
     799              :             END DO
     800              :          END DO
     801              :       END DO
     802              : 
     803           36 :       CALL pw_grid%para%group%alltoall(scount, rcount, 1)
     804           36 :       CALL set_displacements(scount, sdispl)
     805           36 :       CALL set_displacements(rcount, rdispl)
     806          108 :       nsend = SUM(scount)
     807          108 :       nrecv = SUM(rcount)
     808              : 
     809          180 :       ALLOCATE (sbuf(MAX(nsend, 1)), rbuf(MAX(nrecv, 1)))
     810          180 :       ALLOCATE (coord_sbuf(MAX(3*nsend, 1)), coord_rbuf(MAX(3*nrecv, 1)))
     811          180 :       ALLOCATE (coord_scount(nproc), coord_sdispl(nproc), coord_rcount(nproc), coord_rdispl(nproc))
     812          108 :       coord_scount(:) = 3*scount(:)
     813          108 :       coord_rcount(:) = 3*rcount(:)
     814          108 :       coord_sdispl(:) = 3*sdispl(:)
     815          108 :       coord_rdispl(:) = 3*rdispl(:)
     816          108 :       send_pos(:) = sdispl(:) + 1
     817              : 
     818         1008 :       DO k = z_start, z_end
     819        53496 :          DO j = 1, n2
     820      2887812 :             DO i = 1, n1
     821     11337408 :                q = [i, j, k]
     822     11337408 :                DO idir = 1, 3
     823     11337408 :                   u(wavelet%axis(idir)) = q(idir) + pw_grid%bounds(1, wavelet%axis(idir)) - 1
     824              :                END DO
     825      2834352 :                dest = cp2k_rank_owner(u(1), u(2), pw_grid)
     826      2834352 :                ii = send_pos(dest + 1)
     827      2834352 :                local_z = k - pw_grid%para%group%mepos*local_z_dim
     828      2834352 :                sbuf(ii) = wavelet%rho_z_sliced(i, j, local_z)
     829      2834352 :                coord_sbuf(3*ii - 2) = u(1)
     830      2834352 :                coord_sbuf(3*ii - 1) = u(2)
     831      2834352 :                coord_sbuf(3*ii) = u(3)
     832      2886840 :                send_pos(dest + 1) = ii + 1
     833              :             END DO
     834              :          END DO
     835              :       END DO
     836              : 
     837           36 :       CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
     838              :       CALL pw_grid%para%group%alltoall(coord_sbuf, coord_scount, coord_sdispl, &
     839           36 :                                        coord_rbuf, coord_rcount, coord_rdispl)
     840              : 
     841      2834388 :       DO ii = 1, nrecv
     842      2834352 :          u(1) = coord_rbuf(3*ii - 2)
     843      2834352 :          u(2) = coord_rbuf(3*ii - 1)
     844      2834352 :          u(3) = coord_rbuf(3*ii)
     845              :          IF (u(1) >= lb(1) .AND. u(1) <= ub(1) .AND. u(2) >= lb(2) .AND. u(2) <= ub(2) .AND. &
     846      2834388 :              u(3) >= lb(3) .AND. u(3) <= ub(3)) THEN
     847      2834352 :             density%array(u(1), u(2), u(3)) = rbuf(ii)
     848              :          END IF
     849              :       END DO
     850              : 
     851            0 :       DEALLOCATE (sbuf, rbuf, coord_sbuf, coord_rbuf, coord_scount, coord_sdispl, coord_rcount, &
     852           36 :                   coord_rdispl, scount, sdispl, rcount, rdispl, send_pos)
     853              : 
     854           36 :    END SUBROUTINE z_slices_to_cp2k_distribution_permuted
     855              : 
     856              : ! **************************************************************************************************
     857              : !> \brief ...
     858              : !> \param wavelet ...
     859              : !> \param pw_grid ...
     860              : ! **************************************************************************************************
     861        66590 :    SUBROUTINE ps_wavelet_solve(wavelet, pw_grid)
     862              : 
     863              :       TYPE(ps_wavelet_type), POINTER                     :: wavelet
     864              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
     865              : 
     866              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'ps_wavelet_solve'
     867              : 
     868              :       CHARACTER(LEN=1)                                   :: geocode
     869              :       INTEGER                                            :: handle, iproc, nproc, nx, ny, nz
     870              :       REAL(KIND=dp)                                      :: hx, hy, hz
     871              : 
     872        33295 :       CALL timeset(routineN, handle)
     873        99885 :       nproc = PRODUCT(pw_grid%para%group%num_pe_cart)
     874        33295 :       iproc = pw_grid%para%group%mepos
     875        33295 :       geocode = wavelet%geocode
     876        33295 :       CALL get_wavelet_grid(wavelet, pw_grid, nx, ny, nz, hx, hy, hz)
     877              : 
     878              :       CALL PSolver(geocode, iproc, nproc, nx, ny, nz, hx, hy, hz, &
     879        33295 :                    wavelet%rho_z_sliced, wavelet%karray, pw_grid)
     880        33295 :       CALL timestop(handle)
     881        33295 :    END SUBROUTINE ps_wavelet_solve
     882              : 
     883              : END MODULE ps_wavelet_methods
        

Generated by: LCOV version 2.0-1