28#include "../base/base_uses.f90"
34 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'ps_wavelet_kernel'
83 SUBROUTINE createkernel(geocode, n01, n02, n03, hx, hy, hz, itype_scf, iproc, nproc, kernel, mpi_group)
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(:)
93 INTEGER :: m1, m2, m3, md1, md2, md3, n1, n2, n3, &
94 nd1, nd2, nd3, nlimd, nlimk
95 REAL(kind=
dp) :: hgrid
97 hgrid = max(hx, hy, hz)
99 IF (geocode ==
'P')
THEN
102 md1, md2, md3, nd1, nd2, nd3, nproc)
108 ELSE IF (geocode ==
'S')
THEN
111 md1, md2, md3, nd1, nd2, nd3, nproc)
113 ALLOCATE (kernel(nd1*nd2*nd3/nproc))
117 CALL surfaces_kernel(n1, n2, n3, m3, nd1, nd2, nd3, hx, hz, hy, &
118 itype_scf, kernel, iproc, nproc, mpi_group)
123 ELSE IF (geocode ==
'F')
THEN
128 md1, md2, md3, nd1, nd2, nd3, nproc)
129 ALLOCATE (kernel(nd1*nd2*nd3/nproc))
132 CALL free_kernel(n01, n02, n03, n1, n2, n3, nd1, nd2, nd3, hgrid, &
133 itype_scf, iproc, nproc, kernel, mpi_group)
141 cpabort(
"No wavelet based poisson solver for given geometry")
169 SUBROUTINE surfaces_kernel(n1, n2, n3, m3, nker1, nker2, nker3, h1, h2, h3, &
170 itype_scf, karray, iproc, nproc, mpi_group)
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
176 DIMENSION(nker1, nker2, nker3/nproc), &
177 INTENT(out) :: karray
180 INTEGER,
PARAMETER :: n_points = 2**6, ncache_optimal = 8*1024
182 COMPLEX(KIND=dp),
CONTIGUOUS,
DIMENSION(:), &
183 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, &
187 REAL(kind=
dp) :: a, b, c, cp, d, diff, dx, fei, fer, foi, &
188 for, fr, mu1, pion, ponx, pony,
sp, &
190 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: kernel_scf, x_scf, y_scf
191 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
205 cpol(1, 3) = 1._dp/3._dp
206 cpol(1, 4) = 7._dp/12._dp
207 cpol(2, 4) = 8._dp/3._dp
208 cpol(1, 5) = 19._dp/50._dp
209 cpol(2, 5) = 3._dp/2._dp
210 cpol(1, 6) = 41._dp/272._dp
211 cpol(2, 6) = 27._dp/34._dp
212 cpol(3, 6) = 27._dp/272._dp
213 cpol(1, 7) = 751._dp/2989._dp
214 cpol(2, 7) = 73._dp/61._dp
215 cpol(3, 7) = 27._dp/61._dp
216 cpol(1, 8) = -989._dp/4540._dp
217 cpol(2, 8) = -1472._dp/1135._dp
218 cpol(3, 8) = 232._dp/1135._dp
219 cpol(4, 8) = -2624._dp/1135._dp
222 cpol(1, 1) = .5_dp*cpol(1, 1)
223 cpol(1:2, 2) = 2._dp/3._dp*cpol(1:2, 2)
224 cpol(1:2, 3) = 3._dp/8._dp*cpol(1:2, 3)
225 cpol(1:3, 4) = 2._dp/15._dp*cpol(1:3, 4)
226 cpol(1:3, 5) = 25._dp/144._dp*cpol(1:3, 5)
227 cpol(1:4, 6) = 34._dp/105._dp*cpol(1:4, 6)
228 cpol(1:4, 7) = 2989._dp/17280._dp*cpol(1:4, 7)
229 cpol(1:5, 8) = -454._dp/2835._dp*cpol(1:5, 8)
232 cpol(2, 1) = cpol(1, 1)
233 cpol(3, 2) = cpol(1, 2)
234 cpol(3, 3) = cpol(2, 3)
235 cpol(4, 3) = cpol(1, 3)
236 cpol(4, 4) = cpol(2, 4)
237 cpol(5, 4) = cpol(1, 4)
238 cpol(4, 5) = cpol(3, 5)
239 cpol(5, 5) = cpol(2, 5)
240 cpol(6, 5) = cpol(1, 5)
241 cpol(5, 6) = cpol(3, 6)
242 cpol(6, 6) = cpol(2, 6)
243 cpol(7, 6) = cpol(1, 6)
244 cpol(5, 7) = cpol(4, 7)
245 cpol(6, 7) = cpol(3, 7)
246 cpol(7, 7) = cpol(2, 7)
247 cpol(8, 7) = cpol(1, 7)
248 cpol(6, 8) = cpol(4, 8)
249 cpol(7, 8) = cpol(3, 8)
250 cpol(8, 8) = cpol(2, 8)
251 cpol(9, 8) = cpol(1, 8)
254 n_scf = 2*itype_scf*n_points
256 ALLOCATE (x_scf(0:n_scf))
257 ALLOCATE (y_scf(0:n_scf))
262 dx = real(n_range, kind=
dp)/real(n_scf, kind=
dp)
265 n_range = max(n_cell, n_range)
268 ncache = ncache_optimal
271 IF (ncache <= (nker3 - 1)*4) ncache = nker3 - 1*4
276 IF (nproc*(nact2/nproc) /= nact2)
THEN
284 ALLOCATE (kernel(nker1, nact2/nproc, nker3))
285 ALLOCATE (kernel_mpi(nker1, nact2/nproc, nker3/nproc, nproc))
286 ALLOCATE (kernel_scf(n_range))
287 CALL fft_alloc(halfft_cache1, [max(ncache/4, n3/2)])
288 halfft_cache1 = cmplx(0.0_dp, 0.0_dp,
dp)
289 CALL fft_alloc(halfft_cache2, [max(ncache/4, n3/2)])
290 halfft_cache2 = cmplx(0.0_dp, 0.0_dp,
dp)
291 ALLOCATE (cossinarr(2, n3/2 - 1))
294 pion = 2._dp*
pi/real(n3, kind=
dp)
296 x = real(i3 - 1, kind=
dp)*pion
297 cossinarr(1, i3 - 1) = cos(x)
298 cossinarr(2, i3 - 1) = -sin(x)
303 kernel_mpi = huge(0._dp)
307 num_of_mus = max(1, ncache/(2*n3))
315 j2st = iproc*(nact2/nproc)
316 j2nd = min((iproc + 1)*(nact2/nproc), n2/2 + 1)
319 final_chunk_size = mod((n1/2 + 1)*(j2nd - j2st), num_of_mus)
322 IF ((n1/2 + 1)*(j2nd - j2st) >= num_of_mus)
THEN
324 n3/2, num_of_mus, halfft_cache1, halfft_cache2)
326 IF (final_chunk_size > 0)
THEN
328 n3/2, final_chunk_size, halfft_cache1, halfft_cache2)
331 DO ind2 = (n1/2 + 1)*j2st + 1, (n1/2 + 1)*j2nd, num_of_mus
333 iend = min(ind2 + (num_of_mus - 1), (n1/2 + 1)*j2nd)
334 nfft = iend - istart + 1
339 halfft_cache1 = cmplx(0.0_dp, 0.0_dp,
dp)
340 halfft_cache1 = cmplx(0.0_dp, 0.0_dp,
dp)
342 IF (istart == 1)
THEN
346 CALL calculates_green_opt_muzero(n_range, n_scf, ipolyord, x_scf, y_scf, &
347 cpol(1, ipolyord), dx, kernel_scf)
350 halfft_cache1(1) = cmplx(0._dp, aimag(halfft_cache1(1)),
dp)
354 value = 0.5_dp*h3*kernel_scf(i3)
356 CALL indices(ireim, num_of_mus, n3/2 + i3, 1, ind1)
358 CALL indices(jreim, num_of_mus, n3/2 + 2 - i3, 1, jnd1)
360 halfft_cache1(ind1) = cmplx(
value, aimag(halfft_cache1(ind1)),
dp)
362 halfft_cache1(ind1) = cmplx(real(halfft_cache1(ind1),
dp),
value,
dp)
365 halfft_cache1(jnd1) = cmplx(
value, aimag(halfft_cache1(jnd1)),
dp)
367 halfft_cache1(jnd1) = cmplx(real(halfft_cache1(jnd1),
dp),
value,
dp)
374 loopimpulses:
DO imu = istart + shift, iend
382 i1 = mod(imu, n1/2 + 1)
383 IF (i1 == 0) i1 = n1/2 + 1
384 i2 = (imu - i1)/(n1/2 + 1) + 1
385 ponx = real(i1 - 1, kind=
dp)/real(n1, kind=
dp)
386 pony = real(i2 - 1, kind=
dp)/real(n2, kind=
dp)
388 mu1 = 2._dp*
pi*sqrt((ponx/h1)**2 + (pony/h2)**2)*h3
390 CALL calculates_green_opt(n_range, n_scf, itype_scf, ipolyord, x_scf, y_scf, &
391 cpol(1, ipolyord), mu1, dx, kernel_scf)
396 halfft_cache1(imu - istart + 1) = cmplx(0._dp, aimag(halfft_cache1(imu - istart + 1)),
dp)
398 value = -0.5_dp*h3/mu1*kernel_scf(i3)
400 CALL indices(ireim, num_of_mus, n3/2 + i3, imu - istart + 1, ind1)
402 CALL indices(jreim, num_of_mus, n3/2 + 2 - i3, imu - istart + 1, jnd1)
404 halfft_cache1(ind1) = cmplx(
value, aimag(halfft_cache1(ind1)),
dp)
406 halfft_cache1(ind1) = cmplx(real(halfft_cache1(ind1),
dp),
value,
dp)
409 halfft_cache1(jnd1) = cmplx(
value, aimag(halfft_cache1(jnd1)),
dp)
411 halfft_cache1(jnd1) = cmplx(real(halfft_cache1(jnd1),
dp),
value,
dp)
419 IF (nfft == num_of_mus)
THEN
420 CALL fft_1d(fft_plan_bw, halfft_cache1, halfft_cache2, 1.0_dp, stat)
422 CALL fft_1d(fft_plan_bw_last, halfft_cache1, halfft_cache2, 1.0_dp, stat)
427 DO imu = istart, iend
430 i1 = mod(imu, n1/2 + 1)
431 IF (i1 == 0) i1 = n1/2 + 1
432 i2 = (imu - i1)/(n1/2 + 1) + 1
436 a = real(halfft_cache2(imu - istart + 1),
dp)
437 b = aimag(halfft_cache2(imu - istart + 1))
438 kernel(i1, j2, 1) = a + b
439 kernel(i1, j2, n3/2 + 1) = a - b
442 ind1 = imu - istart + 1 + num_of_mus*(i3 - 1)
443 jnd1 = imu - istart + 1 + num_of_mus*(n3/2 + 2 - i3 - 1)
444 cp = cossinarr(1, i3 - 1)
445 sp = cossinarr(2, i3 - 1)
446 a = real(halfft_cache2(ind1),
dp)
447 b = aimag(halfft_cache2(ind1))
448 c = real(halfft_cache2(jnd1),
dp)
449 d = aimag(halfft_cache2(jnd1))
454 fr = fer + cp*foi -
sp*
for
455 kernel(i1, j2, i3) = fr
461 IF ((n1/2 + 1)*(j2nd - j2st) >= num_of_mus)
CALL fft_destroy_plan(fft_plan_bw)
466 CALL mpi_group%alltoall(kernel, &
467 kernel_mpi, nker1*(nact2/nproc)*(nker3/nproc))
470 DO i3 = 1, nker3/nproc
471 DO i2 = 1, nact2/nproc
472 j2 = i2 + (jp2 - 1)*(nact2/nproc)
473 IF (j2 <= nker2)
THEN
475 karray(i1, j2, i3) = &
476 kernel_mpi(i1, i2, i3, jp2)
484 karray(1:nker1, 1:nker2, 1:nker3) = kernel(1:nker1, 1:nker2, 1:nker3)
489 DEALLOCATE (kernel_mpi)
490 CALL fft_dealloc(halfft_cache1)
491 CALL fft_dealloc(halfft_cache2)
492 DEALLOCATE (kernel_scf)
496 END SUBROUTINE surfaces_kernel
511 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
518 REAL(kind=
dp),
PARAMETER :: mu_max = 0.2_dp
520 INTEGER :: i, iend, ikern, ivalue, izero, n_iter, &
522 REAL(kind=
dp) :: f, filter, fl, fr, gleft, gltmp, gright, &
523 grtmp, mu0, ratio, x, x0, x1
524 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: green, green1
528 IF (mu <= mu_max)
THEN
534 ratio = real(2**n_iter, kind=
dp)
536 IF (mu0 <= mu_max)
THEN
546 ALLOCATE (green(-nrec:nrec))
552 IF (xval(izero) >= real(ikern, kind=
dp) .OR. izero == n_scf)
EXIT initialization
554 END DO initialization
560 IF (ivalue >= n_scf - intorder - 1)
EXIT loop_right
561 DO i = 1, intorder + 1
562 x = xval(ivalue) - real(ikern, kind=
dp)
563 f = yval(ivalue)*exp(-mu0*x)
564 filter = intorder*c(i)
565 gright = gright + filter*f
570 iend = n_scf - ivalue
572 x = xval(ivalue) - real(ikern, kind=
dp)
573 f = yval(ivalue)*exp(-mu0*x)
574 filter = intorder*c(i)
575 gright = gright + filter*f
583 green(ikern) = gleft + gright
592 IF (izero == n_scf)
EXIT loop_integration
593 DO i = 1, intorder + 1
595 fl = yval(ivalue)*exp(mu0*x)
596 fr = yval(ivalue)*exp(-mu0*x)
597 filter = intorder*c(i)
598 gltmp = gltmp + filter*fl
599 grtmp = grtmp + filter*fr
601 IF (xval(izero) >= real(ikern, kind=
dp) .OR. izero == n_scf)
THEN
603 EXIT loop_integration
609 END DO loop_integration
610 gleft = exp(-mu0)*(gleft + hres*exp(-mu0*real(ikern - 1, kind=
dp))*gltmp)
611 IF (izero == n_scf)
THEN
614 gright = exp(mu0)*(gright - hres*exp(mu0*real(ikern - 1, kind=
dp))*grtmp)
616 green(ikern) = gleft + gright
617 green(-ikern) = gleft + gright
618 IF (abs(green(ikern)) <= 1.e-20_dp)
THEN
624 ALLOCATE (green1(-nrec:nrec))
627 CALL scf_recursion(itype_scf, n_iter, nrec, green(-nrec), green1(-nrec))
629 DO i = 1, min(n, nrec)
630 g_mu(i) = green(i - 1)
632 DO i = min(n, nrec) + 1, n
636 DEALLOCATE (green, green1)
638 END SUBROUTINE calculates_green_opt
651 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
658 INTEGER :: i, iend, ikern, ivalue, izero
659 REAL(kind=
dp) :: c0, c1, filter, gl0, gl1, gr0, gr1, x, y
666 IF (xval(izero) >= real(ikern, kind=
dp) .OR. izero == n_scf)
EXIT initialization
668 END DO initialization
675 IF (ivalue >= n_scf - intorder - 1)
EXIT loop_right
676 DO i = 1, intorder + 1
679 filter = intorder*c(i)
680 gr1 = gr1 + filter*x*y
685 iend = n_scf - ivalue
689 filter = intorder*c(i)
690 gr1 = gr1 + filter*x*y
707 IF (izero == n_scf)
EXIT loop_integration
708 DO i = 1, intorder + 1
711 filter = intorder*c(i)
715 IF (xval(izero) >= real(ikern, kind=
dp) .OR. izero == n_scf)
THEN
716 EXIT loop_integration
722 END DO loop_integration
731 green(ikern + 1) = real(ikern, kind=
dp)*(gl0 - gr0) + gr1 - gl1
734 END SUBROUTINE calculates_green_opt_muzero
744 PURE ELEMENTAL SUBROUTINE indices(var_realimag, nelem, intrn, extrn, index)
746 INTEGER,
INTENT(out) :: var_realimag
747 INTEGER,
INTENT(in) :: nelem, intrn, extrn
748 INTEGER,
INTENT(out) :: index
754 var_realimag = 2 - mod(intrn, 2)
759 index = extrn + nelem*(i - 1)
761 END SUBROUTINE indices
790 SUBROUTINE free_kernel(n01, n02, n03, nfft1, nfft2, nfft3, n1k, n2k, n3k, &
791 hgrid, itype_scf, iproc, nproc, karray, mpi_group)
793 INTEGER,
INTENT(in) :: n01, n02, n03, nfft1, nfft2, nfft3, n1k, &
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
801 INTEGER,
PARAMETER :: n_gauss = 89, n_points = 2**6
802 REAL(kind=
dp),
PARAMETER :: p0_ref = 1._dp
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 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: kern_1_scf, kernel_scf, x_scf, y_scf
812 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: kp
813 REAL(kind=
dp),
DIMENSION(n_gauss) :: p_gauss, w_gauss
821 n_scf = 2*itype_scf*n_points
839 IF (
modulo(nker2, nproc) == 0)
EXIT
843 IF (
modulo(nker3, nproc) == 0)
EXIT
848 ALLOCATE (kp(n1h + 1, n3h + 1, nker2/nproc))
853 istart = iproc*nker2/nproc + 1
854 iend = min((iproc + 1)*nker2/nproc, n2h + n03)
857 IF (iproc == 0) istart1 = n2h - n03 + 2
860 ALLOCATE (x_scf(0:n_scf))
861 ALLOCATE (y_scf(0:n_scf))
866 dx = real(n_range, kind=
dp)/real(n_scf, kind=
dp)
868 n_cell = max(n01, n02, n03)
869 n_range = max(n_cell, n_range)
872 ALLOCATE (kernel_scf(-n_range:n_range))
873 ALLOCATE (kern_1_scf(-n_range:n_range))
876 a1 = hgrid*real(n01, kind=
dp)
877 a2 = hgrid*real(n02, kind=
dp)
878 a3 = hgrid*real(n03, kind=
dp)
880 x_scf(:) = hgrid*x_scf(:)
881 y_scf(:) = 1._dp/hgrid*y_scf(:)
884 p0_cell = p0_ref/(hgrid*hgrid)
887 CALL gequad(p_gauss, w_gauss, ur_gauss, dr_gauss, acc_gauss)
891 a_range = sqrt(a1*a1 + a2*a2 + a3*a3)
892 factor = 1._dp/a_range
894 factor2 = 1._dp/(a1*a1 + a2*a2 + a3*a3)
895 DO i_gauss = 1, n_gauss
896 p_gauss(i_gauss) = factor2*p_gauss(i_gauss)
898 DO i_gauss = 1, n_gauss
899 w_gauss(i_gauss) = factor*w_gauss(i_gauss)
904 loop_gauss:
DO i_gauss = n_gauss, 1, -1
906 pgauss = p_gauss(i_gauss)
909 n_iter = nint((log(pgauss) - log(p0_cell))/log(4._dp))
910 IF (n_iter <= 0)
THEN
914 p0gauss = pgauss/4._dp**n_iter
919 kernel_scf(:) = 0._dp
920 DO i_kern = 0, n_range
923 absci = x_scf(i) - real(i_kern, kind=
dp)*hgrid
925 kern = kern + y_scf(i)*exp(-p0gauss*absci)*dx
927 kernel_scf(i_kern) = kern
928 kernel_scf(-i_kern) = kern
929 IF (abs(kern) < 1.e-18_dp)
THEN
936 CALL scf_recursion(itype_scf, n_iter, n_range, kernel_scf, kern_1_scf)
940 DO i3 = istart1, iend
947 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 "(see ps_wavelet_fft3d.F) exactly.")
957 kp(i1, i2, i3 - istart + 1) = kp(i1, i2, i3 - istart + 1) + w_gauss(i_gauss)* &
958 kernel_scf(i01)*kernel_scf(i02)*kernel_scf(i03)
966 DEALLOCATE (kernel_scf)
967 DEALLOCATE (kern_1_scf)
975 CALL kernelfft(nfft1, nfft2, nfft3, nker1, nker2, nker3, n1k, n2k, n3k, nproc, iproc, &
976 kp, karray, mpi_group)
981 END SUBROUTINE free_kernel
993 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), &
997 COMPLEX(KIND=dp),
DIMENSION(lot, n3/2), &
1000 INTEGER :: i01, i03i, i03r, i3, l1, l3
1006 i03r = abs(l3 - n3/2 - 1) + 1
1007 i03i = abs(l3 - n3/2) + 1
1009 i01 = abs(l1 - 1 + i1 - n1/2 - 1) + 1
1010 zw(l1, i3) = cmplx(zf(i01, i03r), zf(i01, i03i),
dp)
1014 END SUBROUTINE inserthalf
1044 SUBROUTINE kernelfft(n1, n2, n3, nd1, nd2, nd3, nk1, nk2, nk3, nproc, iproc, zf, zr, mpi_group)
1046 INTEGER,
INTENT(in) :: n1, n2, n3, nd1, nd2, nd3, nk1, nk2, &
1049 DIMENSION(n1/2+1, n3/2+1, nd2/nproc), &
1051 REAL(kind=
dp),
DIMENSION(nk1, nk2, nk3/nproc), &
1055 INTEGER,
PARAMETER :: ncache_optimal = 8*1024
1057 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: zmpi2
1058 COMPLEX(KIND=dp),
ALLOCATABLE, &
1059 DIMENSION(:, :, :, :) :: zmpi1
1060 COMPLEX(KIND=dp),
CONTIGUOUS,
DIMENSION(:), &
1062 COMPLEX(KIND=dp),
CONTIGUOUS,
DIMENSION(:, :), &
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 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: cosinarr
1069 fft_plan_bw2, fft_plan_bw2_last, &
1070 fft_plan_bw3, fft_plan_bw3_last
1081 cpassert(nd3 >= n3/2 + 1)
1082 cpassert(mod(nd3, nproc) == 0)
1083 cpassert(mod(nd2, nproc) == 0)
1087 ncache = ncache_optimal
1088 IF (ncache <= max(n1, n2, n3/2)*4) ncache = max(n1, n2, n3/2)*4
1090 IF (mod(n2, 2) == 0) lzt = lzt + 1
1093 CALL fft_alloc(zw1, [ncache/4])
1094 zw1 = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1095 CALL fft_alloc(zw2, [ncache/4])
1096 zw2 = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1097 CALL fft_alloc(zt, [lzt, n1])
1098 zt = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1099 ALLOCATE (zmpi2(n1, nd2/nproc, nd3), source=cmplx(0.0_dp, 0.0_dp,
dp))
1100 ALLOCATE (cosinarr(2, n3/2))
1101 IF (nproc > 1)
ALLOCATE (zmpi1(n1, nd2/nproc, nd3/nproc, nproc), source=cmplx(0.0_dp, 0.0_dp,
dp))
1104 twopion = 8._dp*atan(1._dp)/real(n3, kind=
dp)
1106 cosinarr(1, i3) = cos(twopion*(i3 - 1))
1107 cosinarr(2, i3) = -sin(twopion*(i3 - 1))
1112 lot1 = ncache/(4*n1)
1113 lot2 = ncache/(4*n2)
1114 lot3 = ncache/(2*n3)
1117 final_chunk_size1 = mod(n2, lot1)
1118 final_chunk_size2 = mod(nk1, lot2)
1119 final_chunk_size3 = mod(n1, lot3)
1122 IF (n2 >= lot1)
THEN
1125 IF (final_chunk_size1 > 0)
THEN
1127 final_chunk_size1, zw1, zt)
1131 IF (nk1 >= lot2)
THEN
1134 IF (final_chunk_size2 > 0)
THEN
1136 final_chunk_size2, zw1, zw2)
1140 IF (n1 >= lot3)
THEN
1143 IF (final_chunk_size3 > 0)
THEN
1145 lot3, lot3, n3/2, final_chunk_size3, zw1, zw2)
1148 DO j2 = 1, nd2/nproc
1150 IF (iproc*(nd2/nproc) + j2 <= n2)
THEN
1153 mb = min(i1 + (lot3 - 1), n1)
1159 CALL inserthalf(n1, n3, lot3, nfft, i1, zf(1, 1, j2), zw1)
1163 IF (nfft == lot3)
THEN
1164 CALL fft_1d(fft_plan_bw3, zw1, zw2, 1.0_dp, stat)
1166 CALL fft_1d(fft_plan_bw3_last, zw1, zw2, 1.0_dp, stat)
1173 CALL scramble_unpack(i1, j2, lot3, nfft, n1, n3, nd2, nproc, nd3, zw2, zmpi2, cosinarr)
1183 CALL mpi_group%alltoall(zmpi2, zmpi1, n1*(nd2/nproc)*(nd3/nproc))
1187 DO j3 = 1, nd3/nproc
1189 IF (iproc*(nd3/nproc) + j3 <= n3/2 + 1)
THEN
1197 mb = min(j + (lot1 - 1), n2)
1202 IF (nproc == 1)
THEN
1203 CALL mpiswitch(j3, nfft, jp2st, j2st, lot1, n1, nd2, nd3, nproc, zmpi2, zw1)
1205 CALL mpiswitch(j3, nfft, jp2st, j2st, lot1, n1, nd2, nd3, nproc, zmpi1, zw1)
1212 IF (nfft == lot1)
THEN
1213 CALL fft_1d(fft_plan_bw1, zw1, zt(j:, 1), 1.0_dp, stat)
1215 CALL fft_1d(fft_plan_bw1_last, zw1, zt(j:, 1), 1.0_dp, stat)
1224 mb = min(j + (lot2 - 1), nk1)
1229 CALL switch(nfft, n2, lot2, n1, lzt, zt(:, j), zw1)
1235 IF (nfft == lot2)
THEN
1236 CALL fft_1d(fft_plan_bw2, zw1, zw2, 1.0_dp, stat)
1238 CALL fft_1d(fft_plan_bw2_last, zw1, zw2, 1.0_dp, stat)
1241 CALL realcopy(lot2, nfft, n2, nk1, nk2, zw2, zr(j, 1, j3))
1259 CALL fft_dealloc(zw1)
1260 CALL fft_dealloc(zw2)
1261 CALL fft_dealloc(zt)
1262 DEALLOCATE (cosinarr)
1263 IF (nproc > 1)
DEALLOCATE (zmpi1)
1265 END SUBROUTINE kernelfft
1277 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
1286 zout(j, i) = real(zin(j, i),
dp)
1290 END SUBROUTINE realcopy
1302 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)
1314 END SUBROUTINE switch
1330 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)
1337 INTEGER :: i1, j2, jp2, mfft
1340 DO jp2 = jp2st, nproc
1341 DO j2 = j2st, nd2/nproc
1343 IF (mfft > nfft)
THEN
1349 zw(mfft, i1) = zmpi1(i1, j2, j3, jp2)
1354 END SUBROUTINE mpiswitch
1364 PURE SUBROUTINE gequad(p, w, urange, drange, acc)
1366 REAL(kind=
dp),
INTENT(OUT) :: p(89), w(89), urange, drange, acc
1374 p(1) = 4.96142640560223544e19_dp
1375 p(2) = 1.37454269147978052e19_dp
1376 p(3) = 7.58610013441204679e18_dp
1377 p(4) = 4.42040691347806996e18_dp
1378 p(5) = 2.61986077948367892e18_dp
1379 p(6) = 1.56320138155496681e18_dp
1380 p(7) = 9.35645215863028402e17_dp
1381 p(8) = 5.60962910452691703e17_dp
1382 p(9) = 3.3666225119686761e17_dp
1383 p(10) = 2.0218253197947866e17_dp
1384 p(11) = 1.21477756091902017e17_dp
1385 p(12) = 7.3012982513608503e16_dp
1386 p(13) = 4.38951893556421099e16_dp
1387 p(14) = 2.63949482512262325e16_dp
1388 p(15) = 1.58742054072786174e16_dp
1389 p(16) = 9.54806587737665531e15_dp
1390 p(17) = 5.74353712364571709e15_dp
1391 p(18) = 3.455214877389445e15_dp
1392 p(19) = 2.07871658520326804e15_dp
1393 p(20) = 1.25064667315629928e15_dp
1394 p(21) = 7.52469429541933745e14_dp
1395 p(22) = 4.5274603337253175e14_dp
1396 p(23) = 2.72414006900059548e14_dp
1397 p(24) = 1.63912168349216752e14_dp
1398 p(25) = 9.86275802590865738e13_dp
1399 p(26) = 5.93457701624974985e13_dp
1400 p(27) = 3.5709554322296296e13_dp
1401 p(28) = 2.14872890367310454e13_dp
1402 p(29) = 1.29294719957726902e13_dp
1403 p(30) = 7.78003375426361016e12_dp
1404 p(31) = 4.68148199759876704e12_dp
1405 p(32) = 2.8169955024829868e12_dp
1406 p(33) = 1.69507790481958464e12_dp
1407 p(34) = 1.01998486064607581e12_dp
1408 p(35) = 6.13759486539856459e11_dp
1409 p(36) = 3.69320183828682544e11_dp
1410 p(37) = 2.22232783898905102e11_dp
1411 p(38) = 1.33725247623668682e11_dp
1412 p(39) = 8.0467192739036288e10_dp
1413 p(40) = 4.84199582415144143e10_dp
1414 p(41) = 2.91360091170559564e10_dp
1415 p(42) = 1.75321747475309216e10_dp
1416 p(43) = 1.0549735552210995e10_dp
1417 p(44) = 6.34815321079006586e9_dp
1418 p(45) = 3.81991113733594231e9_dp
1419 p(46) = 2.29857747533101109e9_dp
1420 p(47) = 1.38313653595483694e9_dp
1421 p(48) = 8.32282908580025358e8_dp
1422 p(49) = 5.00814519374587467e8_dp
1423 p(50) = 3.01358090773319025e8_dp
1424 p(51) = 1.81337994217503535e8_dp
1425 p(52) = 1.09117589961086823e8_dp
1426 p(53) = 6.56599771718640323e7_dp
1427 p(54) = 3.95099693638497164e7_dp
1428 p(55) = 2.37745694710665991e7_dp
1429 p(56) = 1.43060135285912813e7_dp
1430 p(57) = 8.60844290313506695e6_dp
1431 p(58) = 5.18000974075383424e6_dp
1432 p(59) = 3.116998193057466e6_dp
1433 p(60) = 1.87560993870024029e6_dp
1434 p(61) = 1.12862197183979562e6_dp
1435 p(62) = 679132.441326077231_dp
1436 p(63) = 408658.421279877969_dp
1437 p(64) = 245904.473450669789_dp
1438 p(65) = 147969.568088321005_dp
1439 p(66) = 89038.612357311147_dp
1440 p(67) = 53577.7362552358895_dp
1441 p(68) = 32239.6513926914668_dp
1442 p(69) = 19399.7580852362791_dp
1443 p(70) = 11673.5323603058634_dp
1444 p(71) = 7024.38438577707758_dp
1445 p(72) = 4226.82479307685999_dp
1446 p(73) = 2543.43254175354295_dp
1447 p(74) = 1530.47486269122675_dp
1448 p(75) = 920.941785160749482_dp
1449 p(76) = 554.163803906291646_dp
1450 p(77) = 333.46029740785694_dp
1451 p(78) = 200.6550575335041_dp
1452 p(79) = 120.741366914147284_dp
1453 p(80) = 72.6544243200329916_dp
1454 p(81) = 43.7187810415471025_dp
1455 p(82) = 26.3071631447061043_dp
1456 p(83) = 15.8299486353816329_dp
1457 p(84) = 9.52493152341244004_dp
1458 p(85) = 5.72200417067776041_dp
1459 p(86) = 3.36242234070940928_dp
1460 p(87) = 1.75371394604499472_dp
1461 p(88) = 0.64705932650658966_dp
1462 p(89) = 0.072765905943708247_dp
1464 w(1) = 47.67445484528304247e10_dp
1465 w(2) = 11.37485774750442175e9_dp
1466 w(3) = 78.64340976880190239e8_dp
1467 w(4) = 46.27335788759590498e8_dp
1468 w(5) = 24.7380464827152951e8_dp
1469 w(6) = 13.62904116438987719e8_dp
1470 w(7) = 92.79560029045882433e8_dp
1471 w(8) = 52.15931216254660251e8_dp
1472 w(9) = 31.67018011061666244e8_dp
1473 w(10) = 1.29291036801493046e8_dp
1474 w(11) = 1.00139319988015862e8_dp
1475 w(12) = 7.75892350510188341e7_dp
1476 w(13) = 6.01333567950731271e7_dp
1477 w(14) = 4.66141178654796875e7_dp
1478 w(15) = 3.61398903394911448e7_dp
1479 w(16) = 2.80225846672956389e7_dp
1480 w(17) = 2.1730509180930247e7_dp
1481 w(18) = 1.68524482625876965e7_dp
1482 w(19) = 1.30701489345870338e7_dp
1483 w(20) = 1.01371784832269282e7_dp
1484 w(21) = 7.86264116300379329e6_dp
1485 w(22) = 6.09861667912273717e6_dp
1486 w(23) = 4.73045784039455683e6_dp
1487 w(24) = 3.66928949951594161e6_dp
1488 w(25) = 2.8462050836230259e6_dp
1489 w(26) = 2.20777394798527011e6_dp
1490 w(27) = 1.71256191589205524e6_dp
1491 w(28) = 1.32843556197737076e6_dp
1492 w(29) = 1.0304731275955989e6_dp
1493 w(30) = 799345.206572271448_dp
1494 w(31) = 620059.354143595343_dp
1495 w(32) = 480986.704107449333_dp
1496 w(33) = 373107.167700228515_dp
1497 w(34) = 289424.08337412132_dp
1498 w(35) = 224510.248231581788_dp
1499 w(36) = 174155.825690028966_dp
1500 w(37) = 135095.256919654065_dp
1501 w(38) = 104795.442776800312_dp
1502 w(39) = 81291.4458222430418_dp
1503 w(40) = 63059.0493649328682_dp
1504 w(41) = 48915.9040455329689_dp
1505 w(42) = 37944.8484018048756_dp
1506 w(43) = 29434.4290473253969_dp
1507 w(44) = 22832.7622054490044_dp
1508 w(45) = 17711.743950151233_dp
1509 w(46) = 13739.287867104177_dp
1510 w(47) = 10657.7895710752585_dp
1511 w(48) = 8267.42141053961834_dp
1512 w(49) = 6413.17397520136448_dp
1513 w(50) = 4974.80402838654277_dp
1514 w(51) = 3859.03698188553047_dp
1515 w(52) = 2993.51824493299154_dp
1516 w(53) = 2322.1211966811754_dp
1517 w(54) = 1801.30750964719641_dp
1518 w(55) = 1397.30379659817038_dp
1519 w(56) = 1083.91149143250697_dp
1520 w(57) = 840.807939169209188_dp
1521 w(58) = 652.228524366749422_dp
1522 w(59) = 505.944376983506128_dp
1523 w(60) = 392.469362317941064_dp
1524 w(61) = 304.444930257324312_dp
1525 w(62) = 236.162932842453601_dp
1526 w(63) = 183.195466078603525_dp
1527 w(64) = 142.107732186551471_dp
1528 w(65) = 110.23530215723992_dp
1529 w(66) = 85.5113346705382257_dp
1530 w(67) = 66.3325469806696621_dp
1531 w(68) = 51.4552463353841373_dp
1532 w(69) = 39.9146798429449273_dp
1533 w(70) = 30.9624728409162095_dp
1534 w(71) = 24.018098812215013_dp
1535 w(72) = 18.6312338024296588_dp
1536 w(73) = 14.4525541233150501_dp
1537 w(74) = 11.2110836519105938_dp
1538 w(75) = 8.69662175848497178_dp
1539 w(76) = 6.74611236165731961_dp
1540 w(77) = 5.23307018057529994_dp
1541 w(78) = 4.05937850501539556_dp
1542 w(79) = 3.14892659076635714_dp
1543 w(80) = 2.44267408211071604_dp
1544 w(81) = 1.89482240522855261_dp
1545 w(82) = 1.46984505907050079_dp
1546 w(83) = 1.14019261330527007_dp
1547 w(84) = 0.884791217422925293_dp
1548 w(85) = 0.692686387080616483_dp
1549 w(86) = 0.585244576897023282_dp
1550 w(87) = 0.576182522545327589_dp
1551 w(88) = 0.596688817388997178_dp
1552 w(89) = 0.607879901151108771_dp
1558 END SUBROUTINE gequad
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
for(int lxp=0;lxp<=lp;lxp++)
subroutine, public fft_destroy_plan(plan)
...
subroutine, public fft_1d(plan, zin, zout, scale, stat)
...
subroutine, public fft_create_plan_1d(plan, fsign, trans_in, trans_out, ldx_in, ldx_out, n, m, zin, zout)
...
Type to store data about a (1D or 3D) FFT, including FFTW plan.
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public sp
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
Interface to the message passing library MPI.
Creates the wavelet kernel for the wavelet based poisson solver.
subroutine, public scramble_unpack(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zw, zmpi2, cosinarr)
(Based on suitable modifications of S.Goedecker routines) Assign the correct planes to the work array...
Creates the wavelet kernel for the wavelet based poisson solver.
subroutine, public createkernel(geocode, n01, n02, n03, hx, hy, hz, itype_scf, iproc, nproc, kernel, mpi_group)
Allocate a pointer which corresponds to the zero-padded FFT slice needed for calculating the convolut...
Creates the wavelet kernel for the wavelet based poisson solver.
subroutine, public scaling_function(itype, nd, nrange, a, x)
Calculate the values of a scaling function in real uniform grid.
pure subroutine, public scf_recursion(itype, n_iter, n_range, kernel_scf, kern_1_scf)
Do iterations to go from p0gauss to pgauss order interpolating scaling function.
Performs a wavelet based solution of the Poisson equation.
subroutine, public s_fft_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
Calculate four sets of dimension needed for the calculation of the convolution for the surface system...
subroutine, public f_fft_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
Calculate four sets of dimension needed for the calculation of the zero-padded convolution.