LCOV - code coverage report
Current view: top level - src/pw - ps_wavelet_scaling_function.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:2c0d679) Lines: 62.4 % 109 68
Test Date: 2026-09-25 00:58:37 Functions: 71.4 % 7 5

            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 Creates the wavelet kernel for the wavelet based poisson solver.
      10              : !> \author Florian Schiffmann (09.2007,fschiff)
      11              : ! **************************************************************************************************
      12              : MODULE ps_wavelet_scaling_function
      13              :    USE kinds,                           ONLY: dp
      14              :    USE lazy,                            ONLY: lazy_arrays
      15              : #include "../base/base_uses.f90"
      16              : 
      17              :    IMPLICIT NONE
      18              : 
      19              :    PRIVATE
      20              : 
      21              :    PUBLIC :: scaling_function, &
      22              :              scf_recursion
      23              : 
      24              : CONTAINS
      25              : 
      26              : ! **************************************************************************************************
      27              : !> \brief Calculate the values of a scaling function in real uniform grid
      28              : !> \param itype ...
      29              : !> \param nd ...
      30              : !> \param nrange ...
      31              : !> \param a ...
      32              : !> \param x ...
      33              : ! **************************************************************************************************
      34          600 :    SUBROUTINE scaling_function(itype, nd, nrange, a, x)
      35              : 
      36              :       !Type of interpolating functions
      37              :       INTEGER, INTENT(in)                                :: itype, nd
      38              :       INTEGER, INTENT(out)                               :: nrange
      39              :       REAL(KIND=dp), DIMENSION(0:nd), INTENT(out)        :: a, x
      40              : 
      41              :       INTEGER                                            :: i, i_all, m, ni, nt
      42          600 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: y
      43          600 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cg, cgt, ch, cht
      44              : 
      45              : !Number of points: must be 2**nex
      46              : 
      47      3039920 :       a = 0.0_dp
      48      3039920 :       x = 0.0_dp
      49          600 :       m = itype + 2
      50          600 :       CALL lazy_arrays(itype, m, ch, cg, cgt, cht)
      51              : 
      52          600 :       ni = 2*itype
      53          600 :       nrange = ni
      54         1800 :       ALLOCATE (y(0:nd), stat=i_all)
      55          600 :       IF (i_all /= 0) THEN
      56            0 :          CPABORT("Scaling_function: problem of memory allocation")
      57              :       END IF
      58              : 
      59              :       ! plot scaling function
      60          600 :       CALL zero(nd + 1, x)
      61          600 :       CALL zero(nd + 1, y)
      62          600 :       nt = ni
      63          600 :       x(nt/2 - 1) = 1._dp
      64              :       loop1: DO
      65         3600 :          nt = 2*nt
      66              : 
      67         3600 :          CALL back_trans(nd, nt, x, y, m, ch, cg)
      68         3600 :          CALL dcopy(nt, y, 1, x, 1)
      69         3600 :          IF (nt == nd) THEN
      70              :             EXIT loop1
      71              :          END IF
      72              :       END DO loop1
      73              : 
      74      3039920 :       DO i = 0, nd
      75      3039920 :          a(i) = 1._dp*i*ni/nd - (.5_dp*ni - 1._dp)
      76              :       END DO
      77          600 :       DEALLOCATE (ch, cg, cgt, cht)
      78          600 :       DEALLOCATE (y)
      79          600 :    END SUBROUTINE scaling_function
      80              : 
      81              : ! **************************************************************************************************
      82              : !> \brief Calculate the values of the wavelet function in a real uniform mesh.
      83              : !> \param itype ...
      84              : !> \param nd ...
      85              : !> \param a ...
      86              : !> \param x ...
      87              : ! **************************************************************************************************
      88            0 :    SUBROUTINE wavelet_function(itype, nd, a, x)
      89              : 
      90              :       !Type of the interpolating scaling function
      91              :       INTEGER, INTENT(in)                                :: itype, nd
      92              :       REAL(KIND=dp), DIMENSION(0:nd), INTENT(out)        :: a, x
      93              : 
      94              :       INTEGER                                            :: i, i_all, m, ni, nt
      95            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: y
      96            0 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cg, cgt, ch, cht
      97              : 
      98              : !must be 2**nex
      99              : 
     100            0 :       a = 0.0_dp
     101            0 :       x = 0.0_dp
     102            0 :       m = itype + 2
     103            0 :       ni = 2*itype
     104            0 :       CALL lazy_arrays(itype, m, ch, cg, cgt, cht)
     105            0 :       ALLOCATE (y(0:nd), stat=i_all)
     106            0 :       IF (i_all /= 0) THEN
     107            0 :          CPABORT("Wavelet_function: problem of memory allocation")
     108              :       END IF
     109              : 
     110              :       ! plot wavelet
     111            0 :       CALL zero(nd + 1, x)
     112            0 :       CALL zero(nd + 1, y)
     113            0 :       nt = ni
     114            0 :       x(nt + nt/2 - 1) = 1._dp
     115              :       loop3: DO
     116            0 :          nt = 2*nt
     117              :          !WRITE(*,*) 'nd,nt',nd,nt
     118            0 :          CALL back_trans(nd, nt, x, y, m, ch, cg)
     119            0 :          CALL dcopy(nd, y, 1, x, 1)
     120            0 :          IF (nt == nd) THEN
     121              :             EXIT loop3
     122              :          END IF
     123              :       END DO loop3
     124              : 
     125              :       !open (unit=1,file='wavelet',status='unknown')
     126            0 :       DO i = 0, nd - 1
     127            0 :          a(i) = 1._dp*i*ni/nd - (.5_dp*ni - .5_dp)
     128              :       END DO
     129            0 :       DEALLOCATE (ch, cg, cgt, cht)
     130            0 :       DEALLOCATE (y)
     131              : 
     132            0 :    END SUBROUTINE wavelet_function
     133              : 
     134              : ! **************************************************************************************************
     135              : !> \brief Do iterations to go from p0gauss to pgauss
     136              : !>    order interpolating scaling function
     137              : !> \param itype ...
     138              : !> \param n_iter ...
     139              : !> \param n_range ...
     140              : !> \param kernel_scf ...
     141              : !> \param kern_1_scf ...
     142              : ! **************************************************************************************************
     143        55215 :    PURE SUBROUTINE scf_recursion(itype, n_iter, n_range, kernel_scf, kern_1_scf)
     144              :       INTEGER, INTENT(in)                                :: itype, n_iter, n_range
     145              :       REAL(KIND=dp), INTENT(inout)                       :: kernel_scf(-n_range:n_range)
     146              :       REAL(KIND=dp), INTENT(out)                         :: kern_1_scf(-n_range:n_range)
     147              : 
     148              :       INTEGER                                            :: m
     149        55215 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cg, cgt, ch, cht
     150              : 
     151     10106380 :       kern_1_scf = 0.0_dp
     152        55215 :       m = itype + 2
     153        55215 :       CALL lazy_arrays(itype, m, ch, cg, cgt, cht)
     154        55215 :       CALL scf_recurs(n_iter, n_range, kernel_scf, kern_1_scf, m, ch)
     155        55215 :       DEALLOCATE (ch, cg, cgt, cht)
     156              : 
     157        55215 :    END SUBROUTINE scf_recursion
     158              : 
     159              : ! **************************************************************************************************
     160              : !> \brief Set to zero an array x(n)
     161              : !> \param n ...
     162              : !> \param x ...
     163              : ! **************************************************************************************************
     164         1200 :    PURE SUBROUTINE zero(n, x)
     165              :       INTEGER, INTENT(in)                                :: n
     166              :       REAL(KIND=dp), INTENT(out)                         :: x(n)
     167              : 
     168              :       INTEGER                                            :: i
     169              : 
     170      6079840 :       DO i = 1, n
     171      6079840 :          x(i) = 0._dp
     172              :       END DO
     173         1200 :    END SUBROUTINE zero
     174              : 
     175              : ! **************************************************************************************************
     176              : !> \brief forward wavelet transform
     177              : !>    nd: length of data set
     178              : !>    nt length of data in data set to be transformed
     179              : !>    m filter length (m has to be even!)
     180              : !>    x input data, y output data
     181              : !> \param nd ...
     182              : !> \param nt ...
     183              : !> \param x ...
     184              : !> \param y ...
     185              : !> \param m ...
     186              : !> \param cgt ...
     187              : !> \param cht ...
     188              : ! **************************************************************************************************
     189            0 :    PURE SUBROUTINE for_trans(nd, nt, x, y, m, cgt, cht)
     190              :       INTEGER, INTENT(in)                                :: nd, nt
     191              :       REAL(KIND=dp), INTENT(in)                          :: x(0:nd - 1)
     192              :       REAL(KIND=dp), INTENT(out)                         :: y(0:nd - 1)
     193              :       INTEGER, INTENT(in)                                :: m
     194              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cgt, cht
     195              : 
     196              :       INTEGER                                            :: i, ind, j
     197              : 
     198            0 :       y = 0.0_dp
     199            0 :       DO i = 0, nt/2 - 1
     200            0 :          y(i) = 0._dp
     201            0 :          y(nt/2 + i) = 0._dp
     202              : 
     203            0 :          DO j = -m + 1, m
     204              : 
     205              :             ! periodically wrap index if necessary
     206            0 :             ind = j + 2*i
     207              :             loop99: DO
     208            0 :                IF (ind < 0) THEN
     209            0 :                   ind = ind + nt
     210            0 :                   CYCLE loop99
     211              :                END IF
     212            0 :                IF (ind >= nt) THEN
     213            0 :                   ind = ind - nt
     214            0 :                   CYCLE loop99
     215              :                END IF
     216              :                EXIT loop99
     217              :             END DO loop99
     218              : 
     219            0 :             y(i) = y(i) + cht(j)*x(ind)
     220            0 :             y(nt/2 + i) = y(nt/2 + i) + cgt(j)*x(ind)
     221              :          END DO
     222              : 
     223              :       END DO
     224              : 
     225            0 :    END SUBROUTINE for_trans
     226              : 
     227              : ! **************************************************************************************************
     228              : !> \brief ...
     229              : !> \param nd ...
     230              : !> \param nt ...
     231              : !> \param x ...
     232              : !> \param y ...
     233              : !> \param m ...
     234              : !> \param ch ...
     235              : !> \param cg ...
     236              : ! **************************************************************************************************
     237         3600 :    PURE SUBROUTINE back_trans(nd, nt, x, y, m, ch, cg)
     238              :       ! backward wavelet transform
     239              :       ! nd: length of data set
     240              :       ! nt length of data in data set to be transformed
     241              :       ! m filter length (m has to be even!)
     242              :       ! x input data, y output data
     243              :       INTEGER, INTENT(in)                                :: nd, nt
     244              :       REAL(KIND=dp), INTENT(in)                          :: x(0:nd - 1)
     245              :       REAL(KIND=dp), INTENT(out)                         :: y(0:nd - 1)
     246              :       INTEGER, INTENT(in)                                :: m
     247              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: ch, cg
     248              : 
     249              :       INTEGER                                            :: i, ind, j
     250              : 
     251     18235920 :       y = 0.0_dp
     252              : 
     253      2994840 :       DO i = 0, nt/2 - 1
     254      2991240 :          y(2*i + 0) = 0._dp
     255      2991240 :          y(2*i + 1) = 0._dp
     256              : 
     257    128168280 :          DO j = -m/2, m/2 - 1
     258              : 
     259              :             ! periodically wrap index if necessary
     260    125173440 :             ind = i - j
     261              :             loop99: DO
     262    126738420 :                IF (ind < 0) THEN
     263       745080 :                   ind = ind + nt/2
     264       745080 :                   CYCLE loop99
     265              :                END IF
     266    125993340 :                IF (ind >= nt/2) THEN
     267       819900 :                   ind = ind - nt/2
     268       819900 :                   CYCLE loop99
     269              :                END IF
     270              :                EXIT loop99
     271              :             END DO loop99
     272              : 
     273    125173440 :             y(2*i + 0) = y(2*i + 0) + ch(2*j - 0)*x(ind) + cg(2*j - 0)*x(ind + nt/2)
     274    128164680 :             y(2*i + 1) = y(2*i + 1) + ch(2*j + 1)*x(ind) + cg(2*j + 1)*x(ind + nt/2)
     275              :          END DO
     276              : 
     277              :       END DO
     278              : 
     279         3600 :    END SUBROUTINE back_trans
     280              : 
     281              : ! **************************************************************************************************
     282              : !> \brief Do iterations to go from p0gauss to pgauss
     283              : !>    8th-order interpolating scaling function
     284              : !> \param n_iter ...
     285              : !> \param n_range ...
     286              : !> \param kernel_scf ...
     287              : !> \param kern_1_scf ...
     288              : !> \param m ...
     289              : !> \param ch ...
     290              : ! **************************************************************************************************
     291        55215 :    PURE SUBROUTINE scf_recurs(n_iter, n_range, kernel_scf, kern_1_scf, m, ch)
     292              :       INTEGER, INTENT(in)                                :: n_iter, n_range
     293              :       REAL(KIND=dp), INTENT(inout)                       :: kernel_scf(-n_range:n_range)
     294              :       REAL(KIND=dp), INTENT(out)                         :: kern_1_scf(-n_range:n_range)
     295              :       INTEGER, INTENT(in)                                :: m
     296              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: ch
     297              : 
     298              :       INTEGER                                            :: i, i_iter, ind, j
     299              :       REAL(KIND=dp)                                      :: kern, kern_tot
     300              : 
     301     10106380 :       kern_1_scf = 0.0_dp
     302              :       !Start the iteration to go from p0gauss to pgauss
     303       614391 :       loop_iter_scf: DO i_iter = 1, n_iter
     304     95428584 :          kern_1_scf(:) = kernel_scf(:)
     305     95428584 :          kernel_scf(:) = 0._dp
     306     22345873 :          loop_iter_i: DO i = 0, n_range
     307     22290658 :             kern_tot = 0._dp
     308   1871962508 :             DO j = -m, m
     309   1849671850 :                ind = 2*i - j
     310   1849671850 :                IF (ABS(ind) > n_range) THEN
     311              :                   kern = 0._dp
     312              :                ELSE
     313   1636785514 :                   kern = kern_1_scf(ind)
     314              :                END IF
     315   1871962508 :                kern_tot = kern_tot + ch(j)*kern
     316              :             END DO
     317     22290658 :             IF (kern_tot == 0._dp) THEN
     318              :                !zero after (be sure because strictly == 0._dp)
     319              :                EXIT loop_iter_i
     320              :             ELSE
     321     21731482 :                kernel_scf(i) = 0.5_dp*kern_tot
     322     21731482 :                kernel_scf(-i) = kernel_scf(i)
     323              :             END IF
     324              :          END DO loop_iter_i
     325              :       END DO loop_iter_scf
     326        55215 :    END SUBROUTINE scf_recurs
     327              : 
     328              : END MODULE ps_wavelet_scaling_function
        

Generated by: LCOV version 2.0-1