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