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_kernel
13 : USE fft_lib, ONLY: fft_1d,&
14 : fft_create_plan_1d,&
15 : fft_destroy_plan
16 : USE fft_plan, ONLY: fft_plan_type
17 : USE fft_tools, ONLY: BWFFT,&
18 : fft_alloc,&
19 : fft_dealloc
20 : USE kinds, ONLY: dp
21 : USE mathconstants, ONLY: pi
22 : USE message_passing, ONLY: mp_comm_type
23 : USE ps_wavelet_base, ONLY: scramble_unpack
24 : USE ps_wavelet_scaling_function, ONLY: scaling_function,&
25 : scf_recursion
26 : USE ps_wavelet_util, ONLY: F_FFT_dimensions,&
27 : S_FFT_dimensions
28 : #include "../base/base_uses.f90"
29 :
30 : IMPLICIT NONE
31 :
32 : PRIVATE
33 :
34 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ps_wavelet_kernel'
35 :
36 : ! *** Public data types ***
37 :
38 : PUBLIC :: createKernel
39 :
40 : CONTAINS
41 :
42 : ! **************************************************************************************************
43 : !> \brief Allocate a pointer which corresponds to the zero-padded FFT slice needed for
44 : !> calculating the convolution with the kernel expressed in the interpolating scaling
45 : !> function basis. The kernel pointer is unallocated on input, allocated on output.
46 : !> \param geocode Indicates the boundary conditions (BC) of the problem:
47 : !> 'F' free BC, isolated systems.
48 : !> The program calculates the solution as if the given density is
49 : !> "alone" in R^3 space.
50 : !> 'S' surface BC, isolated in y direction, periodic in xz plane
51 : !> The given density is supposed to be periodic in the xz plane,
52 : !> so the dimensions in these direction mus be compatible with the FFT
53 : !> Beware of the fact that the isolated direction is y!
54 : !> 'P' periodic BC.
55 : !> The density is supposed to be periodic in all the three directions,
56 : !> then all the dimensions must be compatible with the FFT.
57 : !> No need for setting up the kernel.
58 : !> \param n01 dimensions of the real space grid to be hit with the Poisson Solver
59 : !> \param n02 dimensions of the real space grid to be hit with the Poisson Solver
60 : !> \param n03 dimensions of the real space grid to be hit with the Poisson Solver
61 : !> \param hx grid spacings. For the isolated BC case for the moment they are supposed to
62 : !> be equal in the three directions
63 : !> \param hy grid spacings. For the isolated BC case for the moment they are supposed to
64 : !> be equal in the three directions
65 : !> \param hz grid spacings. For the isolated BC case for the moment they are supposed to
66 : !> be equal in the three directions
67 : !> \param itype_scf order of the interpolating scaling functions used in the decomposition
68 : !> \param iproc ,nproc: number of process, number of processes
69 : !> \param nproc ...
70 : !> \param kernel pointer for the kernel FFT. Unallocated on input, allocated on output.
71 : !> Its dimensions are equivalent to the region of the FFT space for which the
72 : !> kernel is injective. This will divide by two each direction,
73 : !> since the kernel for the zero-padded convolution is real and symmetric.
74 : !> \param mpi_group ...
75 : !> \date February 2007
76 : !> \author Luigi Genovese
77 : !> \note Due to the fact that the kernel dimensions are unknown before the calling, the kernel
78 : !> must be declared as pointer in input of this routine.
79 : !> To avoid that, one can properly define the kernel dimensions by adding
80 : !> the nd1,nd2,nd3 arguments to the PS_dim4allocation routine, then eliminating the pointer
81 : !> declaration.
82 : ! **************************************************************************************************
83 926 : SUBROUTINE createKernel(geocode, n01, n02, n03, hx, hy, hz, itype_scf, iproc, nproc, kernel, mpi_group)
84 :
85 : CHARACTER(len=1), INTENT(in) :: geocode
86 : INTEGER, INTENT(in) :: n01, n02, n03
87 : REAL(KIND=dp), INTENT(in) :: hx, hy, hz
88 : INTEGER, INTENT(in) :: itype_scf, iproc, nproc
89 : REAL(KIND=dp), POINTER :: kernel(:)
90 :
91 : CLASS(mp_comm_type), INTENT(in) :: mpi_group
92 :
93 : INTEGER :: m1, m2, m3, md1, md2, md3, n1, n2, n3, &
94 : nd1, nd2, nd3, nlimd, nlimk
95 : REAL(KIND=dp) :: hgrid
96 :
97 926 : hgrid = MAX(hx, hy, hz)
98 :
99 926 : IF (geocode == 'P') THEN
100 :
101 : CALL F_FFT_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, &
102 326 : md1, md2, md3, nd1, nd2, nd3, nproc)
103 :
104 326 : ALLOCATE (kernel(1))
105 326 : nlimd = n2
106 652 : nlimk = 0
107 :
108 600 : ELSE IF (geocode == 'S') THEN
109 :
110 : CALL S_FFT_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, &
111 6 : md1, md2, md3, nd1, nd2, nd3, nproc)
112 :
113 18 : ALLOCATE (kernel(nd1*nd2*nd3/nproc))
114 :
115 : !the kernel must be built and scattered to all the processes
116 :
117 : CALL Surfaces_Kernel(n1, n2, n3, m3, nd1, nd2, nd3, hx, hz, hy, &
118 6 : itype_scf, kernel, iproc, nproc, mpi_group)
119 : !last plane calculated for the density and the kernel
120 :
121 6 : nlimd = n2
122 12 : nlimk = n3/2 + 1
123 594 : ELSE IF (geocode == 'F') THEN
124 :
125 : !Build the Kernel
126 :
127 : CALL F_FFT_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, &
128 594 : md1, md2, md3, nd1, nd2, nd3, nproc)
129 1782 : ALLOCATE (kernel(nd1*nd2*nd3/nproc))
130 :
131 : !the kernel must be built and scattered to all the processes
132 : CALL Free_Kernel(n01, n02, n03, n1, n2, n3, nd1, nd2, nd3, hgrid, &
133 594 : itype_scf, iproc, nproc, kernel, mpi_group)
134 :
135 : !last plane calculated for the density and the kernel
136 594 : nlimd = n2/2
137 1188 : nlimk = n3/2 + 1
138 :
139 : ELSE
140 :
141 0 : CPABORT("No wavelet based poisson solver for given geometry")
142 :
143 : END IF
144 926 : END SUBROUTINE createKernel
145 :
146 : ! **************************************************************************************************
147 : !> \brief Build the kernel of the Poisson operator with
148 : !> surfaces Boundary conditions
149 : !> in an interpolating scaling functions basis.
150 : !> Beware of the fact that the nonperiodic direction is y!
151 : !> \param n1 Dimensions for the FFT
152 : !> \param n2 Dimensions for the FFT
153 : !> \param n3 Dimensions for the FFT
154 : !> \param m3 Actual dimension in non-periodic direction
155 : !> \param nker1 Dimensions of the kernel (nker3=n3/2+1) nker(1,2)=n(1,2)/2+1
156 : !> \param nker2 Dimensions of the kernel (nker3=n3/2+1) nker(1,2)=n(1,2)/2+1
157 : !> \param nker3 Dimensions of the kernel (nker3=n3/2+1) nker(1,2)=n(1,2)/2+1
158 : !> \param h1 Mesh steps in the three dimensions
159 : !> \param h2 Mesh steps in the three dimensions
160 : !> \param h3 Mesh steps in the three dimensions
161 : !> \param itype_scf Order of the scaling function
162 : !> \param karray output array
163 : !> \param iproc Number of process
164 : !> \param nproc number of processes
165 : !> \param mpi_group ...
166 : !> \date October 2006
167 : !> \author L. Genovese
168 : ! **************************************************************************************************
169 6 : SUBROUTINE Surfaces_Kernel(n1, n2, n3, m3, nker1, nker2, nker3, h1, h2, h3, &
170 6 : itype_scf, karray, iproc, nproc, mpi_group)
171 :
172 : INTEGER, INTENT(in) :: n1, n2, n3, m3, nker1, nker2, nker3
173 : REAL(KIND=dp), INTENT(in) :: h1, h2, h3
174 : INTEGER, INTENT(in) :: itype_scf, nproc, iproc
175 : REAL(KIND=dp), &
176 : DIMENSION(nker1, nker2, nker3/nproc), &
177 : INTENT(out) :: karray
178 : TYPE(mp_comm_type), INTENT(in) :: mpi_group
179 :
180 : INTEGER, PARAMETER :: n_points = 2**6, ncache_optimal = 8*1024
181 :
182 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:), &
183 6 : POINTER :: halfft_cache1, halfft_cache2
184 : INTEGER :: final_chunk_size, i1, i2, i3, iend, imu, ind1, ind2, ipolyord, ireim, istart, j2, &
185 : j2nd, j2st, jnd1, jp2, jreim, n_cell, n_range, n_scf, nact2, ncache, nfft, num_of_mus, &
186 : shift, stat
187 : REAL(kind=dp) :: a, b, c, cp, d, diff, dx, feI, feR, foI, &
188 : foR, fR, mu1, pion, ponx, pony, sp, &
189 : value, x
190 6 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: kernel_scf, x_scf, y_scf
191 6 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: cossinarr
192 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: kernel
193 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: kernel_mpi
194 : REAL(KIND=dp), DIMENSION(9, 8) :: cpol
195 : TYPE(fft_plan_type) :: fft_plan_bw, fft_plan_bw_last
196 :
197 : !Better if higher (1024 points are enough 10^{-14}: 2*itype_scf*n_points)
198 : !FFT arrays
199 : !coefficients for the polynomial interpolation
200 : !assign the values of the coefficients
201 :
202 136590 : karray = 0.0_dp
203 486 : cpol(:, :) = 1._dp
204 6 : cpol(1, 2) = .25_dp
205 6 : cpol(1, 3) = 1._dp/3._dp
206 6 : cpol(1, 4) = 7._dp/12._dp
207 6 : cpol(2, 4) = 8._dp/3._dp
208 6 : cpol(1, 5) = 19._dp/50._dp
209 6 : cpol(2, 5) = 3._dp/2._dp
210 6 : cpol(1, 6) = 41._dp/272._dp
211 6 : cpol(2, 6) = 27._dp/34._dp
212 6 : cpol(3, 6) = 27._dp/272._dp
213 6 : cpol(1, 7) = 751._dp/2989._dp
214 6 : cpol(2, 7) = 73._dp/61._dp
215 6 : cpol(3, 7) = 27._dp/61._dp
216 6 : cpol(1, 8) = -989._dp/4540._dp
217 6 : cpol(2, 8) = -1472._dp/1135._dp
218 6 : cpol(3, 8) = 232._dp/1135._dp
219 6 : cpol(4, 8) = -2624._dp/1135._dp
220 :
221 : !renormalize values
222 6 : cpol(1, 1) = .5_dp*cpol(1, 1)
223 18 : cpol(1:2, 2) = 2._dp/3._dp*cpol(1:2, 2)
224 18 : cpol(1:2, 3) = 3._dp/8._dp*cpol(1:2, 3)
225 24 : cpol(1:3, 4) = 2._dp/15._dp*cpol(1:3, 4)
226 24 : cpol(1:3, 5) = 25._dp/144._dp*cpol(1:3, 5)
227 30 : cpol(1:4, 6) = 34._dp/105._dp*cpol(1:4, 6)
228 30 : cpol(1:4, 7) = 2989._dp/17280._dp*cpol(1:4, 7)
229 36 : cpol(1:5, 8) = -454._dp/2835._dp*cpol(1:5, 8)
230 :
231 : !assign the complete values
232 6 : cpol(2, 1) = cpol(1, 1)
233 6 : cpol(3, 2) = cpol(1, 2)
234 6 : cpol(3, 3) = cpol(2, 3)
235 6 : cpol(4, 3) = cpol(1, 3)
236 6 : cpol(4, 4) = cpol(2, 4)
237 6 : cpol(5, 4) = cpol(1, 4)
238 6 : cpol(4, 5) = cpol(3, 5)
239 6 : cpol(5, 5) = cpol(2, 5)
240 6 : cpol(6, 5) = cpol(1, 5)
241 6 : cpol(5, 6) = cpol(3, 6)
242 6 : cpol(6, 6) = cpol(2, 6)
243 6 : cpol(7, 6) = cpol(1, 6)
244 6 : cpol(5, 7) = cpol(4, 7)
245 6 : cpol(6, 7) = cpol(3, 7)
246 6 : cpol(7, 7) = cpol(2, 7)
247 6 : cpol(8, 7) = cpol(1, 7)
248 6 : cpol(6, 8) = cpol(4, 8)
249 6 : cpol(7, 8) = cpol(3, 8)
250 6 : cpol(8, 8) = cpol(2, 8)
251 6 : cpol(9, 8) = cpol(1, 8)
252 :
253 : !Number of integration points : 2*itype_scf*n_points
254 6 : n_scf = 2*itype_scf*n_points
255 : !Allocations
256 18 : ALLOCATE (x_scf(0:n_scf))
257 12 : ALLOCATE (y_scf(0:n_scf))
258 :
259 : !Build the scaling function
260 6 : CALL scaling_function(itype_scf, n_scf, n_range, x_scf, y_scf)
261 : !Step grid for the integration
262 6 : dx = REAL(n_range, KIND=dp)/REAL(n_scf, KIND=dp)
263 : !Extend the range (no more calculations because fill in by 0._dp)
264 6 : n_cell = m3
265 6 : n_range = MAX(n_cell, n_range)
266 :
267 : !Allocations
268 6 : ncache = ncache_optimal
269 : !the HalFFT must be performed only in the third dimension,
270 : !and nker3=n3/2+1, hence
271 6 : IF (ncache <= (nker3 - 1)*4) ncache = nker3 - 1*4
272 :
273 : !enlarge the second dimension of the kernel to be compatible with nproc
274 6 : nact2 = nker2
275 0 : enlarge_ydim: DO
276 6 : IF (nproc*(nact2/nproc) /= nact2) THEN
277 0 : nact2 = nact2 + 1
278 : ELSE
279 : EXIT enlarge_ydim
280 : END IF
281 : END DO enlarge_ydim
282 :
283 : !array for the MPI procedure
284 30 : ALLOCATE (kernel(nker1, nact2/nproc, nker3))
285 36 : ALLOCATE (kernel_mpi(nker1, nact2/nproc, nker3/nproc, nproc))
286 18 : ALLOCATE (kernel_scf(n_range))
287 12 : CALL fft_alloc(halfft_cache1, [MAX(ncache/4, n3/2)])
288 6 : halfft_cache1 = CMPLX(0.0_dp, 0.0_dp, dp)
289 12 : CALL fft_alloc(halfft_cache2, [MAX(ncache/4, n3/2)])
290 6 : halfft_cache2 = CMPLX(0.0_dp, 0.0_dp, dp)
291 18 : ALLOCATE (cossinarr(2, n3/2 - 1))
292 :
293 : !build the phases for the HalFFT reconstruction
294 6 : pion = 2._dp*pi/REAL(n3, KIND=dp)
295 324 : DO i3 = 2, n3/2
296 318 : x = REAL(i3 - 1, KIND=dp)*pion
297 318 : cossinarr(1, i3 - 1) = COS(x)
298 324 : cossinarr(2, i3 - 1) = -SIN(x)
299 : END DO
300 :
301 : ! satisfy valgrind, init arrays to large value, even if the offending bit is (likely?) padding
302 136758 : kernel = HUGE(0._dp)
303 136770 : kernel_mpi = HUGE(0._dp)
304 :
305 : !calculate the limits of the FFT calculations
306 : !that can be performed in a row remaining inside the cache
307 6 : num_of_mus = MAX(1, ncache/(2*n3))
308 :
309 6 : diff = 0._dp
310 : !order of the polynomial to be used for integration (must be a power of two)
311 6 : ipolyord = 8 !this part should be incorporated inside the numerical integration
312 : !here we have to choice the piece of the x-y grid to cover
313 :
314 : !let us now calculate the fraction of mu that will be considered
315 6 : j2st = iproc*(nact2/nproc)
316 6 : j2nd = MIN((iproc + 1)*(nact2/nproc), n2/2 + 1)
317 :
318 : ! The size of the last chunk
319 6 : final_chunk_size = MOD((n1/2 + 1)*(j2nd - j2st), num_of_mus)
320 :
321 : ! Prevent OOB-access if n1 < num_of_mus
322 6 : IF ((n1/2 + 1)*(j2nd - j2st) >= num_of_mus) THEN
323 : CALL fft_create_plan_1d(fft_plan_bw, BWFFT, .TRUE., .TRUE., num_of_mus, num_of_mus, &
324 6 : n3/2, num_of_mus, halfft_cache1, halfft_cache2)
325 : END IF
326 6 : IF (final_chunk_size > 0) THEN
327 : CALL fft_create_plan_1d(fft_plan_bw_last, BWFFT, .TRUE., .TRUE., num_of_mus, num_of_mus, &
328 6 : n3/2, final_chunk_size, halfft_cache1, halfft_cache2)
329 : END IF
330 :
331 72 : DO ind2 = (n1/2 + 1)*j2st + 1, (n1/2 + 1)*j2nd, num_of_mus
332 66 : istart = ind2
333 66 : iend = MIN(ind2 + (num_of_mus - 1), (n1/2 + 1)*j2nd)
334 66 : nfft = iend - istart + 1
335 66 : shift = 0
336 :
337 : !initialization of the interesting part of the cache array
338 : ! THis could be replaced using a R2C-FFT (not yet available in CP2K)
339 66 : halfft_cache1 = CMPLX(0.0_dp, 0.0_dp, dp)
340 66 : halfft_cache1 = CMPLX(0.0_dp, 0.0_dp, dp)
341 :
342 66 : IF (istart == 1) THEN
343 : !i2=1
344 3 : shift = 1
345 :
346 : CALL calculates_green_opt_muzero(n_range, n_scf, ipolyord, x_scf, y_scf, &
347 3 : cpol(1, ipolyord), dx, kernel_scf)
348 :
349 : !copy of the first zero value
350 3 : halfft_cache1(1) = CMPLX(0._dp, AIMAG(halfft_cache1(1)), dp)
351 :
352 165 : DO i3 = 1, m3
353 :
354 162 : value = 0.5_dp*h3*kernel_scf(i3)
355 : !index in where to copy the value of the kernel
356 162 : CALL indices(ireim, num_of_mus, n3/2 + i3, 1, ind1)
357 : !index in where to copy the symmetric value
358 162 : CALL indices(jreim, num_of_mus, n3/2 + 2 - i3, 1, jnd1)
359 162 : IF (ireim == 1) THEN
360 81 : halfft_cache1(ind1) = CMPLX(value, AIMAG(halfft_cache1(ind1)), dp)
361 : ELSE
362 81 : halfft_cache1(ind1) = CMPLX(REAL(halfft_cache1(ind1), dp), value, dp)
363 : END IF
364 165 : IF (jreim == 1) THEN
365 81 : halfft_cache1(jnd1) = CMPLX(value, AIMAG(halfft_cache1(jnd1)), dp)
366 : ELSE
367 81 : halfft_cache1(jnd1) = CMPLX(REAL(halfft_cache1(jnd1), dp), value, dp)
368 : END IF
369 :
370 : END DO
371 :
372 : END IF
373 :
374 2415 : loopimpulses: DO imu = istart + shift, iend
375 :
376 : !here there is the value of mu associated to hgrid
377 : !note that we have multiplicated mu for hgrid to be comparable
378 : !with mu0ref
379 :
380 : !calculate the proper value of mu taking into account the periodic dimensions
381 : !corresponding value of i1 and i2
382 2349 : i1 = MOD(imu, n1/2 + 1)
383 2349 : IF (i1 == 0) i1 = n1/2 + 1
384 2349 : i2 = (imu - i1)/(n1/2 + 1) + 1
385 2349 : ponx = REAL(i1 - 1, KIND=dp)/REAL(n1, KIND=dp)
386 2349 : pony = REAL(i2 - 1, KIND=dp)/REAL(n2, KIND=dp)
387 :
388 2349 : mu1 = 2._dp*pi*SQRT((ponx/h1)**2 + (pony/h2)**2)*h3
389 :
390 : CALL calculates_green_opt(n_range, n_scf, itype_scf, ipolyord, x_scf, y_scf, &
391 2349 : cpol(1, ipolyord), mu1, dx, kernel_scf)
392 :
393 : !readjust the coefficient and define the final kernel
394 :
395 : !copy of the first zero value
396 2349 : halfft_cache1(imu - istart + 1) = CMPLX(0._dp, AIMAG(halfft_cache1(imu - istart + 1)), dp)
397 129261 : DO i3 = 1, m3
398 126846 : value = -0.5_dp*h3/mu1*kernel_scf(i3)
399 : !index in where to copy the value of the kernel
400 126846 : CALL indices(ireim, num_of_mus, n3/2 + i3, imu - istart + 1, ind1)
401 : !index in where to copy the symmetric value
402 126846 : CALL indices(jreim, num_of_mus, n3/2 + 2 - i3, imu - istart + 1, jnd1)
403 126846 : IF (ireim == 1) THEN
404 63423 : halfft_cache1(ind1) = CMPLX(value, AIMAG(halfft_cache1(ind1)), dp)
405 : ELSE
406 63423 : halfft_cache1(ind1) = CMPLX(REAL(halfft_cache1(ind1), dp), value, dp)
407 : END IF
408 129195 : IF (jreim == 1) THEN
409 63423 : halfft_cache1(jnd1) = CMPLX(value, AIMAG(halfft_cache1(jnd1)), dp)
410 : ELSE
411 63423 : halfft_cache1(jnd1) = CMPLX(REAL(halfft_cache1(jnd1), dp), value, dp)
412 : END IF
413 : END DO
414 :
415 : END DO loopimpulses
416 :
417 : !now perform the FFT of the array in cache
418 : ! This is equivalent to
419 66 : IF (nfft == num_of_mus) THEN
420 60 : CALL fft_1d(fft_plan_bw, halfft_cache1, halfft_cache2, 1.0_dp, stat)
421 : ELSE
422 6 : CALL fft_1d(fft_plan_bw_last, halfft_cache1, halfft_cache2, 1.0_dp, stat)
423 : END IF
424 :
425 : !assign the values of the FFT array
426 : !and compare with the good results
427 2424 : DO imu = istart, iend
428 :
429 : !corresponding value of i1 and i2
430 2352 : i1 = MOD(imu, n1/2 + 1)
431 2352 : IF (i1 == 0) i1 = n1/2 + 1
432 2352 : i2 = (imu - i1)/(n1/2 + 1) + 1
433 :
434 2352 : j2 = i2 - j2st
435 :
436 2352 : a = REAL(halfft_cache2(imu - istart + 1), dp)
437 2352 : b = AIMAG(halfft_cache2(imu - istart + 1))
438 2352 : kernel(i1, j2, 1) = a + b
439 2352 : kernel(i1, j2, n3/2 + 1) = a - b
440 :
441 127074 : DO i3 = 2, n3/2
442 124656 : ind1 = imu - istart + 1 + num_of_mus*(i3 - 1)
443 124656 : jnd1 = imu - istart + 1 + num_of_mus*(n3/2 + 2 - i3 - 1)
444 124656 : cp = cossinarr(1, i3 - 1)
445 124656 : sp = cossinarr(2, i3 - 1)
446 124656 : a = REAL(halfft_cache2(ind1), dp)
447 124656 : b = AIMAG(halfft_cache2(ind1))
448 124656 : c = REAL(halfft_cache2(jnd1), dp)
449 124656 : d = AIMAG(halfft_cache2(jnd1))
450 124656 : feR = .5_dp*(a + c)
451 124656 : feI = .5_dp*(b - d)
452 124656 : foR = .5_dp*(a - c)
453 124656 : foI = .5_dp*(b + d)
454 124656 : fR = feR + cp*foI - sp*foR
455 127008 : kernel(i1, j2, i3) = fR
456 : END DO
457 : END DO
458 :
459 : END DO
460 :
461 6 : IF ((n1/2 + 1)*(j2nd - j2st) >= num_of_mus) CALL fft_destroy_plan(fft_plan_bw)
462 6 : IF (final_chunk_size > 0) CALL fft_destroy_plan(fft_plan_bw_last)
463 :
464 : !give to each processor a slice of the third dimension
465 6 : IF (nproc > 1) THEN
466 : CALL mpi_group%alltoall(kernel, &!nker1*(nact2/nproc)*(nker3/nproc), &
467 6 : kernel_mpi, nker1*(nact2/nproc)*(nker3/nproc))
468 :
469 18 : DO jp2 = 1, nproc
470 354 : DO i3 = 1, nker3/nproc
471 5052 : DO i2 = 1, nact2/nproc
472 4704 : j2 = i2 + (jp2 - 1)*(nact2/nproc)
473 5040 : IF (j2 <= nker2) THEN
474 136416 : DO i1 = 1, nker1
475 : karray(i1, j2, i3) = &
476 136416 : kernel_mpi(i1, i2, i3, jp2)
477 : END DO
478 : END IF
479 : END DO
480 : END DO
481 : END DO
482 :
483 : ELSE
484 0 : karray(1:nker1, 1:nker2, 1:nker3) = kernel(1:nker1, 1:nker2, 1:nker3)
485 : END IF
486 :
487 : !De-allocations
488 6 : DEALLOCATE (kernel)
489 6 : DEALLOCATE (kernel_mpi)
490 6 : CALL fft_dealloc(halfft_cache1)
491 6 : CALL fft_dealloc(halfft_cache2)
492 6 : DEALLOCATE (kernel_scf)
493 6 : DEALLOCATE (x_scf)
494 6 : DEALLOCATE (y_scf)
495 :
496 54 : END SUBROUTINE Surfaces_Kernel
497 :
498 : ! **************************************************************************************************
499 : !> \brief ...
500 : !> \param n ...
501 : !> \param n_scf ...
502 : !> \param itype_scf ...
503 : !> \param intorder ...
504 : !> \param xval ...
505 : !> \param yval ...
506 : !> \param c ...
507 : !> \param mu ...
508 : !> \param hres ...
509 : !> \param g_mu ...
510 : ! **************************************************************************************************
511 2349 : SUBROUTINE calculates_green_opt(n, n_scf, itype_scf, intorder, xval, yval, c, mu, hres, g_mu)
512 : INTEGER, INTENT(in) :: n, n_scf, itype_scf, intorder
513 : REAL(KIND=dp), DIMENSION(0:n_scf), INTENT(in) :: xval, yval
514 : REAL(KIND=dp), DIMENSION(intorder+1), INTENT(in) :: c
515 : REAL(KIND=dp), INTENT(in) :: mu, hres
516 : REAL(KIND=dp), DIMENSION(n), INTENT(out) :: g_mu
517 :
518 : REAL(KIND=dp), PARAMETER :: mu_max = 0.2_dp
519 :
520 : INTEGER :: i, iend, ikern, ivalue, izero, n_iter, &
521 : nrec
522 : REAL(KIND=dp) :: f, filter, fl, fr, gleft, gltmp, gright, &
523 : grtmp, mu0, ratio, x, x0, x1
524 2349 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: green, green1
525 :
526 129195 : g_mu = 0.0_dp
527 : !We calculate the number of iterations to go from mu0 to mu0_ref
528 2349 : IF (mu <= mu_max) THEN
529 9 : n_iter = 0
530 9 : mu0 = mu
531 : ELSE
532 2340 : n_iter = 1
533 6888 : loop_iter: DO
534 9228 : ratio = REAL(2**n_iter, KIND=dp)
535 9228 : mu0 = mu/ratio
536 9228 : IF (mu0 <= mu_max) THEN
537 : EXIT loop_iter
538 : END IF
539 6888 : n_iter = n_iter + 1
540 : END DO loop_iter
541 : END IF
542 :
543 : !dimension needed for the correct calculation of the recursion
544 2349 : nrec = 2**n_iter*n
545 :
546 7047 : ALLOCATE (green(-nrec:nrec))
547 :
548 : !initialization of the branching value
549 1956717 : ikern = 0
550 1956717 : izero = 0
551 1954368 : initialization: DO
552 1956717 : IF (xval(izero) >= REAL(ikern, KIND=dp) .OR. izero == n_scf) EXIT initialization
553 1954368 : izero = izero + 1
554 : END DO initialization
555 2349 : green = 0._dp
556 : !now perform the interpolation in right direction
557 2349 : ivalue = izero
558 2349 : gright = 0._dp
559 279531 : loop_right: DO
560 281880 : IF (ivalue >= n_scf - intorder - 1) EXIT loop_right
561 2795310 : DO i = 1, intorder + 1
562 2515779 : x = xval(ivalue) - REAL(ikern, KIND=dp)
563 2515779 : f = yval(ivalue)*EXP(-mu0*x)
564 2515779 : filter = intorder*c(i)
565 2515779 : gright = gright + filter*f
566 2795310 : ivalue = ivalue + 1
567 : END DO
568 279531 : ivalue = ivalue - 1
569 : END DO loop_right
570 2349 : iend = n_scf - ivalue
571 21141 : DO i = 1, iend
572 18792 : x = xval(ivalue) - REAL(ikern, KIND=dp)
573 18792 : f = yval(ivalue)*EXP(-mu0*x)
574 18792 : filter = intorder*c(i)
575 18792 : gright = gright + filter*f
576 21141 : ivalue = ivalue + 1
577 : END DO
578 2349 : gright = hres*gright
579 :
580 : !the scaling function is symmetric, so the same for the other direction
581 2349 : gleft = gright
582 :
583 2349 : green(ikern) = gleft + gright
584 :
585 : !now the loop until the last value
586 758880 : DO ikern = 1, nrec
587 1005372 : gltmp = 0._dp
588 1005372 : grtmp = 0._dp
589 1005372 : ivalue = izero
590 1005372 : x0 = xval(izero)
591 246645 : loop_integration: DO
592 1005372 : IF (izero == n_scf) EXIT loop_integration
593 2783565 : DO i = 1, intorder + 1
594 2536920 : x = xval(ivalue)
595 2536920 : fl = yval(ivalue)*EXP(mu0*x)
596 2536920 : fr = yval(ivalue)*EXP(-mu0*x)
597 2536920 : filter = intorder*c(i)
598 2536920 : gltmp = gltmp + filter*fl
599 2536920 : grtmp = grtmp + filter*fr
600 2536920 : ivalue = ivalue + 1
601 2536920 : IF (xval(izero) >= REAL(ikern, KIND=dp) .OR. izero == n_scf) THEN
602 : x1 = xval(izero)
603 : EXIT loop_integration
604 : END IF
605 2748330 : izero = izero + 1
606 : END DO
607 246645 : ivalue = ivalue - 1
608 246645 : izero = izero - 1
609 : END DO loop_integration
610 758727 : gleft = EXP(-mu0)*(gleft + hres*EXP(-mu0*REAL(ikern - 1, KIND=dp))*gltmp)
611 758727 : IF (izero == n_scf) THEN
612 : gright = 0._dp
613 : ELSE
614 32886 : gright = EXP(mu0)*(gright - hres*EXP(mu0*REAL(ikern - 1, KIND=dp))*grtmp)
615 : END IF
616 758727 : green(ikern) = gleft + gright
617 758727 : green(-ikern) = gleft + gright
618 758880 : IF (ABS(green(ikern)) <= 1.e-20_dp) THEN
619 2196 : nrec = ikern
620 2196 : EXIT
621 : END IF
622 : END DO
623 : !now we must calculate the recursion
624 7047 : ALLOCATE (green1(-nrec:nrec))
625 :
626 : !Start the iteration to go from mu0 to mu
627 2349 : CALL scf_recursion(itype_scf, n_iter, nrec, green(-nrec), green1(-nrec))
628 :
629 129195 : DO i = 1, MIN(n, nrec)
630 129195 : g_mu(i) = green(i - 1)
631 : END DO
632 2349 : DO i = MIN(n, nrec) + 1, n
633 2349 : g_mu(i) = 0._dp
634 : END DO
635 :
636 2349 : DEALLOCATE (green, green1)
637 :
638 2349 : END SUBROUTINE calculates_green_opt
639 :
640 : ! **************************************************************************************************
641 : !> \brief ...
642 : !> \param n ...
643 : !> \param n_scf ...
644 : !> \param intorder ...
645 : !> \param xval ...
646 : !> \param yval ...
647 : !> \param c ...
648 : !> \param hres ...
649 : !> \param green ...
650 : ! **************************************************************************************************
651 3 : PURE SUBROUTINE calculates_green_opt_muzero(n, n_scf, intorder, xval, yval, c, hres, green)
652 : INTEGER, INTENT(in) :: n, n_scf, intorder
653 : REAL(KIND=dp), DIMENSION(0:n_scf), INTENT(in) :: xval, yval
654 : REAL(KIND=dp), DIMENSION(intorder+1), INTENT(in) :: c
655 : REAL(KIND=dp), INTENT(in) :: hres
656 : REAL(KIND=dp), DIMENSION(n), INTENT(out) :: green
657 :
658 : INTEGER :: i, iend, ikern, ivalue, izero
659 : REAL(KIND=dp) :: c0, c1, filter, gl0, gl1, gr0, gr1, x, y
660 :
661 : !initialization of the branching value
662 :
663 3 : ikern = 0
664 3 : izero = 0
665 2496 : initialization: DO
666 2499 : IF (xval(izero) >= REAL(ikern, KIND=dp) .OR. izero == n_scf) EXIT initialization
667 2496 : izero = izero + 1
668 : END DO initialization
669 165 : green = 0._dp
670 : !first case, ikern=0
671 : !now perform the interpolation in right direction
672 : ivalue = izero
673 : gr1 = 0._dp
674 357 : loop_right: DO
675 360 : IF (ivalue >= n_scf - intorder - 1) EXIT loop_right
676 3570 : DO i = 1, intorder + 1
677 3213 : x = xval(ivalue)
678 3213 : y = yval(ivalue)
679 3213 : filter = intorder*c(i)
680 3213 : gr1 = gr1 + filter*x*y
681 3570 : ivalue = ivalue + 1
682 : END DO
683 357 : ivalue = ivalue - 1
684 : END DO loop_right
685 3 : iend = n_scf - ivalue
686 27 : DO i = 1, iend
687 24 : x = xval(ivalue)
688 24 : y = yval(ivalue)
689 24 : filter = intorder*c(i)
690 24 : gr1 = gr1 + filter*x*y
691 27 : ivalue = ivalue + 1
692 : END DO
693 3 : gr1 = hres*gr1
694 : !the scaling function is symmetric
695 3 : gl1 = -gr1
696 3 : gl0 = 0.5_dp
697 3 : gr0 = 0.5_dp
698 :
699 3 : green(1) = 2._dp*gr1
700 :
701 : !now the loop until the last value
702 162 : DO ikern = 1, n - 1
703 : c0 = 0._dp
704 : c1 = 0._dp
705 : ivalue = izero
706 315 : loop_integration: DO
707 474 : IF (izero == n_scf) EXIT loop_integration
708 3555 : DO i = 1, intorder + 1
709 3240 : x = xval(ivalue)
710 3240 : y = yval(ivalue)
711 3240 : filter = intorder*c(i)
712 3240 : c0 = c0 + filter*y
713 3240 : c1 = c1 + filter*y*x
714 3240 : ivalue = ivalue + 1
715 3240 : IF (xval(izero) >= REAL(ikern, KIND=dp) .OR. izero == n_scf) THEN
716 : EXIT loop_integration
717 : END IF
718 3510 : izero = izero + 1
719 : END DO
720 315 : ivalue = ivalue - 1
721 360 : izero = izero - 1
722 : END DO loop_integration
723 159 : c0 = hres*c0
724 159 : c1 = hres*c1
725 :
726 159 : gl0 = gl0 + c0
727 159 : gl1 = gl1 + c1
728 159 : gr0 = gr0 - c0
729 159 : gr1 = gr1 - c1
730 : !general case
731 162 : green(ikern + 1) = REAL(ikern, KIND=dp)*(gl0 - gr0) + gr1 - gl1
732 : END DO
733 :
734 3 : END SUBROUTINE calculates_green_opt_muzero
735 :
736 : ! **************************************************************************************************
737 : !> \brief ...
738 : !> \param var_realimag ...
739 : !> \param nelem ...
740 : !> \param intrn ...
741 : !> \param extrn ...
742 : !> \param index ...
743 : ! **************************************************************************************************
744 254016 : PURE ELEMENTAL SUBROUTINE indices(var_realimag, nelem, intrn, extrn, index)
745 :
746 : INTEGER, INTENT(out) :: var_realimag
747 : INTEGER, INTENT(in) :: nelem, intrn, extrn
748 : INTEGER, INTENT(out) :: index
749 :
750 : INTEGER :: i
751 :
752 : !real or imaginary part
753 :
754 254016 : var_realimag = 2 - MOD(intrn, 2)
755 : !actual index over half the length
756 :
757 254016 : i = (intrn + 1)/2
758 : !complete index to be assigned
759 254016 : index = extrn + nelem*(i - 1)
760 :
761 254016 : END SUBROUTINE indices
762 :
763 : ! **************************************************************************************************
764 : !> \brief Build the kernel of a gaussian function
765 : !> for interpolating scaling functions.
766 : !> Do the parallel HalFFT of the symmetrized function and stores into
767 : !> memory only 1/8 of the grid divided by the number of processes nproc
768 : !>
769 : !> Build the kernel (karray) of a gaussian function
770 : !> for interpolating scaling functions
771 : !> $$ K(j) = \sum_k \omega_k \int \int \phi(x) g_k(x'-x) \delta(x'- j) dx dx' $$
772 : !> \param n01 Mesh dimensions of the density
773 : !> \param n02 Mesh dimensions of the density
774 : !> \param n03 Mesh dimensions of the density
775 : !> \param nfft1 Dimensions of the FFT grid (HalFFT in the third direction)
776 : !> \param nfft2 Dimensions of the FFT grid (HalFFT in the third direction)
777 : !> \param nfft3 Dimensions of the FFT grid (HalFFT in the third direction)
778 : !> \param n1k Dimensions of the kernel FFT
779 : !> \param n2k Dimensions of the kernel FFT
780 : !> \param n3k Dimensions of the kernel FFT
781 : !> \param hgrid Mesh step
782 : !> \param itype_scf Order of the scaling function (8,14,16)
783 : !> \param iproc ...
784 : !> \param nproc ...
785 : !> \param karray ...
786 : !> \param mpi_group ...
787 : !> \date February 2006
788 : !> \author T. Deutsch, L. Genovese
789 : ! **************************************************************************************************
790 594 : SUBROUTINE Free_Kernel(n01, n02, n03, nfft1, nfft2, nfft3, n1k, n2k, n3k, &
791 594 : hgrid, itype_scf, iproc, nproc, karray, mpi_group)
792 :
793 : INTEGER, INTENT(in) :: n01, n02, n03, nfft1, nfft2, nfft3, n1k, &
794 : n2k, n3k
795 : REAL(KIND=dp), INTENT(in) :: hgrid
796 : INTEGER, INTENT(in) :: itype_scf, iproc, nproc
797 : REAL(KIND=dp), DIMENSION(n1k, n2k, n3k/nproc), &
798 : INTENT(out) :: karray
799 : TYPE(mp_comm_type), INTENT(in) :: mpi_group
800 :
801 : INTEGER, PARAMETER :: n_gauss = 89, n_points = 2**6
802 : REAL(KIND=dp), PARAMETER :: p0_ref = 1._dp
803 :
804 : INTEGER :: i, i01, i02, i03, i1, i2, i3, i_gauss, &
805 : i_kern, iend, istart, istart1, n1h, &
806 : n2h, n3h, n_cell, n_iter, n_range, &
807 : n_scf, nker1, nker2, nker3
808 : REAL(KIND=dp) :: a1, a2, a3, a_range, absci, acc_gauss, &
809 : dr_gauss, dx, factor, factor2, kern, &
810 : p0_cell, p0gauss, pgauss, ur_gauss
811 594 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: kern_1_scf, kernel_scf, x_scf, y_scf
812 594 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: kp
813 : REAL(KIND=dp), DIMENSION(n_gauss) :: p_gauss, w_gauss
814 :
815 : !Do not touch !!!!
816 : !Better if higher (1024 points are enough 10^{-14}: 2*itype_scf*n_points)
817 : !Better p_gauss for calculation
818 : !(the support of the exponential should be inside [-n_range/2,n_range/2])
819 : !Number of integration points : 2*itype_scf*n_points
820 :
821 594 : n_scf = 2*itype_scf*n_points
822 : !Set karray
823 51582166 : karray = 0.0_dp
824 : !here we must set the dimensions for the fft part, starting from the nfft
825 : !remember that actually nfft2 is associated to n03 and viceversa
826 :
827 : !dimensions that define the center of symmetry
828 594 : n1h = nfft1/2
829 594 : n2h = nfft2/2
830 594 : n3h = nfft3/2
831 :
832 : !Auxiliary dimensions only for building the FFT part
833 594 : nker1 = nfft1
834 594 : nker2 = nfft2
835 594 : nker3 = nfft3/2 + 1
836 :
837 : !adjusting the last two dimensions to be multiples of nproc
838 0 : DO
839 594 : IF (MODULO(nker2, nproc) == 0) EXIT
840 0 : nker2 = nker2 + 1
841 : END DO
842 430 : DO
843 1024 : IF (MODULO(nker3, nproc) == 0) EXIT
844 430 : nker3 = nker3 + 1
845 : END DO
846 :
847 : !this will be the array of the kernel in the real space
848 3564 : ALLOCATE (kp(n1h + 1, n3h + 1, nker2/nproc))
849 :
850 : !defining proper extremes for the calculation of the
851 : !local part of the kernel
852 :
853 594 : istart = iproc*nker2/nproc + 1
854 594 : iend = MIN((iproc + 1)*nker2/nproc, n2h + n03)
855 :
856 594 : istart1 = istart
857 594 : IF (iproc == 0) istart1 = n2h - n03 + 2
858 :
859 : !Allocations
860 1782 : ALLOCATE (x_scf(0:n_scf))
861 1188 : ALLOCATE (y_scf(0:n_scf))
862 :
863 : !Build the scaling function
864 594 : CALL scaling_function(itype_scf, n_scf, n_range, x_scf, y_scf)
865 : !Step grid for the integration
866 594 : dx = REAL(n_range, KIND=dp)/REAL(n_scf, KIND=dp)
867 : !Extend the range (no more calculations because fill in by 0._dp)
868 594 : n_cell = MAX(n01, n02, n03)
869 594 : n_range = MAX(n_cell, n_range)
870 :
871 : !Allocations
872 1782 : ALLOCATE (kernel_scf(-n_range:n_range))
873 1188 : ALLOCATE (kern_1_scf(-n_range:n_range))
874 :
875 : !Lengthes of the box (use FFT dimension)
876 594 : a1 = hgrid*REAL(n01, KIND=dp)
877 594 : a2 = hgrid*REAL(n02, KIND=dp)
878 594 : a3 = hgrid*REAL(n03, KIND=dp)
879 :
880 3029156 : x_scf(:) = hgrid*x_scf(:)
881 3029156 : y_scf(:) = 1._dp/hgrid*y_scf(:)
882 594 : dx = hgrid*dx
883 : !To have a correct integration
884 594 : p0_cell = p0_ref/(hgrid*hgrid)
885 :
886 : !Initialization of the gaussian (Beylkin)
887 594 : CALL gequad(p_gauss, w_gauss, ur_gauss, dr_gauss, acc_gauss)
888 : !In order to have a range from a_range=sqrt(a1*a1+a2*a2+a3*a3)
889 : !(biggest length in the cube)
890 : !We divide the p_gauss by a_range**2 and a_gauss by a_range
891 594 : a_range = SQRT(a1*a1 + a2*a2 + a3*a3)
892 594 : factor = 1._dp/a_range
893 : !factor2 = factor*factor
894 594 : factor2 = 1._dp/(a1*a1 + a2*a2 + a3*a3)
895 53460 : DO i_gauss = 1, n_gauss
896 53460 : p_gauss(i_gauss) = factor2*p_gauss(i_gauss)
897 : END DO
898 53460 : DO i_gauss = 1, n_gauss
899 53460 : w_gauss(i_gauss) = factor*w_gauss(i_gauss)
900 : END DO
901 :
902 594 : kp(:, :, :) = 0._dp
903 : !Use in this order (better for accuracy).
904 53460 : loop_gauss: DO i_gauss = n_gauss, 1, -1
905 : !Gaussian
906 52866 : pgauss = p_gauss(i_gauss)
907 :
908 : !We calculate the number of iterations to go from pgauss to p0_ref
909 52866 : n_iter = NINT((LOG(pgauss) - LOG(p0_cell))/LOG(4._dp))
910 52866 : IF (n_iter <= 0) THEN
911 11448 : n_iter = 0
912 11448 : p0gauss = pgauss
913 : ELSE
914 41418 : p0gauss = pgauss/4._dp**n_iter
915 : END IF
916 :
917 : !Stupid integration
918 : !Do the integration with the exponential centered in i_kern
919 52866 : kernel_scf(:) = 0._dp
920 1677130 : DO i_kern = 0, n_range
921 : kern = 0._dp
922 8540366120 : DO i = 0, n_scf
923 8538693780 : absci = x_scf(i) - REAL(i_kern, KIND=dp)*hgrid
924 8538693780 : absci = absci*absci
925 8540366120 : kern = kern + y_scf(i)*EXP(-p0gauss*absci)*dx
926 : END DO
927 1672340 : kernel_scf(i_kern) = kern
928 1672340 : kernel_scf(-i_kern) = kern
929 1677130 : IF (ABS(kern) < 1.e-18_dp) THEN
930 : !Too small not useful to calculate
931 : EXIT
932 : END IF
933 : END DO
934 :
935 : !Start the iteration to go from p0gauss to pgauss
936 52866 : CALL scf_recursion(itype_scf, n_iter, n_range, kernel_scf, kern_1_scf)
937 :
938 : !Add to the kernel (only the local part)
939 :
940 2899235 : DO i3 = istart1, iend
941 2845775 : i03 = i3 - n2h - 1
942 : ! Crash if index out of range
943 : ! Without compiler bounds checking, the calculation might run successfully but
944 : ! it is also possible that the Hartree energy will blow up
945 : ! This seems to happen with large MPI processor counts if the size of the
946 : ! RS grid is not directly compatible with the allowed FFT dimensions
947 2845775 : IF (i03 < -n_range .OR. i03 > n_range) THEN
948 : CALL cp_abort(__LOCATION__, "Index out of range in wavelet solver. "// &
949 : "Try decreasing the number of MPI processors, or adjust the PW_CUTOFF or cell size "// &
950 : "so that 2*(number of RS grid points) matches the allowed FFT dimensions "// &
951 0 : "(see ps_wavelet_fft3d.F) exactly.")
952 : END IF
953 144938102 : DO i2 = 1, n02
954 142039461 : i02 = i2 - 1
955 8260627115 : DO i1 = 1, n01
956 8115741879 : i01 = i1 - 1
957 : kp(i1, i2, i3 - istart + 1) = kp(i1, i2, i3 - istart + 1) + w_gauss(i_gauss)* &
958 8257781340 : kernel_scf(i01)*kernel_scf(i02)*kernel_scf(i03)
959 : END DO
960 : END DO
961 : END DO
962 :
963 : END DO loop_gauss
964 :
965 : !De-allocations
966 594 : DEALLOCATE (kernel_scf)
967 594 : DEALLOCATE (kern_1_scf)
968 594 : DEALLOCATE (x_scf)
969 594 : DEALLOCATE (y_scf)
970 :
971 : !!!!END KERNEL CONSTRUCTION
972 :
973 : !!$ if(iproc .eq. 0) print *,"Do a 3D PHalFFT for the kernel"
974 :
975 : CALL kernelfft(nfft1, nfft2, nfft3, nker1, nker2, nker3, n1k, n2k, n3k, nproc, iproc, &
976 594 : kp, karray, mpi_group)
977 :
978 : !De-allocations
979 594 : DEALLOCATE (kp)
980 :
981 1188 : END SUBROUTINE Free_Kernel
982 :
983 : ! **************************************************************************************************
984 : !> \brief ...
985 : !> \param n1 ...
986 : !> \param n3 ...
987 : !> \param lot ...
988 : !> \param nfft ...
989 : !> \param i1 ...
990 : !> \param zf ...
991 : !> \param zw ...
992 : ! **************************************************************************************************
993 105278 : PURE SUBROUTINE inserthalf(n1, n3, lot, nfft, i1, zf, zw)
994 : INTEGER, INTENT(in) :: n1, n3, lot, nfft, i1
995 : REAL(KIND=dp), DIMENSION(n1/2+1, n3/2+1), &
996 : INTENT(in) :: zf
997 : COMPLEX(KIND=dp), DIMENSION(lot, n3/2), &
998 : INTENT(out) :: zw
999 :
1000 : INTEGER :: i01, i03i, i03r, i3, l1, l3
1001 :
1002 219437566 : zw = 0.0_dp
1003 105278 : i3 = 0
1004 6936294 : DO l3 = 1, n3, 2
1005 6831016 : i3 = i3 + 1
1006 6831016 : i03r = ABS(l3 - n3/2 - 1) + 1
1007 6831016 : i03i = ABS(l3 - n3/2) + 1
1008 197071030 : DO l1 = 1, nfft
1009 190134736 : i01 = ABS(l1 - 1 + i1 - n1/2 - 1) + 1
1010 196965752 : zw(l1, i3) = CMPLX(zf(i01, i03r), zf(i01, i03i), dp)
1011 : END DO
1012 : END DO
1013 :
1014 105278 : END SUBROUTINE inserthalf
1015 :
1016 : ! **************************************************************************************************
1017 : !> \brief (Based on suitable modifications of S.Goedecker routines)
1018 : !> Calculates the FFT of the distributed kernel
1019 : !> \param n1 logical dimension of the transform.
1020 : !> \param n2 logical dimension of the transform.
1021 : !> \param n3 logical dimension of the transform.
1022 : !> \param nd1 Dimensions of work arrays
1023 : !> \param nd2 Dimensions of work arrays
1024 : !> \param nd3 Dimensions of work arrays
1025 : !> \param nk1 ...
1026 : !> \param nk2 ...
1027 : !> \param nk3 ...
1028 : !> \param nproc number of processors used as returned by MPI_COMM_SIZE
1029 : !> \param iproc [0:nproc-1] number of processor as returned by MPI_COMM_RANK
1030 : !> \param zf Real kernel (input)
1031 : !> zf(i1,i2,i3)
1032 : !> \param zr Distributed Kernel FFT
1033 : !> zr(2,i1,i2,i3)
1034 : !> \param mpi_group ...
1035 : !> \date February 2006
1036 : !> \par Restrictions
1037 : !> Copyright (C) Stefan Goedecker, Cornell University, Ithaca, USA, 1994
1038 : !> Copyright (C) Stefan Goedecker, MPI Stuttgart, Germany, 1999
1039 : !> Copyright (C) 2002 Stefan Goedecker, CEA Grenoble
1040 : !> This file is distributed under the terms of the
1041 : !> GNU General Public License, see http://www.gnu.org/copyleft/gpl.txt .
1042 : !> \author S. Goedecker, L. Genovese
1043 : ! **************************************************************************************************
1044 594 : SUBROUTINE kernelfft(n1, n2, n3, nd1, nd2, nd3, nk1, nk2, nk3, nproc, iproc, zf, zr, mpi_group)
1045 :
1046 : INTEGER, INTENT(in) :: n1, n2, n3, nd1, nd2, nd3, nk1, nk2, &
1047 : nk3, nproc, iproc
1048 : REAL(KIND=dp), &
1049 : DIMENSION(n1/2+1, n3/2+1, nd2/nproc), &
1050 : INTENT(in) :: zf
1051 : REAL(KIND=dp), DIMENSION(nk1, nk2, nk3/nproc), &
1052 : INTENT(inout) :: zr
1053 : TYPE(mp_comm_type), INTENT(in) :: mpi_group
1054 :
1055 : INTEGER, PARAMETER :: ncache_optimal = 8*1024
1056 :
1057 : COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: zmpi2
1058 : COMPLEX(KIND=dp), ALLOCATABLE, &
1059 594 : DIMENSION(:, :, :, :) :: zmpi1
1060 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:), &
1061 594 : POINTER :: zw1, zw2
1062 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
1063 594 : POINTER :: zt
1064 : INTEGER :: final_chunk_size1, final_chunk_size2, final_chunk_size3, i1, i3, j, j2, J2st, j3, &
1065 : Jp2st, lot1, lot2, lot3, lzt, ma, mb, ncache, nfft, stat
1066 : REAL(kind=dp) :: twopion
1067 594 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: cosinarr
1068 : TYPE(fft_plan_type) :: fft_plan_bw1, fft_plan_bw1_last, &
1069 : fft_plan_bw2, fft_plan_bw2_last, &
1070 : fft_plan_bw3, fft_plan_bw3_last
1071 :
1072 : !work arrays for transpositions
1073 : !work arrays for MPI
1074 : !cache work array
1075 : !FFT work arrays
1076 : !Body
1077 : !check input
1078 :
1079 0 : CPASSERT(nd1 >= n1)
1080 594 : CPASSERT(nd2 >= n2)
1081 594 : CPASSERT(nd3 >= n3/2 + 1)
1082 594 : CPASSERT(MOD(nd3, nproc) == 0)
1083 594 : CPASSERT(MOD(nd2, nproc) == 0)
1084 : MARK_USED(nd1)
1085 :
1086 : !defining work arrays dimensions
1087 594 : ncache = ncache_optimal
1088 594 : IF (ncache <= MAX(n1, n2, n3/2)*4) ncache = MAX(n1, n2, n3/2)*4
1089 594 : lzt = n2
1090 594 : IF (MOD(n2, 2) == 0) lzt = lzt + 1
1091 :
1092 : !Allocations
1093 1188 : CALL fft_alloc(zw1, [ncache/4])
1094 594 : zw1 = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
1095 1188 : CALL fft_alloc(zw2, [ncache/4])
1096 594 : zw2 = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
1097 1782 : CALL fft_alloc(zt, [lzt, n1])
1098 594 : zt = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
1099 2970 : ALLOCATE (zmpi2(n1, nd2/nproc, nd3), SOURCE=CMPLX(0.0_dp, 0.0_dp, dp))
1100 2376 : ALLOCATE (cosinarr(2, n3/2))
1101 2744 : IF (nproc > 1) ALLOCATE (zmpi1(n1, nd2/nproc, nd3/nproc, nproc), SOURCE=CMPLX(0.0_dp, 0.0_dp, dp))
1102 :
1103 : !Calculating array of phases for HalFFT decoding
1104 594 : twopion = 8._dp*ATAN(1._dp)/REAL(n3, KIND=dp)
1105 28362 : DO i3 = 1, n3/2
1106 27768 : cosinarr(1, i3) = COS(twopion*(i3 - 1))
1107 28362 : cosinarr(2, i3) = -SIN(twopion*(i3 - 1))
1108 : END DO
1109 :
1110 : !transform along z axis
1111 :
1112 594 : lot1 = ncache/(4*n1)
1113 594 : lot2 = ncache/(4*n2)
1114 594 : lot3 = ncache/(2*n3)
1115 :
1116 : ! The size of the last chunk
1117 594 : final_chunk_size1 = MOD(n2, lot1)
1118 594 : final_chunk_size2 = MOD(nk1, lot2)
1119 594 : final_chunk_size3 = MOD(n1, lot3)
1120 :
1121 : ! Prevent OOB-access if n2 < lot1
1122 594 : IF (n2 >= lot1) THEN
1123 546 : CALL fft_create_plan_1d(fft_plan_bw1, BWFFT, .TRUE., .TRUE., lot1, lzt, n1, lot1, zw1, zt)
1124 : END IF
1125 594 : IF (final_chunk_size1 > 0) THEN
1126 : CALL fft_create_plan_1d(fft_plan_bw1_last, BWFFT, .TRUE., .TRUE., lot1, lzt, n1, &
1127 460 : final_chunk_size1, zw1, zt)
1128 : END IF
1129 :
1130 : ! Prevent OOB-access if n2 < lot1
1131 594 : IF (nk1 >= lot2) THEN
1132 494 : CALL fft_create_plan_1d(fft_plan_bw2, BWFFT, .TRUE., .TRUE., lot2, lot2, n2, lot2, zw1, zw2)
1133 : END IF
1134 594 : IF (final_chunk_size2 > 0) THEN
1135 : CALL fft_create_plan_1d(fft_plan_bw2_last, BWFFT, .TRUE., .TRUE., lot2, lot2, n2, &
1136 594 : final_chunk_size2, zw1, zw2)
1137 : END IF
1138 :
1139 : ! Prevent OOB-access if n1 < lot3
1140 594 : IF (n1 >= lot3) THEN
1141 494 : CALL fft_create_plan_1d(fft_plan_bw3, BWFFT, .TRUE., .TRUE., lot3, lot3, n3/2, lot3, zw1, zw2)
1142 : END IF
1143 594 : IF (final_chunk_size3 > 0) THEN
1144 : CALL fft_create_plan_1d(fft_plan_bw3_last, BWFFT, .TRUE., .TRUE., &
1145 506 : lot3, lot3, n3/2, final_chunk_size3, zw1, zw2)
1146 : END IF
1147 :
1148 33104 : DO j2 = 1, nd2/nproc
1149 : !this condition ensures that we manage only the interesting part for the FFT
1150 33104 : IF (iproc*(nd2/nproc) + j2 <= n2) THEN
1151 137788 : DO i1 = 1, n1, lot3
1152 105278 : ma = i1
1153 105278 : mb = MIN(i1 + (lot3 - 1), n1)
1154 105278 : nfft = mb - ma + 1
1155 :
1156 : !inserting real data into complex array of half length
1157 : !input: I1,I3,J2,(Jp2)
1158 :
1159 105278 : CALL inserthalf(n1, n3, lot3, nfft, i1, zf(1, 1, j2), zw1)
1160 :
1161 : !performing FFT
1162 : ! This is equivalent to
1163 105278 : IF (nfft == lot3) THEN
1164 79016 : CALL fft_1d(fft_plan_bw3, zw1, zw2, 1.0_dp, stat)
1165 : ELSE
1166 26262 : CALL fft_1d(fft_plan_bw3_last, zw1, zw2, 1.0_dp, stat)
1167 : END IF
1168 : !output: I1,i3,J2,(Jp2)
1169 :
1170 : !unpacking FFT in order to restore correct result,
1171 : !while exchanging components
1172 : !input: I1,i3,J2,(Jp2)
1173 137788 : CALL scramble_unpack(i1, j2, lot3, nfft, n1, n3, nd2, nproc, nd3, zw2, zmpi2, cosinarr)
1174 : !output: I1,J2,i3,(Jp2)
1175 : END DO
1176 : END IF
1177 : END DO
1178 :
1179 : !Interprocessor data transposition
1180 : !input: I1,J2,j3,jp3,(Jp2)
1181 594 : IF (nproc > 1) THEN
1182 : !communication scheduling
1183 430 : CALL mpi_group%alltoall(zmpi2, zmpi1, n1*(nd2/nproc)*(nd3/nproc))
1184 : ! output: I1,J2,j3,Jp2,(jp3)
1185 : END IF
1186 :
1187 17778 : DO j3 = 1, nd3/nproc
1188 : !this condition ensures that we manage only the interesting part for the FFT
1189 17778 : IF (iproc*(nd3/nproc) + j3 <= n3/2 + 1) THEN
1190 16969 : Jp2st = 1
1191 16969 : J2st = 1
1192 :
1193 : !transform along x axis
1194 :
1195 123225 : DO j = 1, n2, lot1
1196 106256 : ma = j
1197 106256 : mb = MIN(j + (lot1 - 1), n2)
1198 106256 : nfft = mb - ma + 1
1199 :
1200 : !reverse ordering
1201 : !input: I1,J2,j3,Jp2,(jp3)
1202 106256 : IF (nproc == 1) THEN
1203 19380 : CALL mpiswitch(j3, nfft, Jp2st, J2st, lot1, n1, nd2, nd3, nproc, zmpi2, zw1)
1204 : ELSE
1205 86876 : CALL mpiswitch(j3, nfft, Jp2st, J2st, lot1, n1, nd2, nd3, nproc, zmpi1, zw1)
1206 : END IF
1207 : !output: J2,Jp2,I1,j3,(jp3)
1208 :
1209 : !performing FFT
1210 : !input: I2,I1,j3,(jp3)
1211 : ! This is equivalent to
1212 123225 : IF (nfft == lot1) THEN
1213 93466 : CALL fft_1d(fft_plan_bw1, zw1, zt(j:, 1), 1.0_dp, stat)
1214 : ELSE
1215 12790 : CALL fft_1d(fft_plan_bw1_last, zw1, zt(j:, 1), 1.0_dp, stat)
1216 : END IF
1217 : !output: I2,i1,j3,(jp3)
1218 : END DO
1219 :
1220 : !transform along y axis, and taking only the first half
1221 :
1222 75847 : DO j = 1, nk1, lot2
1223 58878 : ma = j
1224 58878 : mb = MIN(j + (lot2 - 1), nk1)
1225 58878 : nfft = mb - ma + 1
1226 :
1227 : !reverse ordering
1228 : !input: I2,i1,j3,(jp3)
1229 58878 : CALL switch(nfft, n2, lot2, n1, lzt, zt(:, j), zw1)
1230 : !output: i1,I2,j3,(jp3)
1231 :
1232 : !performing FFT
1233 : !input: i1,I2,j3,(jp3)
1234 : ! This is equivalent to
1235 58878 : IF (nfft == lot2) THEN
1236 41909 : CALL fft_1d(fft_plan_bw2, zw1, zw2, 1.0_dp, stat)
1237 : ELSE
1238 16969 : CALL fft_1d(fft_plan_bw2_last, zw1, zw2, 1.0_dp, stat)
1239 : END IF
1240 :
1241 75847 : CALL realcopy(lot2, nfft, n2, nk1, nk2, zw2, zr(j, 1, j3))
1242 :
1243 : END DO
1244 : !output: i1,i2,j3,(jp3)
1245 : END IF
1246 : END DO
1247 :
1248 594 : IF (n2 >= lot1) CALL fft_destroy_plan(fft_plan_bw1)
1249 594 : IF (final_chunk_size1 > 0) CALL fft_destroy_plan(fft_plan_bw1_last)
1250 :
1251 594 : IF (nk1 >= lot2) CALL fft_destroy_plan(fft_plan_bw2)
1252 594 : IF (final_chunk_size2 > 0) CALL fft_destroy_plan(fft_plan_bw2_last)
1253 :
1254 594 : IF (n1 >= lot3) CALL fft_destroy_plan(fft_plan_bw3)
1255 594 : IF (final_chunk_size3 > 0) CALL fft_destroy_plan(fft_plan_bw3_last)
1256 :
1257 : !De-allocations
1258 594 : DEALLOCATE (zmpi2)
1259 594 : CALL fft_dealloc(zw1)
1260 594 : CALL fft_dealloc(zw2)
1261 594 : CALL fft_dealloc(zt)
1262 594 : DEALLOCATE (cosinarr)
1263 594 : IF (nproc > 1) DEALLOCATE (zmpi1)
1264 :
1265 11880 : END SUBROUTINE kernelfft
1266 :
1267 : ! **************************************************************************************************
1268 : !> \brief ...
1269 : !> \param lot ...
1270 : !> \param nfft ...
1271 : !> \param n2 ...
1272 : !> \param nk1 ...
1273 : !> \param nk2 ...
1274 : !> \param zin ...
1275 : !> \param zout ...
1276 : ! **************************************************************************************************
1277 58878 : PURE SUBROUTINE realcopy(lot, nfft, n2, nk1, nk2, zin, zout)
1278 : INTEGER, INTENT(in) :: lot, nfft, n2, nk1, nk2
1279 : COMPLEX(KIND=dp), DIMENSION(lot, n2), INTENT(in) :: zin
1280 : REAL(KIND=dp), DIMENSION(nk1, nk2), INTENT(inout) :: zout
1281 :
1282 : INTEGER :: i, j
1283 :
1284 3811107 : DO i = 1, nk2
1285 53863483 : DO j = 1, nfft
1286 53804605 : zout(j, i) = REAL(zin(j, i), dp)
1287 : END DO
1288 : END DO
1289 :
1290 58878 : END SUBROUTINE realcopy
1291 :
1292 : ! **************************************************************************************************
1293 : !> \brief ...
1294 : !> \param nfft ...
1295 : !> \param n2 ...
1296 : !> \param lot ...
1297 : !> \param n1 ...
1298 : !> \param lzt ...
1299 : !> \param zt ...
1300 : !> \param zw ...
1301 : ! **************************************************************************************************
1302 58878 : PURE SUBROUTINE switch(nfft, n2, lot, n1, lzt, zt, zw)
1303 : INTEGER, INTENT(IN) :: nfft, n2, lot, n1, lzt
1304 : COMPLEX(KIND=dp), INTENT(IN) :: zt(lzt, n1)
1305 : COMPLEX(KIND=dp), INTENT(INOUT) :: zw(lot, n2)
1306 :
1307 : INTEGER :: i, j
1308 :
1309 921046 : DO j = 1, nfft
1310 99301462 : DO i = 1, n2
1311 99242584 : zw(j, i) = zt(i, j)
1312 : END DO
1313 : END DO
1314 58878 : END SUBROUTINE switch
1315 :
1316 : ! **************************************************************************************************
1317 : !> \brief ...
1318 : !> \param j3 ...
1319 : !> \param nfft ...
1320 : !> \param Jp2st ...
1321 : !> \param J2st ...
1322 : !> \param lot ...
1323 : !> \param n1 ...
1324 : !> \param nd2 ...
1325 : !> \param nd3 ...
1326 : !> \param nproc ...
1327 : !> \param zmpi1 ...
1328 : !> \param zw ...
1329 : ! **************************************************************************************************
1330 106256 : PURE SUBROUTINE mpiswitch(j3, nfft, Jp2st, J2st, lot, n1, nd2, nd3, nproc, zmpi1, zw)
1331 : INTEGER, INTENT(IN) :: j3, nfft
1332 : INTEGER, INTENT(INOUT) :: Jp2st, J2st
1333 : INTEGER, INTENT(IN) :: lot, n1, nd2, nd3, nproc
1334 : COMPLEX(KIND=dp), INTENT(IN) :: zmpi1(n1, nd2/nproc, nd3/nproc, nproc)
1335 : COMPLEX(KIND=dp), INTENT(INOUT) :: zw(lot, n1)
1336 :
1337 : INTEGER :: I1, J2, JP2, mfft
1338 :
1339 106256 : mfft = 0
1340 134618 : DO Jp2 = Jp2st, nproc
1341 1808047 : DO J2 = J2st, nd2/nproc
1342 1779685 : mfft = mfft + 1
1343 1779685 : IF (mfft > nfft) THEN
1344 89287 : Jp2st = Jp2
1345 89287 : J2st = J2
1346 89287 : RETURN
1347 : END IF
1348 195098796 : DO I1 = 1, n1
1349 195070434 : zw(mfft, I1) = zmpi1(I1, J2, j3, Jp2)
1350 : END DO
1351 : END DO
1352 45331 : J2st = 1
1353 : END DO
1354 : END SUBROUTINE mpiswitch
1355 :
1356 : ! **************************************************************************************************
1357 : !> \brief ...
1358 : !> \param p ...
1359 : !> \param w ...
1360 : !> \param urange ...
1361 : !> \param drange ...
1362 : !> \param acc ...
1363 : ! **************************************************************************************************
1364 594 : PURE SUBROUTINE gequad(p, w, urange, drange, acc)
1365 : !
1366 : REAL(KIND=dp), INTENT(OUT) :: p(89), w(89), urange, drange, acc
1367 :
1368 : !
1369 : !
1370 : ! range [10^(-9),1] and accuracy ~10^(-8);
1371 : !
1372 : !
1373 :
1374 594 : p(1) = 4.96142640560223544e19_dp
1375 594 : p(2) = 1.37454269147978052e19_dp
1376 594 : p(3) = 7.58610013441204679e18_dp
1377 594 : p(4) = 4.42040691347806996e18_dp
1378 594 : p(5) = 2.61986077948367892e18_dp
1379 594 : p(6) = 1.56320138155496681e18_dp
1380 594 : p(7) = 9.35645215863028402e17_dp
1381 594 : p(8) = 5.60962910452691703e17_dp
1382 594 : p(9) = 3.3666225119686761e17_dp
1383 594 : p(10) = 2.0218253197947866e17_dp
1384 594 : p(11) = 1.21477756091902017e17_dp
1385 594 : p(12) = 7.3012982513608503e16_dp
1386 594 : p(13) = 4.38951893556421099e16_dp
1387 594 : p(14) = 2.63949482512262325e16_dp
1388 594 : p(15) = 1.58742054072786174e16_dp
1389 594 : p(16) = 9.54806587737665531e15_dp
1390 594 : p(17) = 5.74353712364571709e15_dp
1391 594 : p(18) = 3.455214877389445e15_dp
1392 594 : p(19) = 2.07871658520326804e15_dp
1393 594 : p(20) = 1.25064667315629928e15_dp
1394 594 : p(21) = 7.52469429541933745e14_dp
1395 594 : p(22) = 4.5274603337253175e14_dp
1396 594 : p(23) = 2.72414006900059548e14_dp
1397 594 : p(24) = 1.63912168349216752e14_dp
1398 594 : p(25) = 9.86275802590865738e13_dp
1399 594 : p(26) = 5.93457701624974985e13_dp
1400 594 : p(27) = 3.5709554322296296e13_dp
1401 594 : p(28) = 2.14872890367310454e13_dp
1402 594 : p(29) = 1.29294719957726902e13_dp
1403 594 : p(30) = 7.78003375426361016e12_dp
1404 594 : p(31) = 4.68148199759876704e12_dp
1405 594 : p(32) = 2.8169955024829868e12_dp
1406 594 : p(33) = 1.69507790481958464e12_dp
1407 594 : p(34) = 1.01998486064607581e12_dp
1408 594 : p(35) = 6.13759486539856459e11_dp
1409 594 : p(36) = 3.69320183828682544e11_dp
1410 594 : p(37) = 2.22232783898905102e11_dp
1411 594 : p(38) = 1.33725247623668682e11_dp
1412 594 : p(39) = 8.0467192739036288e10_dp
1413 594 : p(40) = 4.84199582415144143e10_dp
1414 594 : p(41) = 2.91360091170559564e10_dp
1415 594 : p(42) = 1.75321747475309216e10_dp
1416 594 : p(43) = 1.0549735552210995e10_dp
1417 594 : p(44) = 6.34815321079006586e9_dp
1418 594 : p(45) = 3.81991113733594231e9_dp
1419 594 : p(46) = 2.29857747533101109e9_dp
1420 594 : p(47) = 1.38313653595483694e9_dp
1421 594 : p(48) = 8.32282908580025358e8_dp
1422 594 : p(49) = 5.00814519374587467e8_dp
1423 594 : p(50) = 3.01358090773319025e8_dp
1424 594 : p(51) = 1.81337994217503535e8_dp
1425 594 : p(52) = 1.09117589961086823e8_dp
1426 594 : p(53) = 6.56599771718640323e7_dp
1427 594 : p(54) = 3.95099693638497164e7_dp
1428 594 : p(55) = 2.37745694710665991e7_dp
1429 594 : p(56) = 1.43060135285912813e7_dp
1430 594 : p(57) = 8.60844290313506695e6_dp
1431 594 : p(58) = 5.18000974075383424e6_dp
1432 594 : p(59) = 3.116998193057466e6_dp
1433 594 : p(60) = 1.87560993870024029e6_dp
1434 594 : p(61) = 1.12862197183979562e6_dp
1435 594 : p(62) = 679132.441326077231_dp
1436 594 : p(63) = 408658.421279877969_dp
1437 594 : p(64) = 245904.473450669789_dp
1438 594 : p(65) = 147969.568088321005_dp
1439 594 : p(66) = 89038.612357311147_dp
1440 594 : p(67) = 53577.7362552358895_dp
1441 594 : p(68) = 32239.6513926914668_dp
1442 594 : p(69) = 19399.7580852362791_dp
1443 594 : p(70) = 11673.5323603058634_dp
1444 594 : p(71) = 7024.38438577707758_dp
1445 594 : p(72) = 4226.82479307685999_dp
1446 594 : p(73) = 2543.43254175354295_dp
1447 594 : p(74) = 1530.47486269122675_dp
1448 594 : p(75) = 920.941785160749482_dp
1449 594 : p(76) = 554.163803906291646_dp
1450 594 : p(77) = 333.46029740785694_dp
1451 594 : p(78) = 200.6550575335041_dp
1452 594 : p(79) = 120.741366914147284_dp
1453 594 : p(80) = 72.6544243200329916_dp
1454 594 : p(81) = 43.7187810415471025_dp
1455 594 : p(82) = 26.3071631447061043_dp
1456 594 : p(83) = 15.8299486353816329_dp
1457 594 : p(84) = 9.52493152341244004_dp
1458 594 : p(85) = 5.72200417067776041_dp
1459 594 : p(86) = 3.36242234070940928_dp
1460 594 : p(87) = 1.75371394604499472_dp
1461 594 : p(88) = 0.64705932650658966_dp
1462 594 : p(89) = 0.072765905943708247_dp
1463 : !
1464 594 : w(1) = 47.67445484528304247e10_dp
1465 594 : w(2) = 11.37485774750442175e9_dp
1466 594 : w(3) = 78.64340976880190239e8_dp
1467 594 : w(4) = 46.27335788759590498e8_dp
1468 594 : w(5) = 24.7380464827152951e8_dp
1469 594 : w(6) = 13.62904116438987719e8_dp
1470 594 : w(7) = 92.79560029045882433e8_dp
1471 594 : w(8) = 52.15931216254660251e8_dp
1472 594 : w(9) = 31.67018011061666244e8_dp
1473 594 : w(10) = 1.29291036801493046e8_dp
1474 594 : w(11) = 1.00139319988015862e8_dp
1475 594 : w(12) = 7.75892350510188341e7_dp
1476 594 : w(13) = 6.01333567950731271e7_dp
1477 594 : w(14) = 4.66141178654796875e7_dp
1478 594 : w(15) = 3.61398903394911448e7_dp
1479 594 : w(16) = 2.80225846672956389e7_dp
1480 594 : w(17) = 2.1730509180930247e7_dp
1481 594 : w(18) = 1.68524482625876965e7_dp
1482 594 : w(19) = 1.30701489345870338e7_dp
1483 594 : w(20) = 1.01371784832269282e7_dp
1484 594 : w(21) = 7.86264116300379329e6_dp
1485 594 : w(22) = 6.09861667912273717e6_dp
1486 594 : w(23) = 4.73045784039455683e6_dp
1487 594 : w(24) = 3.66928949951594161e6_dp
1488 594 : w(25) = 2.8462050836230259e6_dp
1489 594 : w(26) = 2.20777394798527011e6_dp
1490 594 : w(27) = 1.71256191589205524e6_dp
1491 594 : w(28) = 1.32843556197737076e6_dp
1492 594 : w(29) = 1.0304731275955989e6_dp
1493 594 : w(30) = 799345.206572271448_dp
1494 594 : w(31) = 620059.354143595343_dp
1495 594 : w(32) = 480986.704107449333_dp
1496 594 : w(33) = 373107.167700228515_dp
1497 594 : w(34) = 289424.08337412132_dp
1498 594 : w(35) = 224510.248231581788_dp
1499 594 : w(36) = 174155.825690028966_dp
1500 594 : w(37) = 135095.256919654065_dp
1501 594 : w(38) = 104795.442776800312_dp
1502 594 : w(39) = 81291.4458222430418_dp
1503 594 : w(40) = 63059.0493649328682_dp
1504 594 : w(41) = 48915.9040455329689_dp
1505 594 : w(42) = 37944.8484018048756_dp
1506 594 : w(43) = 29434.4290473253969_dp
1507 594 : w(44) = 22832.7622054490044_dp
1508 594 : w(45) = 17711.743950151233_dp
1509 594 : w(46) = 13739.287867104177_dp
1510 594 : w(47) = 10657.7895710752585_dp
1511 594 : w(48) = 8267.42141053961834_dp
1512 594 : w(49) = 6413.17397520136448_dp
1513 594 : w(50) = 4974.80402838654277_dp
1514 594 : w(51) = 3859.03698188553047_dp
1515 594 : w(52) = 2993.51824493299154_dp
1516 594 : w(53) = 2322.1211966811754_dp
1517 594 : w(54) = 1801.30750964719641_dp
1518 594 : w(55) = 1397.30379659817038_dp
1519 594 : w(56) = 1083.91149143250697_dp
1520 594 : w(57) = 840.807939169209188_dp
1521 594 : w(58) = 652.228524366749422_dp
1522 594 : w(59) = 505.944376983506128_dp
1523 594 : w(60) = 392.469362317941064_dp
1524 594 : w(61) = 304.444930257324312_dp
1525 594 : w(62) = 236.162932842453601_dp
1526 594 : w(63) = 183.195466078603525_dp
1527 594 : w(64) = 142.107732186551471_dp
1528 594 : w(65) = 110.23530215723992_dp
1529 594 : w(66) = 85.5113346705382257_dp
1530 594 : w(67) = 66.3325469806696621_dp
1531 594 : w(68) = 51.4552463353841373_dp
1532 594 : w(69) = 39.9146798429449273_dp
1533 594 : w(70) = 30.9624728409162095_dp
1534 594 : w(71) = 24.018098812215013_dp
1535 594 : w(72) = 18.6312338024296588_dp
1536 594 : w(73) = 14.4525541233150501_dp
1537 594 : w(74) = 11.2110836519105938_dp
1538 594 : w(75) = 8.69662175848497178_dp
1539 594 : w(76) = 6.74611236165731961_dp
1540 594 : w(77) = 5.23307018057529994_dp
1541 594 : w(78) = 4.05937850501539556_dp
1542 594 : w(79) = 3.14892659076635714_dp
1543 594 : w(80) = 2.44267408211071604_dp
1544 594 : w(81) = 1.89482240522855261_dp
1545 594 : w(82) = 1.46984505907050079_dp
1546 594 : w(83) = 1.14019261330527007_dp
1547 594 : w(84) = 0.884791217422925293_dp
1548 594 : w(85) = 0.692686387080616483_dp
1549 594 : w(86) = 0.585244576897023282_dp
1550 594 : w(87) = 0.576182522545327589_dp
1551 594 : w(88) = 0.596688817388997178_dp
1552 594 : w(89) = 0.607879901151108771_dp
1553 : !
1554 : !
1555 594 : urange = 1._dp
1556 594 : drange = 1e-08_dp
1557 594 : acc = 1e-08_dp
1558 594 : END SUBROUTINE gequad
1559 :
1560 : END MODULE ps_wavelet_kernel
|