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

Generated by: LCOV version 2.0-1