LCOV - code coverage report
Current view: top level - src/pw - ps_wavelet_scaling_function.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:c24029e) Lines: 52.3 % 130 68
Test Date: 2026-07-04 06:36:57 Functions: 62.5 % 8 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          530 :    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          530 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: y
      43          530 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cg, cgt, ch, cht
      44              : 
      45              : !Number of points: must be 2**nex
      46              : 
      47      2681380 :       a = 0.0_dp
      48      2681380 :       x = 0.0_dp
      49          530 :       m = itype + 2
      50          530 :       CALL lazy_arrays(itype, m, ch, cg, cgt, cht)
      51              : 
      52          530 :       ni = 2*itype
      53          530 :       nrange = ni
      54         1590 :       ALLOCATE (y(0:nd), stat=i_all)
      55          530 :       IF (i_all /= 0) THEN
      56            0 :          CPABORT("Scaling_function: problem of memory allocation")
      57              :       END IF
      58              : 
      59              :       ! plot scaling function
      60          530 :       CALL zero(nd + 1, x)
      61          530 :       CALL zero(nd + 1, y)
      62          530 :       nt = ni
      63          530 :       x(nt/2 - 1) = 1._dp
      64              :       loop1: DO
      65         3180 :          nt = 2*nt
      66              : 
      67         3180 :          CALL back_trans(nd, nt, x, y, m, ch, cg)
      68         3180 :          CALL dcopy(nt, y, 1, x, 1)
      69         3180 :          IF (nt == nd) THEN
      70              :             EXIT loop1
      71              :          END IF
      72              :       END DO loop1
      73              : 
      74              :       !open (unit=1,file='scfunction',status='unknown')
      75      2681380 :       DO i = 0, nd
      76      2681380 :          a(i) = 1._dp*i*ni/nd - (.5_dp*ni - 1._dp)
      77              :          !write(1,*) 1._dp*i*ni/nd-(.5_dp*ni-1._dp),x(i)
      78              :       END DO
      79              :       !close(1)
      80          530 :       DEALLOCATE (ch, cg, cgt, cht)
      81          530 :       DEALLOCATE (y)
      82          530 :    END SUBROUTINE scaling_function
      83              : 
      84              : ! **************************************************************************************************
      85              : !> \brief Calculate the values of the wavelet function in a real uniform mesh.
      86              : !> \param itype ...
      87              : !> \param nd ...
      88              : !> \param a ...
      89              : !> \param x ...
      90              : ! **************************************************************************************************
      91            0 :    SUBROUTINE wavelet_function(itype, nd, a, x)
      92              : 
      93              :       !Type of the interpolating scaling function
      94              :       INTEGER, INTENT(in)                                :: itype, nd
      95              :       REAL(KIND=dp), DIMENSION(0:nd), INTENT(out)        :: a, x
      96              : 
      97              :       INTEGER                                            :: i, i_all, m, ni, nt
      98            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: y
      99            0 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cg, cgt, ch, cht
     100              : 
     101              : !must be 2**nex
     102              : 
     103            0 :       a = 0.0_dp
     104            0 :       x = 0.0_dp
     105            0 :       m = itype + 2
     106            0 :       ni = 2*itype
     107            0 :       CALL lazy_arrays(itype, m, ch, cg, cgt, cht)
     108            0 :       ALLOCATE (y(0:nd), stat=i_all)
     109            0 :       IF (i_all /= 0) THEN
     110            0 :          CPABORT("Wavelet_function: problem of memory allocation")
     111              :       END IF
     112              : 
     113              :       ! plot wavelet
     114            0 :       CALL zero(nd + 1, x)
     115            0 :       CALL zero(nd + 1, y)
     116            0 :       nt = ni
     117            0 :       x(nt + nt/2 - 1) = 1._dp
     118              :       loop3: DO
     119            0 :          nt = 2*nt
     120              :          !WRITE(*,*) 'nd,nt',nd,nt
     121            0 :          CALL back_trans(nd, nt, x, y, m, ch, cg)
     122            0 :          CALL dcopy(nd, y, 1, x, 1)
     123            0 :          IF (nt == nd) THEN
     124              :             EXIT loop3
     125              :          END IF
     126              :       END DO loop3
     127              : 
     128              :       !open (unit=1,file='wavelet',status='unknown')
     129            0 :       DO i = 0, nd - 1
     130            0 :          a(i) = 1._dp*i*ni/nd - (.5_dp*ni - .5_dp)
     131              :          !write(1,*) 1._dp*i*ni/nd-(.5_dp*ni-.5_dp),x(i)
     132              :       END DO
     133              :       !close(1)
     134            0 :       DEALLOCATE (ch, cg, cgt, cht)
     135            0 :       DEALLOCATE (y)
     136              : 
     137            0 :    END SUBROUTINE wavelet_function
     138              : 
     139              : ! **************************************************************************************************
     140              : !> \brief Do iterations to go from p0gauss to pgauss
     141              : !>    order interpolating scaling function
     142              : !> \param itype ...
     143              : !> \param n_iter ...
     144              : !> \param n_range ...
     145              : !> \param kernel_scf ...
     146              : !> \param kern_1_scf ...
     147              : ! **************************************************************************************************
     148        48985 :    SUBROUTINE scf_recursion(itype, n_iter, n_range, kernel_scf, kern_1_scf)
     149              :       INTEGER, INTENT(in)                                :: itype, n_iter, n_range
     150              :       REAL(KIND=dp), INTENT(inout)                       :: kernel_scf(-n_range:n_range)
     151              :       REAL(KIND=dp), INTENT(out)                         :: kern_1_scf(-n_range:n_range)
     152              : 
     153              :       INTEGER                                            :: m
     154        48985 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cg, cgt, ch, cht
     155              : 
     156      9097120 :       kern_1_scf = 0.0_dp
     157        48985 :       m = itype + 2
     158        48985 :       CALL lazy_arrays(itype, m, ch, cg, cgt, cht)
     159        48985 :       CALL scf_recurs(n_iter, n_range, kernel_scf, kern_1_scf, m, ch)
     160        48985 :       DEALLOCATE (ch, cg, cgt, cht)
     161              : 
     162        48985 :    END SUBROUTINE scf_recursion
     163              : 
     164              : ! **************************************************************************************************
     165              : !> \brief Set to zero an array x(n)
     166              : !> \param n ...
     167              : !> \param x ...
     168              : ! **************************************************************************************************
     169         1060 :    SUBROUTINE zero(n, x)
     170              :       INTEGER, INTENT(in)                                :: n
     171              :       REAL(KIND=dp), INTENT(out)                         :: x(n)
     172              : 
     173              :       INTEGER                                            :: i
     174              : 
     175      5362760 :       DO i = 1, n
     176      5362760 :          x(i) = 0._dp
     177              :       END DO
     178         1060 :    END SUBROUTINE zero
     179              : 
     180              : ! **************************************************************************************************
     181              : !> \brief forward wavelet transform
     182              : !>    nd: length of data set
     183              : !>    nt length of data in data set to be transformed
     184              : !>    m filter length (m has to be even!)
     185              : !>    x input data, y output data
     186              : !> \param nd ...
     187              : !> \param nt ...
     188              : !> \param x ...
     189              : !> \param y ...
     190              : !> \param m ...
     191              : !> \param cgt ...
     192              : !> \param cht ...
     193              : ! **************************************************************************************************
     194            0 :    SUBROUTINE for_trans(nd, nt, x, y, m, cgt, cht)
     195              :       INTEGER, INTENT(in)                                :: nd, nt
     196              :       REAL(KIND=dp), INTENT(in)                          :: x(0:nd - 1)
     197              :       REAL(KIND=dp), INTENT(out)                         :: y(0:nd - 1)
     198              :       INTEGER                                            :: m
     199              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cgt, cht
     200              : 
     201              :       INTEGER                                            :: i, ind, j
     202              : 
     203            0 :       y = 0.0_dp
     204            0 :       DO i = 0, nt/2 - 1
     205            0 :          y(i) = 0._dp
     206            0 :          y(nt/2 + i) = 0._dp
     207              : 
     208            0 :          DO j = -m + 1, m
     209              : 
     210              :             ! periodically wrap index if necessary
     211            0 :             ind = j + 2*i
     212              :             loop99: DO
     213            0 :                IF (ind < 0) THEN
     214            0 :                   ind = ind + nt
     215            0 :                   CYCLE loop99
     216              :                END IF
     217            0 :                IF (ind >= nt) THEN
     218            0 :                   ind = ind - nt
     219            0 :                   CYCLE loop99
     220              :                END IF
     221              :                EXIT loop99
     222              :             END DO loop99
     223              : 
     224            0 :             y(i) = y(i) + cht(j)*x(ind)
     225            0 :             y(nt/2 + i) = y(nt/2 + i) + cgt(j)*x(ind)
     226              :          END DO
     227              : 
     228              :       END DO
     229              : 
     230            0 :    END SUBROUTINE for_trans
     231              : 
     232              : ! **************************************************************************************************
     233              : !> \brief ...
     234              : !> \param nd ...
     235              : !> \param nt ...
     236              : !> \param x ...
     237              : !> \param y ...
     238              : !> \param m ...
     239              : !> \param ch ...
     240              : !> \param cg ...
     241              : ! **************************************************************************************************
     242         3180 :    SUBROUTINE back_trans(nd, nt, x, y, m, ch, cg)
     243              :       ! backward wavelet transform
     244              :       ! nd: length of data set
     245              :       ! nt length of data in data set to be transformed
     246              :       ! m filter length (m has to be even!)
     247              :       ! x input data, y output data
     248              :       INTEGER, INTENT(in)                                :: nd, nt
     249              :       REAL(KIND=dp), INTENT(in)                          :: x(0:nd - 1)
     250              :       REAL(KIND=dp), INTENT(out)                         :: y(0:nd - 1)
     251              :       INTEGER                                            :: m
     252              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: ch, cg
     253              : 
     254              :       INTEGER                                            :: i, ind, j
     255              : 
     256     16085100 :       y = 0.0_dp
     257              : 
     258      2641620 :       DO i = 0, nt/2 - 1
     259      2638440 :          y(2*i + 0) = 0._dp
     260      2638440 :          y(2*i + 1) = 0._dp
     261              : 
     262    112997460 :          DO j = -m/2, m/2 - 1
     263              : 
     264              :             ! periodically wrap index if necessary
     265    110355840 :             ind = i - j
     266              :             loop99: DO
     267    111735600 :                IF (ind < 0) THEN
     268       656880 :                   ind = ind + nt/2
     269       656880 :                   CYCLE loop99
     270              :                END IF
     271    111078720 :                IF (ind >= nt/2) THEN
     272       722880 :                   ind = ind - nt/2
     273       722880 :                   CYCLE loop99
     274              :                END IF
     275              :                EXIT loop99
     276              :             END DO loop99
     277              : 
     278    110355840 :             y(2*i + 0) = y(2*i + 0) + ch(2*j - 0)*x(ind) + cg(2*j - 0)*x(ind + nt/2)
     279    112994280 :             y(2*i + 1) = y(2*i + 1) + ch(2*j + 1)*x(ind) + cg(2*j + 1)*x(ind + nt/2)
     280              :          END DO
     281              : 
     282              :       END DO
     283              : 
     284         3180 :    END SUBROUTINE back_trans
     285              : 
     286              : ! **************************************************************************************************
     287              : !> \brief Tests the 4 orthogonality relations of the filters
     288              : !> \param m ...
     289              : !> \param ch ...
     290              : !> \param cg ...
     291              : !> \param cgt ...
     292              : !> \param cht ...
     293              : ! **************************************************************************************************
     294            0 :    SUBROUTINE ftest(m, ch, cg, cgt, cht)
     295              :       INTEGER                                            :: m
     296              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: ch, cg, cgt, cht
     297              : 
     298              :       CHARACTER(len=*), PARAMETER                        :: fmt22 = "(a,i3,i4,4(e17.10))"
     299              : 
     300              :       INTEGER                                            :: i, j, l
     301              :       REAL(KIND=dp)                                      :: eps, t1, t2, t3, t4
     302              : 
     303              : ! do i=-m,m
     304              : ! WRITE(*,*) i,ch(i),cg(i)
     305              : ! end do
     306              : 
     307            0 :       DO i = -m, m
     308            0 :          DO j = -m, m
     309            0 :             t1 = 0._dp
     310            0 :             t2 = 0._dp
     311            0 :             t3 = 0._dp
     312            0 :             t4 = 0._dp
     313            0 :             DO l = -3*m, 3*m
     314              :                IF (l - 2*i >= -m .AND. l - 2*i <= m .AND. &
     315            0 :                    l - 2*j >= -m .AND. l - 2*j <= m) THEN
     316            0 :                   t1 = t1 + ch(l - 2*i)*cht(l - 2*j)
     317            0 :                   t2 = t2 + cg(l - 2*i)*cgt(l - 2*j)
     318            0 :                   t3 = t3 + ch(l - 2*i)*cgt(l - 2*j)
     319            0 :                   t4 = t4 + cht(l - 2*i)*cg(l - 2*j)
     320              :                END IF
     321              :             END DO
     322            0 :             eps = 1.e-10_dp
     323            0 :             IF (i == j) THEN
     324              :                IF (ABS(t1 - 1._dp) > eps .OR. ABS(t2 - 1._dp) > eps .OR. &
     325            0 :                    ABS(t3) > eps .OR. ABS(t4) > eps) THEN
     326            0 :                   WRITE (*, fmt22) 'Orthogonality ERROR', i, j, t1, t2, t3, t4
     327              :                END IF
     328              :             ELSE
     329              :                IF (ABS(t1) > eps .OR. ABS(t2) > eps .OR. &
     330            0 :                    ABS(t3) > eps .OR. ABS(t4) > eps) THEN
     331            0 :                   WRITE (*, fmt22) 'Orthogonality ERROR', i, j, t1, t2, t3, t4
     332              :                END IF
     333              :             END IF
     334              :          END DO
     335              :       END DO
     336              : 
     337            0 :       WRITE (*, *) 'FILTER TEST PASSED'
     338              : 
     339            0 :    END SUBROUTINE ftest
     340              : 
     341              : ! **************************************************************************************************
     342              : !> \brief Do iterations to go from p0gauss to pgauss
     343              : !>    8th-order interpolating scaling function
     344              : !> \param n_iter ...
     345              : !> \param n_range ...
     346              : !> \param kernel_scf ...
     347              : !> \param kern_1_scf ...
     348              : !> \param m ...
     349              : !> \param ch ...
     350              : ! **************************************************************************************************
     351        48985 :    SUBROUTINE scf_recurs(n_iter, n_range, kernel_scf, kern_1_scf, m, ch)
     352              :       INTEGER, INTENT(in)                                :: n_iter, n_range
     353              :       REAL(KIND=dp), INTENT(inout)                       :: kernel_scf(-n_range:n_range)
     354              :       REAL(KIND=dp), INTENT(out)                         :: kern_1_scf(-n_range:n_range)
     355              :       INTEGER                                            :: m
     356              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: ch
     357              : 
     358              :       INTEGER                                            :: i, i_iter, ind, j
     359              :       REAL(KIND=dp)                                      :: kern, kern_tot
     360              : 
     361      9097120 :       kern_1_scf = 0.0_dp
     362              :       !Start the iteration to go from p0gauss to pgauss
     363       546697 :       loop_iter_scf: DO i_iter = 1, n_iter
     364     85471416 :          kern_1_scf(:) = kernel_scf(:)
     365     85471416 :          kernel_scf(:) = 0._dp
     366     19930365 :          loop_iter_i: DO i = 0, n_range
     367     19881380 :             kern_tot = 0._dp
     368   1664764600 :             DO j = -m, m
     369   1644883220 :                ind = 2*i - j
     370   1644883220 :                IF (ABS(ind) > n_range) THEN
     371              :                   kern = 0._dp
     372              :                ELSE
     373   1456043460 :                   kern = kern_1_scf(ind)
     374              :                END IF
     375   1664764600 :                kern_tot = kern_tot + ch(j)*kern
     376              :             END DO
     377     19881380 :             IF (kern_tot == 0._dp) THEN
     378              :                !zero after (be sure because strictly == 0._dp)
     379              :                EXIT loop_iter_i
     380              :             ELSE
     381     19383668 :                kernel_scf(i) = 0.5_dp*kern_tot
     382     19383668 :                kernel_scf(-i) = kernel_scf(i)
     383              :             END IF
     384              :          END DO loop_iter_i
     385              :       END DO loop_iter_scf
     386        48985 :    END SUBROUTINE scf_recurs
     387              : 
     388              : END MODULE ps_wavelet_scaling_function
        

Generated by: LCOV version 2.0-1