24#include "../base/base_uses.f90"
30 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'ps_wavelet_base'
56 SUBROUTINE p_poissonsolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, zf &
57 , scal, hx, hy, hz, mpi_group)
58 INTEGER,
INTENT(in) :: n1, n2, n3, nd1, nd2, nd3, md1, md2, &
60 REAL(kind=
dp),
DIMENSION(md1, md3, md2/nproc), &
62 REAL(kind=
dp),
INTENT(in) :: scal, hx, hy, hz
66 INTEGER,
PARAMETER :: ncache_optimal = 8*1024
68 INTEGER :: i1, i3, j, j2, &
69 j2stb, j2stf, j3, jp2stb, jp2stf, lot1, lot2, lot3, &
70 lzt, ma, mb, ncache, nfft, stat, &
71 final_chunk_size3, final_chunk_size1, final_chunk_size2
72 COMPLEX(KIND=dp),
POINTER,
CONTIGUOUS,
DIMENSION(:, :) :: zt
73 COMPLEX(KIND=dp),
POINTER,
CONTIGUOUS,
DIMENSION(:) :: zw1, zw2
74 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: zmpi2
75 COMPLEX(KIND=dp),
ALLOCATABLE, &
76 DIMENSION(:, :, :, :) :: zmpi1
77 TYPE(
fft_plan_type) :: fft_plan_bw3, fft_plan_bw3_last, fft_plan_fw3, fft_plan_fw3_last, &
78 fft_plan_bw1, fft_plan_bw1_last, fft_plan_fw1, fft_plan_fw1_last, &
79 fft_plan_bw2, fft_plan_bw2_last, fft_plan_fw2, fft_plan_fw2_last
81 IF (nd1 < n1/2 + 1) cpabort(
"Parallel convolution:ERROR:nd1")
82 IF (nd2 < n2/2 + 1) cpabort(
"Parallel convolution:ERROR:nd2")
83 IF (nd3 < n3/2 + 1) cpabort(
"Parallel convolution:ERROR:nd3")
84 IF (md1 < n1) cpabort(
"Parallel convolution:ERROR:md1")
85 IF (md2 < n2) cpabort(
"Parallel convolution:ERROR:md2")
86 IF (md3 < n3) cpabort(
"Parallel convolution:ERROR:md3")
87 IF (mod(nd3, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:nd3")
88 IF (mod(md2, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:md2")
91 ncache = ncache_optimal
92 IF (ncache <= max(n1, n2, n3)*4) ncache = max(n1, n2, n3)*4
95 IF (mod(n2, 2) == 0) lzt = lzt + 1
98 CALL fft_alloc(zw1, [ncache/4])
99 zw1 = cmplx(0.0_dp, 0.0_dp, kind=
dp)
100 CALL fft_alloc(zw2, [ncache/4])
101 zw2 = cmplx(0.0_dp, 0.0_dp, kind=
dp)
102 CALL fft_alloc(zt, [lzt, n1])
103 zt = cmplx(0.0_dp, 0.0_dp, kind=
dp)
104 ALLOCATE (zmpi2(n1, md2/nproc, nd3), source=cmplx(0.0_dp, 0.0_dp, kind=
dp))
105 IF (nproc > 1)
ALLOCATE (zmpi1(n1, md2/nproc, nd3/nproc, nproc), source=cmplx(0.0_dp, 0.0_dp, kind=
dp))
114 final_chunk_size1 = mod(n2, lot1)
115 final_chunk_size2 = mod(n1, lot2)
116 final_chunk_size3 = mod(n1, lot3)
123 IF (final_chunk_size1 > 0)
THEN
125 final_chunk_size1, zw1, zt)
127 final_chunk_size1, zt, zw1)
135 IF (final_chunk_size2 > 0)
THEN
137 final_chunk_size2, zw1, zw2)
139 final_chunk_size2, zw2, zw1)
147 IF (final_chunk_size3 > 0)
THEN
149 lot3, lot3, n3, final_chunk_size3, zw1, zw2)
151 lot3, lot3, n3, final_chunk_size3, zw1, zw2)
156 IF (iproc*(md2/nproc) + j2 <= n2)
THEN
159 mb = min(i1 + (lot3 - 1), n1)
162 CALL p_fill_upcorn(md1, md3, lot3, nfft, n3, zf(i1, 1, j2), zw1)
167 IF (nfft == lot3)
THEN
168 CALL fft_1d(fft_plan_bw3, zw1, zw2, 1.0_dp, stat)
170 CALL fft_1d(fft_plan_bw3_last, zw1, zw2, 1.0_dp, stat)
176 CALL scramble_p(i1, j2, lot3, nfft, n1, n3, md2, nproc, nd3, zw2, zmpi2)
186 CALL mpi_group%alltoall(zmpi2, zmpi1, n1*(md2/nproc)*(nd3/nproc))
193 IF (iproc*(nd3/nproc) + j3 <= n3/2 + 1)
THEN
203 mb = min(j + (lot1 - 1), n2)
209 CALL p_mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot1, n1, md2, nd3, nproc, zmpi2, zw1)
211 CALL p_mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot1, n1, md2, nd3, nproc, zmpi1, zw1)
218 IF (nfft == lot1)
THEN
219 CALL fft_1d(fft_plan_bw1, zw1, zt(j:, 1), 1.0_dp, stat)
221 CALL fft_1d(fft_plan_bw1_last, zw1, zt(j:, 1), 1.0_dp, stat)
230 mb = min(j + (lot2 - 1), n1)
235 CALL p_switch_upcorn(nfft, n2, lot2, n1, lzt, zt(:, j), zw1)
241 IF (nfft == lot2)
THEN
242 CALL fft_1d(fft_plan_bw2, zw1, zw2, 1.0_dp, stat)
244 CALL fft_1d(fft_plan_bw2_last, zw1, zw2, 1.0_dp, stat)
249 i3 = iproc*(nd3/nproc) + j3
250 CALL p_multkernel(n1, n2, n3, lot2, nfft, j, i3, zw2, hx, hy, hz)
257 IF (nfft == lot2)
THEN
258 CALL fft_1d(fft_plan_fw2, zw2, zw1, 1.0_dp, stat)
260 CALL fft_1d(fft_plan_fw2_last, zw2, zw1, 1.0_dp, stat)
265 CALL p_unswitch_downcorn(nfft, n2, lot2, n1, lzt, zw1, zt(:, j))
273 mb = min(j + (lot1 - 1), n2)
278 IF (nfft == lot1)
THEN
279 CALL fft_1d(fft_plan_fw1, zt(j:, 1), zw2, 1.0_dp, stat)
281 CALL fft_1d(fft_plan_fw1_last, zt(j:, 1), zw2, 1.0_dp, stat)
288 CALL p_unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot1, n1, md2, nd3, nproc, zw2, zmpi2)
290 CALL p_unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot1, n1, md2, nd3, nproc, zw2, zmpi1)
301 CALL mpi_group%alltoall(zmpi1, zmpi2, n1*(md2/nproc)*(nd3/nproc))
308 IF (iproc*(md2/nproc) + j2 <= n2)
THEN
311 mb = min(i1 + (lot3 - 1), n1)
316 CALL unscramble_p(i1, j2, lot3, nfft, n1, n3, md2, nproc, nd3, zmpi2, zw1)
322 IF (nfft == lot3)
THEN
323 CALL fft_1d(fft_plan_fw3, zw1, zw2, 1.0_dp, stat)
325 CALL fft_1d(fft_plan_fw3_last, zw1, zw2, 1.0_dp, stat)
330 CALL p_unfill_downcorn(md1, md3, lot3, nfft, n3, zw2, zf(i1, 1, j2), scal)
353 CALL fft_dealloc(zw1)
354 CALL fft_dealloc(zw2)
356 IF (nproc > 1)
DEALLOCATE (zmpi1)
373 SUBROUTINE p_mpiswitch_upcorn(j3, nfft, Jp2stb, J2stb, lot, n1, md2, nd3, nproc, zmpi1, zw)
374 INTEGER,
INTENT(in) :: j3, nfft
375 INTEGER,
INTENT(inout) :: jp2stb, j2stb
376 INTEGER,
INTENT(in) :: lot, n1, md2, nd3, nproc
378 DIMENSION(n1, md2/nproc, nd3/nproc, nproc), &
380 COMPLEX(KIND=dp),
DIMENSION(lot, n1), &
383 INTEGER :: i1, j2, jp2, mfft
386 DO jp2 = jp2stb, nproc
387 DO j2 = j2stb, md2/nproc
389 IF (mfft > nfft)
THEN
395 zw(mfft, i1) = zmpi1(i1, j2, j3, jp2)
400 END SUBROUTINE p_mpiswitch_upcorn
412 SUBROUTINE p_switch_upcorn(nfft, n2, lot, n1, lzt, zt, zw)
413 INTEGER,
INTENT(in) :: nfft, n2, lot, n1, lzt
414 COMPLEX(KIND=dp),
DIMENSION(lzt, n1),
INTENT(in) :: zt
415 COMPLEX(KIND=dp),
DIMENSION(lot, n2), &
426 END SUBROUTINE p_switch_upcorn
438 SUBROUTINE p_unswitch_downcorn(nfft, n2, lot, n1, lzt, zw, zt)
439 INTEGER,
INTENT(in) :: nfft, n2, lot, n1, lzt
440 COMPLEX(KIND=dp),
DIMENSION(lot, n2),
INTENT(in) :: zw
441 COMPLEX(KIND=dp),
DIMENSION(lzt, n1), &
452 END SUBROUTINE p_unswitch_downcorn
468 SUBROUTINE p_unmpiswitch_downcorn(j3, nfft, Jp2stf, J2stf, lot, n1, md2, nd3, nproc, zw, zmpi1)
469 INTEGER,
INTENT(in) :: j3, nfft
470 INTEGER,
INTENT(inout) :: jp2stf, j2stf
471 INTEGER,
INTENT(in) :: lot, n1, md2, nd3, nproc
472 COMPLEX(KIND=dp),
DIMENSION(lot, n1),
INTENT(in) :: zw
474 DIMENSION(n1, md2/nproc, nd3/nproc, nproc), &
475 INTENT(inout) :: zmpi1
477 INTEGER :: i1, j2, jp2, mfft
480 DO jp2 = jp2stf, nproc
481 DO j2 = j2stf, md2/nproc
483 IF (mfft > nfft)
THEN
489 zmpi1(i1, j2, j3, jp2) = zw(mfft, i1)
494 END SUBROUTINE p_unmpiswitch_downcorn
520 SUBROUTINE p_unfill_downcorn(md1, md3, lot, nfft, n3, zw, zf, scal)
521 INTEGER,
INTENT(in) :: md1, md3, lot, nfft, n3
522 COMPLEX(KIND=dp),
DIMENSION(lot, n3),
INTENT(in) :: zw
523 REAL(kind=
dp),
DIMENSION(md1, md3),
INTENT(inout) :: zf
524 REAL(kind=
dp),
INTENT(in) :: scal
527 REAL(kind=
dp) :: pot1
531 pot1 = scal*real(zw(i1, i3),
dp)
536 END SUBROUTINE p_unfill_downcorn
548 SUBROUTINE p_fill_upcorn(md1, md3, lot, nfft, n3, zf, zw)
549 INTEGER,
INTENT(in) :: md1, md3, lot, nfft, n3
550 REAL(kind=
dp),
DIMENSION(md1, md3),
INTENT(in) :: zf
551 COMPLEX(KIND=dp),
DIMENSION(lot, n3), &
558 zw(i1, i3) = cmplx(zf(i1, i3), 0.0_dp,
dp)
562 END SUBROUTINE p_fill_upcorn
589 SUBROUTINE scramble_p(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zw, zmpi2)
590 INTEGER,
INTENT(in) :: i1, j2, lot, nfft, n1, n3, md2, nproc, &
592 COMPLEX(KIND=dp),
DIMENSION(lot, n3),
INTENT(in) :: zw
593 COMPLEX(KIND=dp),
DIMENSION(n1, md2/nproc, nd3), &
594 INTENT(inout) :: zmpi2
600 zmpi2(i1 + i, j2, i3) = zw(i + 1, i3)
604 END SUBROUTINE scramble_p
631 SUBROUTINE unscramble_p(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zmpi2, zw)
632 INTEGER,
INTENT(in) :: i1, j2, lot, nfft, n1, n3, md2, nproc, &
634 COMPLEX(KIND=dp),
DIMENSION(n1, md2/nproc, nd3), &
636 COMPLEX(KIND=dp),
DIMENSION(lot, n3), &
643 zw(i + 1, i3) = zmpi2(i1 + i, j2, i3)
649 zw(i + 1, j3) = conjg(zmpi2(i1 + i, j2, i3))
650 zw(i + 1, i3) = zmpi2(i1 + i, j2, i3)
654 END SUBROUTINE unscramble_p
684 SUBROUTINE p_multkernel(n1, n2, n3, lot, nfft, jS, i3, zw, hx, hy, hz)
685 INTEGER,
INTENT(in) :: n1, n2, n3, lot, nfft, js, i3
686 COMPLEX(KIND=dp),
DIMENSION(lot, n2), &
688 REAL(kind=
dp),
INTENT(in) :: hx, hy, hz
690 INTEGER :: i1, i2, j1, j2, j3
691 REAL(kind=
dp) :: fourpi2, ker, mu3, p1, p2
693 fourpi2 = 4._dp*
pi**2
695 mu3 = real(j3 - 1, kind=
dp)/real(n3, kind=
dp)
702 j1 = j1 - (j1/(n1/2 + 2))*n1
703 j2 = i2 - (i2/(n2/2 + 2))*n2
704 p1 = real(j1 - 1, kind=
dp)/real(n1, kind=
dp)
705 p2 = real(j2 - 1, kind=
dp)/real(n2, kind=
dp)
706 ker = -fourpi2*((p1/hx)**2 + (p2/hz)**2 + mu3)
707 IF (ker /= 0._dp) ker = 1._dp/ker
708 zw(i1, i2) = zw(i1, i2)*ker
712 END SUBROUTINE p_multkernel
740 SUBROUTINE multkernel(nd1, nd2, n1, n2, lot, nfft, jS, pot, zw)
741 INTEGER,
INTENT(in) :: nd1, nd2, n1, n2, lot, nfft, js
742 REAL(kind=
dp),
DIMENSION(nd1, nd2),
INTENT(in) :: pot
743 COMPLEX(KIND=dp),
DIMENSION(lot, n2), &
746 INTEGER :: i2, j, j1, j2
750 j1 = j1 + (j1/(n1/2 + 2))*(n1 + 2 - 2*j1)
751 zw(j, 1) = zw(j, 1)*pot(j1, 1)
758 j1 = j1 + (j1/(n1/2 + 2))*(n1 + 2 - 2*j1)
760 zw(j, i2) = zw(j, i2)*pot(j1, i2)
761 zw(j, j2) = zw(j, j2)*pot(j1, i2)
768 j1 = j1 + (j1/(n1/2 + 2))*(n1 + 2 - 2*j1)
770 zw(j, j2) = zw(j, j2)*pot(j1, j2)
773 END SUBROUTINE multkernel
811 SUBROUTINE s_poissonsolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, pot, zf, &
813 INTEGER,
INTENT(in) :: n1, n2, n3, nd1, nd2, nd3, md1, md2, &
815 REAL(kind=
dp),
DIMENSION(nd1, nd2, nd3/nproc), &
817 REAL(kind=
dp),
DIMENSION(md1, md3, md2/nproc), &
819 REAL(kind=
dp),
INTENT(in) :: scal
823 CHARACTER(len=*),
PARAMETER :: routinen =
'S_PoissonSolver'
824 INTEGER,
PARAMETER :: ncache_optimal = 8*1024
826 INTEGER :: handle, i1, i3, j, j2, j2stb, j2stf, j3, jp2stb, &
827 jp2stf, lot1, lot2, lot3, lzt, ma, mb, ncache, nfft, stat, &
828 final_chunk_size1, final_chunk_size2, final_chunk_size3
829 REAL(kind=
dp) :: twopion
830 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: cosinarr
831 COMPLEX(KIND=dp),
POINTER,
CONTIGUOUS,
DIMENSION(:, :) :: zt
832 COMPLEX(KIND=dp),
POINTER,
CONTIGUOUS,
DIMENSION(:) :: zw1, zw2
833 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: zmpi2
834 COMPLEX(KIND=dp),
ALLOCATABLE, &
835 DIMENSION(:, :, :, :) :: zmpi1
836 TYPE(
fft_plan_type) :: fft_plan_bw3, fft_plan_bw3_last, fft_plan_fw3, fft_plan_fw3_last, &
837 fft_plan_bw1, fft_plan_bw1_last, fft_plan_fw1, fft_plan_fw1_last, &
838 fft_plan_bw2, fft_plan_bw2_last, fft_plan_fw2, fft_plan_fw2_last
840 CALL timeset(routinen, handle)
842 IF (mod(n3, 2) /= 0) cpabort(
"Parallel convolution:ERROR:n3")
843 IF (nd1 < n1/2 + 1) cpabort(
"Parallel convolution:ERROR:nd1")
844 IF (nd2 < n2/2 + 1) cpabort(
"Parallel convolution:ERROR:nd2")
845 IF (nd3 < n3/2 + 1) cpabort(
"Parallel convolution:ERROR:nd3")
846 IF (md1 < n1) cpabort(
"Parallel convolution:ERROR:md1")
847 IF (md2 < n2) cpabort(
"Parallel convolution:ERROR:md2")
848 IF (md3 < n3/2) cpabort(
"Parallel convolution:ERROR:md3")
849 IF (mod(nd3, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:nd3")
850 IF (mod(md2, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:md2")
853 ncache = ncache_optimal
854 IF (ncache <= max(n1, n2, n3/2)*4) ncache = max(n1, n2, n3/2)*4
857 IF (mod(n2, 2) == 0) lzt = lzt + 1
858 IF (mod(n2, 4) == 0) lzt = lzt + 1
860 CALL fft_alloc(zw1, [ncache/4])
861 zw1 = cmplx(0.0_dp, 0.0_dp, kind=
dp)
862 CALL fft_alloc(zw2, [ncache/4])
863 zw2 = cmplx(0.0_dp, 0.0_dp, kind=
dp)
864 CALL fft_alloc(zt, [lzt, n1])
865 zt = cmplx(0.0_dp, 0.0_dp,
dp)
866 ALLOCATE (zmpi2(n1, md2/nproc, nd3), source=cmplx(0.0_dp, 0.0_dp,
dp))
867 ALLOCATE (cosinarr(2, n3/2))
868 IF (nproc > 1)
ALLOCATE (zmpi1(n1, md2/nproc, nd3/nproc, nproc), source=cmplx(0.0_dp, 0.0_dp,
dp))
871 twopion = 8._dp*atan(1._dp)/real(n3, kind=
dp)
873 cosinarr(1, i3) = cos(twopion*(i3 - 1))
874 cosinarr(2, i3) = -sin(twopion*(i3 - 1))
885 final_chunk_size1 = mod(n2, lot1)
886 final_chunk_size2 = mod(n1, lot2)
887 final_chunk_size3 = mod(n1, lot3)
894 IF (final_chunk_size1 > 0)
THEN
896 final_chunk_size1, zw1, zt)
898 final_chunk_size1, zt, zw1)
906 IF (final_chunk_size2 > 0)
THEN
908 final_chunk_size2, zw1, zw2)
910 final_chunk_size2, zw2, zw1)
918 IF (final_chunk_size3 > 0)
THEN
920 lot3, lot3, n3/2, final_chunk_size3, zw1, zw2)
922 lot3, lot3, n3/2, final_chunk_size3, zw1, zw2)
927 IF (iproc*(md2/nproc) + j2 <= n2)
THEN
930 mb = min(i1 + (lot3 - 1), n1)
934 CALL halfill_upcorn(md1, md3, lot3, nfft, n3, zf(i1, 1, j2), zw1)
939 IF (nfft == lot3)
THEN
940 CALL fft_1d(fft_plan_bw3, zw1, zw2, 1.0_dp, stat)
942 CALL fft_1d(fft_plan_bw3_last, zw1, zw2, 1.0_dp, stat)
948 CALL scramble_unpack(i1, j2, lot3, nfft, n1, n3, md2, nproc, nd3, zw2, zmpi2, cosinarr)
956 CALL mpi_group%alltoall(zmpi2, zmpi1, n1*(md2/nproc)*(nd3/nproc))
963 IF (iproc*(nd3/nproc) + j3 <= n3/2 + 1)
THEN
973 mb = min(j + (lot1 - 1), n2)
979 CALL s_mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot1, n1, md2, nd3, nproc, zmpi2, zw1)
981 CALL s_mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot1, n1, md2, nd3, nproc, zmpi1, zw1)
988 IF (nfft == lot1)
THEN
989 CALL fft_1d(fft_plan_bw1, zw1, zt(j:, 1), 1.0_dp, stat)
991 CALL fft_1d(fft_plan_bw1_last, zw1, zt(j:, 1), 1.0_dp, stat)
1000 mb = min(j + (lot2 - 1), n1)
1005 CALL s_switch_upcorn(nfft, n2, lot2, n1, lzt, zt(:, j), zw1)
1011 IF (nfft == lot2)
THEN
1012 CALL fft_1d(fft_plan_bw2, zw1, zw2, 1.0_dp, stat)
1014 CALL fft_1d(fft_plan_bw2_last, zw1, zw2, 1.0_dp, stat)
1019 CALL multkernel(nd1, nd2, n1, n2, lot2, nfft, j, pot(1, 1, j3), zw2)
1026 IF (nfft == lot2)
THEN
1027 CALL fft_1d(fft_plan_fw2, zw2, zw1, 1.0_dp, stat)
1029 CALL fft_1d(fft_plan_fw2_last, zw2, zw1, 1.0_dp, stat)
1034 CALL s_unswitch_downcorn(nfft, n2, lot2, n1, lzt, zw1, zt(:, j))
1042 mb = min(j + (lot1 - 1), n2)
1047 IF (nfft == lot1)
THEN
1048 CALL fft_1d(fft_plan_fw1, zt(j:, 1), zw2, 1.0_dp, stat)
1050 CALL fft_1d(fft_plan_fw1_last, zt(j:, 1), zw2, 1.0_dp, stat)
1056 IF (nproc == 1)
THEN
1057 CALL s_unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot1, n1, md2, nd3, nproc, zw2, zmpi2)
1059 CALL s_unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot1, n1, md2, nd3, nproc, zw2, zmpi1)
1070 CALL mpi_group%alltoall(zmpi1, zmpi2, n1*(md2/nproc)*(nd3/nproc))
1077 DO j2 = 1, md2/nproc
1079 IF (iproc*(md2/nproc) + j2 <= n2)
THEN
1082 mb = min(i1 + (lot3 - 1), n1)
1087 CALL unscramble_pack(i1, j2, lot3, nfft, n1, n3, md2, nproc, nd3, zmpi2, zw1, cosinarr)
1093 IF (nfft == lot3)
THEN
1094 CALL fft_1d(fft_plan_fw3, zw1, zw2, 1.0_dp, stat)
1096 CALL fft_1d(fft_plan_fw3_last, zw1, zw2, 1.0_dp, stat)
1101 CALL unfill_downcorn(md1, md3, lot3, nfft, n3, zw2, zf(i1, 1, j2), scal)
1126 CALL fft_dealloc(zw1)
1127 CALL fft_dealloc(zw2)
1128 CALL fft_dealloc(zt)
1129 DEALLOCATE (cosinarr)
1130 IF (nproc > 1)
DEALLOCATE (zmpi1)
1132 CALL timestop(handle)
1149 SUBROUTINE s_mpiswitch_upcorn(j3, nfft, Jp2stb, J2stb, lot, n1, md2, nd3, nproc, zmpi1, zw)
1150 INTEGER,
INTENT(in) :: j3, nfft
1151 INTEGER,
INTENT(inout) :: jp2stb, j2stb
1152 INTEGER,
INTENT(in) :: lot, n1, md2, nd3, nproc
1154 DIMENSION(n1, md2/nproc, nd3/nproc, nproc), &
1156 COMPLEX(KIND=dp),
DIMENSION(lot, n1), &
1159 INTEGER :: i1, j2, jp2, mfft
1162 DO jp2 = jp2stb, nproc
1163 DO j2 = j2stb, md2/nproc
1165 IF (mfft > nfft)
THEN
1171 zw(mfft, i1) = zmpi1(i1, j2, j3, jp2)
1176 END SUBROUTINE s_mpiswitch_upcorn
1188 SUBROUTINE s_switch_upcorn(nfft, n2, lot, n1, lzt, zt, zw)
1189 INTEGER,
INTENT(in) :: nfft, n2, lot, n1, lzt
1190 COMPLEX(KIND=dp),
DIMENSION(lzt, n1),
INTENT(in) :: zt
1191 COMPLEX(KIND=dp),
DIMENSION(lot, n2), &
1201 END SUBROUTINE s_switch_upcorn
1213 SUBROUTINE s_unswitch_downcorn(nfft, n2, lot, n1, lzt, zw, zt)
1214 INTEGER,
INTENT(in) :: nfft, n2, lot, n1, lzt
1215 COMPLEX(KIND=dp),
DIMENSION(lot, n2),
INTENT(in) :: zw
1216 COMPLEX(KIND=dp),
DIMENSION(lzt, n1), &
1226 END SUBROUTINE s_unswitch_downcorn
1242 SUBROUTINE s_unmpiswitch_downcorn(j3, nfft, Jp2stf, J2stf, lot, n1, md2, nd3, nproc, zw, zmpi1)
1243 INTEGER,
INTENT(in) :: j3, nfft
1244 INTEGER,
INTENT(inout) :: jp2stf, j2stf
1245 INTEGER,
INTENT(in) :: lot, n1, md2, nd3, nproc
1246 COMPLEX(KIND=dp),
DIMENSION(lot, n1),
INTENT(in) :: zw
1248 DIMENSION(n1, md2/nproc, nd3/nproc, nproc), &
1249 INTENT(inout) :: zmpi1
1251 INTEGER :: i1, j2, jp2, mfft
1254 DO jp2 = jp2stf, nproc
1255 DO j2 = j2stf, md2/nproc
1257 IF (mfft > nfft)
THEN
1263 zmpi1(i1, j2, j3, jp2) = zw(mfft, i1)
1268 END SUBROUTINE s_unmpiswitch_downcorn
1295 SUBROUTINE unfill_downcorn(md1, md3, lot, nfft, n3, zw, zf, scal)
1296 INTEGER,
INTENT(in) :: md1, md3, lot, nfft, n3
1297 COMPLEX(KIND=dp),
DIMENSION(lot, n3/2),
INTENT(in) :: zw
1298 REAL(kind=
dp),
DIMENSION(md1, md3),
INTENT(inout) :: zf
1299 REAL(kind=
dp),
INTENT(in) :: scal
1302 REAL(kind=
dp) :: pot1
1306 pot1 = scal*real(zw(i1, i3),
dp)
1308 zf(i1, 2*i3 - 1) = pot1
1309 pot1 = scal*aimag(zw(i1, i3))
1314 END SUBROUTINE unfill_downcorn
1326 SUBROUTINE halfill_upcorn(md1, md3, lot, nfft, n3, zf, zw)
1327 INTEGER :: md1, md3, lot, nfft, n3
1328 REAL(kind=
dp) :: zf(md1, md3)
1329 COMPLEX(KIND=dp) :: zw(lot, n3/2)
1338 zw(i1, i3) = cmplx(0.0_dp, 0.0_dp,
dp)
1341 DO i3 = n3/4 + 1, n3/2
1343 zw(i1, i3) = cmplx(zf(i1, 2*i3 - 1 - n3/2), zf(i1, 2*i3 - n3/2),
dp)
1347 END SUBROUTINE halfill_upcorn
1377 SUBROUTINE scramble_unpack(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zw, zmpi2, cosinarr)
1378 INTEGER,
INTENT(in) :: i1, j2, lot, nfft, n1, n3, md2, nproc, &
1380 COMPLEX(KIND=dp),
DIMENSION(lot, n3/2),
INTENT(in) :: zw
1381 COMPLEX(KIND=dp),
DIMENSION(n1, md2/nproc, nd3), &
1382 INTENT(inout) :: zmpi2
1383 REAL(kind=
dp),
DIMENSION(2, n3/2),
INTENT(in) :: cosinarr
1385 INTEGER :: i, i3, ind1, ind2
1386 REAL(kind=
dp) :: a, b, c, cp, d, fei, fer, fi, foi,
for, &
1392 a = real(zw(i + 1, 1),
dp)
1393 b = aimag(zw(i + 1, 1))
1394 zmpi2(i1 + i, j2, 1) = cmplx(a + b, 0.0_dp,
dp)
1395 zmpi2(i1 + i, j2, n3/2 + 1) = cmplx(a - b, 0.0_dp,
dp)
1400 ind2 = n3/2 - i3 + 2
1401 cp = cosinarr(1, i3)
1402 sp = cosinarr(2, i3)
1404 a = real(zw(i + 1, ind1),
dp)
1405 b = aimag(zw(i + 1, ind1))
1406 c = real(zw(i + 1, ind2),
dp)
1407 d = aimag(zw(i + 1, ind2))
1412 fr = fer + cp*foi -
sp*
for
1413 fi = fei - cp*
for -
sp*foi
1414 zmpi2(i1 + i, j2, ind1) = cmplx(fr, fi,
dp)
1448 SUBROUTINE unscramble_pack(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zmpi2, zw, cosinarr)
1449 INTEGER,
INTENT(in) :: i1, j2, lot, nfft, n1, n3, md2, nproc, &
1451 COMPLEX(KIND=dp),
DIMENSION(n1, md2/nproc, nd3), &
1453 COMPLEX(KIND=dp),
DIMENSION(lot, n3/2), &
1455 REAL(kind=
dp),
DIMENSION(2, n3/2),
INTENT(in) :: cosinarr
1457 INTEGER :: i, i3, inda, indb
1458 REAL(kind=
dp) :: a, b, c, cp, d, ie, ih, io, re, rh, ro, &
1463 indb = n3/2 + 2 - i3
1464 cp = cosinarr(1, i3)
1465 sp = cosinarr(2, i3)
1467 a = real(zmpi2(i1 + i, j2, inda),
dp)
1468 b = aimag(zmpi2(i1 + i, j2, inda))
1469 c = real(zmpi2(i1 + i, j2, indb),
dp)
1470 d = -aimag(zmpi2(i1 + i, j2, indb))
1473 ro = (a - c)*cp - (b - d)*
sp
1474 io = (a - c)*
sp + (b - d)*cp
1477 zw(i + 1, inda) = cmplx(rh, ih,
dp)
1481 END SUBROUTINE unscramble_pack
1517 SUBROUTINE f_poissonsolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, pot, zf, &
1519 INTEGER,
INTENT(in) :: n1, n2, n3, nd1, nd2, nd3, md1, md2, &
1521 REAL(kind=
dp),
DIMENSION(nd1, nd2, nd3/nproc), &
1523 REAL(kind=
dp),
DIMENSION(md1, md3, md2/nproc), &
1525 REAL(kind=
dp),
INTENT(in) :: scal
1529 INTEGER,
PARAMETER :: ncache_optimal = 8*1024
1531 INTEGER :: i1, i3, j, j2, &
1532 j2stb, j2stf, j3, jp2stb, jp2stf, lot1, lot2, lot3, &
1533 lzt, ma, mb, ncache, nfft, stat, &
1534 final_chunk_size1, final_chunk_size2, final_chunk_size3
1535 REAL(kind=
dp) :: twopion
1536 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: cosinarr
1537 COMPLEX(KIND=dp),
POINTER,
CONTIGUOUS,
DIMENSION(:, :) :: zt
1538 COMPLEX(KIND=dp),
POINTER,
CONTIGUOUS,
DIMENSION(:) :: zw1, zw2
1539 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: zmpi2
1540 COMPLEX(KIND=dp),
ALLOCATABLE, &
1541 DIMENSION(:, :, :, :) :: zmpi1
1542 TYPE(
fft_plan_type) :: fft_plan_bw3, fft_plan_bw3_last, fft_plan_fw3, fft_plan_fw3_last, &
1543 fft_plan_bw1, fft_plan_bw1_last, fft_plan_fw1, fft_plan_fw1_last, &
1544 fft_plan_bw2, fft_plan_bw2_last, fft_plan_fw2, fft_plan_fw2_last
1546 IF (mod(n1, 2) /= 0) cpabort(
"Parallel convolution:ERROR:n1")
1547 IF (mod(n2, 2) /= 0) cpabort(
"Parallel convolution:ERROR:n2")
1548 IF (mod(n3, 2) /= 0) cpabort(
"Parallel convolution:ERROR:n3")
1549 IF (nd1 < n1/2 + 1) cpabort(
"Parallel convolution:ERROR:nd1")
1550 IF (nd2 < n2/2 + 1) cpabort(
"Parallel convolution:ERROR:nd2")
1551 IF (nd3 < n3/2 + 1) cpabort(
"Parallel convolution:ERROR:nd3")
1552 IF (md1 < n1/2) cpabort(
"Parallel convolution:ERROR:md1")
1553 IF (md2 < n2/2) cpabort(
"Parallel convolution:ERROR:md2")
1554 IF (md3 < n3/2) cpabort(
"Parallel convolution:ERROR:md3")
1555 IF (mod(nd3, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:nd3")
1556 IF (mod(md2, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:md2")
1560 ncache = ncache_optimal
1561 IF (ncache <= max(n1, n2, n3/2)*4) ncache = max(n1, n2, n3/2)*4
1563 IF (mod(n2/2, 2) == 0) lzt = lzt + 1
1564 IF (mod(n2/2, 4) == 0) lzt = lzt + 1
1567 CALL fft_alloc(zw1, [ncache/4])
1568 zw1 = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1569 CALL fft_alloc(zw2, [ncache/4])
1570 zw2 = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1571 CALL fft_alloc(zt, [lzt, n1])
1572 zt = cmplx(0.0_dp, 0.0_dp, kind=
dp)
1573 ALLOCATE (zmpi2(n1, md2/nproc, nd3), source=cmplx(0.0_dp, 0.0_dp,
dp))
1574 ALLOCATE (cosinarr(2, n3/2), source=0.0_dp)
1575 IF (nproc > 1)
ALLOCATE (zmpi1(n1, md2/nproc, nd3/nproc, nproc), source=cmplx(0.0_dp, 0.0_dp,
dp))
1578 twopion = 8._dp*atan(1._dp)/real(n3, kind=
dp)
1580 cosinarr(1, i3) = cos(twopion*(i3 - 1))
1581 cosinarr(2, i3) = -sin(twopion*(i3 - 1))
1585 lot1 = ncache/(4*n1)
1586 lot2 = ncache/(4*n2)
1587 lot3 = ncache/(2*n3)
1590 final_chunk_size1 = mod(n2/2, lot1)
1591 final_chunk_size2 = mod(n1, lot2)
1592 final_chunk_size3 = mod(n1/2, lot3)
1595 IF (n2/2 >= lot1)
THEN
1599 IF (final_chunk_size1 > 0)
THEN
1601 final_chunk_size1, zw1, zt)
1603 final_chunk_size1, zt, zw1)
1607 IF (n1 >= lot2)
THEN
1611 IF (final_chunk_size2 > 0)
THEN
1613 final_chunk_size2, zw1, zw2)
1615 final_chunk_size2, zw2, zw1)
1619 IF (n1/2 >= lot3)
THEN
1623 IF (final_chunk_size3 > 0)
THEN
1625 lot3, lot3, n3/2, final_chunk_size3, zw1, zw2)
1627 lot3, lot3, n3/2, final_chunk_size3, zw1, zw2)
1630 DO j2 = 1, md2/nproc
1632 IF (iproc*(md2/nproc) + j2 <= n2/2)
THEN
1633 DO i1 = 1, (n1/2), lot3
1635 mb = min(i1 + (lot3 - 1), (n1/2))
1639 CALL halfill_upcorn(md1, md3, lot3, nfft, n3, zf(i1, 1, j2), zw1)
1644 IF (nfft == lot3)
THEN
1645 CALL fft_1d(fft_plan_bw3, zw1, zw2, 1.0_dp, stat)
1647 CALL fft_1d(fft_plan_bw3_last, zw1, zw2, 1.0_dp, stat)
1654 CALL scramble_unpack(i1, j2, lot3, nfft, n1/2, n3, md2, nproc, nd3, zw2, zmpi2, cosinarr)
1664 CALL mpi_group%alltoall(zmpi2, zmpi1, n1/2*(md2/nproc)*(nd3/nproc))
1669 DO j3 = 1, nd3/nproc
1671 IF (iproc*(nd3/nproc) + j3 <= n3/2 + 1)
THEN
1679 DO j = 1, n2/2, lot1
1681 mb = min(j + (lot1 - 1), n2/2)
1686 IF (nproc == 1)
THEN
1687 CALL mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot1, n1, md2, nd3, nproc, zmpi2, zw1)
1689 CALL mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot1, n1, md2, nd3, nproc, zmpi1, zw1)
1696 IF (nfft == lot1)
THEN
1697 CALL fft_1d(fft_plan_bw1, zw1, zt(j:, 1), 1.0_dp, stat)
1699 CALL fft_1d(fft_plan_bw1_last, zw1, zt(j:, 1), 1.0_dp, stat)
1708 mb = min(j + (lot2 - 1), n1)
1713 CALL switch_upcorn(nfft, n2, lot2, n1, lzt, zt(:, j), zw1)
1719 IF (nfft == lot2)
THEN
1720 CALL fft_1d(fft_plan_bw2, zw1, zw2, 1.0_dp, stat)
1722 CALL fft_1d(fft_plan_bw2_last, zw1, zw2, 1.0_dp, stat)
1727 CALL multkernel(nd1, nd2, n1, n2, lot2, nfft, j, pot(1, 1, j3), zw2)
1734 IF (nfft == lot2)
THEN
1735 CALL fft_1d(fft_plan_fw2, zw2, zw1, 1.0_dp, stat)
1737 CALL fft_1d(fft_plan_fw2_last, zw2, zw1, 1.0_dp, stat)
1742 CALL unswitch_downcorn(nfft, n2, lot2, n1, lzt, zw1, zt(:, j))
1748 DO j = 1, n2/2, lot1
1750 mb = min(j + (lot1 - 1), n2/2)
1755 IF (nfft == lot1)
THEN
1756 CALL fft_1d(fft_plan_fw1, zt(j:, 1), zw2, 1.0_dp, stat)
1758 CALL fft_1d(fft_plan_fw1_last, zt(j:, 1), zw2, 1.0_dp, stat)
1764 IF (nproc == 1)
THEN
1765 CALL unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot1, n1, md2, nd3, nproc, zw2, zmpi2)
1767 CALL unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot1, n1, md2, nd3, nproc, zw2, zmpi1)
1778 CALL mpi_group%alltoall(zmpi1, zmpi2, n1/2*(md2/nproc)*(nd3/nproc))
1784 DO j2 = 1, md2/nproc
1786 IF (iproc*(md2/nproc) + j2 <= n2/2)
THEN
1787 DO i1 = 1, (n1/2), lot3
1789 mb = min(i1 + (lot3 - 1), (n1/2))
1794 CALL unscramble_pack(i1, j2, lot3, nfft, n1/2, n3, md2, nproc, nd3, zmpi2, zw1, cosinarr)
1800 IF (nfft == lot3)
THEN
1801 CALL fft_1d(fft_plan_fw3, zw1, zw2, 1.0_dp, stat)
1803 CALL fft_1d(fft_plan_fw3_last, zw1, zw2, 1.0_dp, stat)
1808 CALL unfill_downcorn(md1, md3, lot3, nfft, n3, zw2, zf(i1, 1, j2), scal)
1830 CALL fft_dealloc(zw1)
1831 CALL fft_dealloc(zw2)
1832 CALL fft_dealloc(zt)
1833 DEALLOCATE (cosinarr)
1834 IF (nproc > 1)
DEALLOCATE (zmpi1)
1848 PURE SUBROUTINE switch_upcorn(nfft, n2, lot, n1, lzt, zt, zw)
1849 INTEGER,
INTENT(IN) :: nfft, n2, lot, n1, lzt
1850 COMPLEX(KIND=dp),
INTENT(IN) :: zt(lzt, n1)
1851 COMPLEX(KIND=dp),
INTENT(INOUT) :: zw(lot, n2)
1861 zw(j, i) = zt(i - n2/2, j)
1867 zw(j, i) = cmplx(0.0_dp, 0.0_dp,
dp)
1870 END SUBROUTINE switch_upcorn
1886 PURE SUBROUTINE mpiswitch_upcorn(j3, nfft, Jp2stb, J2stb, lot, n1, md2, nd3, nproc, zmpi1, zw)
1887 INTEGER,
INTENT(IN) :: j3, nfft
1888 INTEGER,
INTENT(INOUT) :: jp2stb, j2stb
1889 INTEGER,
INTENT(IN) :: lot, n1, md2, nd3, nproc
1890 COMPLEX(KIND=dp),
INTENT(IN) :: zmpi1(n1/2, md2/nproc, nd3/nproc, nproc)
1891 COMPLEX(KIND=dp),
INTENT(INOUT) :: zw(lot, n1)
1893 INTEGER :: i1, j2, jp2, mfft
1899 main:
DO jp2 = jp2stb, nproc
1900 DO j2 = j2stb, md2/nproc
1902 IF (mfft > nfft)
THEN
1908 zw(mfft, i1) = cmplx(0.0_dp, 0.0_dp,
dp)
1910 DO i1 = n1/2 + 1, n1
1911 zw(mfft, i1) = zmpi1(i1 - n1/2, j2, j3, jp2)
1916 END SUBROUTINE mpiswitch_upcorn
1928 PURE SUBROUTINE unswitch_downcorn(nfft, n2, lot, n1, lzt, zw, zt)
1929 INTEGER,
INTENT(IN) :: nfft, n2, lot, n1, lzt
1930 COMPLEX(KIND=dp),
INTENT(IN) :: zw(lot, n2)
1931 COMPLEX(KIND=dp),
INTENT(INOUT) :: zt(lzt, n1)
1945 END SUBROUTINE unswitch_downcorn
1961 PURE SUBROUTINE unmpiswitch_downcorn(j3, nfft, Jp2stf, J2stf, lot, n1, md2, nd3, nproc, zw, zmpi1)
1962 INTEGER,
INTENT(IN) :: j3, nfft
1963 INTEGER,
INTENT(INOUT) :: jp2stf, j2stf
1964 INTEGER,
INTENT(IN) :: lot, n1, md2, nd3, nproc
1965 COMPLEX(KIND=dp),
INTENT(IN) :: zw(lot, n1)
1966 COMPLEX(KIND=dp),
INTENT(INOUT) :: zmpi1(n1/2, md2/nproc, nd3/nproc, nproc)
1968 INTEGER :: i1, j2, jp2, mfft
1974 main:
DO jp2 = jp2stf, nproc
1975 DO j2 = j2stf, md2/nproc
1977 IF (mfft > nfft)
THEN
1983 zmpi1(i1, j2, j3, jp2) = zw(mfft, i1)
1988 END SUBROUTINE unmpiswitch_downcorn
2016 PURE SUBROUTINE f_unfill_downcorn(md1, md3, lot, nfft, n3, zw, zf, scal, ehartreetmp)
2017 INTEGER,
INTENT(in) :: md1, md3, lot, nfft, n3
2018 COMPLEX(KIND=dp),
DIMENSION(lot, n3/2),
INTENT(in) :: zw
2019 REAL(kind=
dp),
DIMENSION(md1, md3),
INTENT(inout) :: zf
2020 REAL(kind=
dp),
INTENT(in) :: scal
2021 REAL(kind=
dp),
INTENT(out) :: ehartreetmp
2024 REAL(kind=
dp) :: pot1
2029 pot1 = scal*real(zw(i1, i3),
dp)
2030 ehartreetmp = ehartreetmp + pot1*zf(i1, 2*i3 - 1)
2031 zf(i1, 2*i3 - 1) = pot1
2032 pot1 = scal*aimag(zw(i1, i3))
2033 ehartreetmp = ehartreetmp + pot1*zf(i1, 2*i3)
2037 END SUBROUTINE f_unfill_downcorn
int main(int argc, char *argv[])
Stand-alone miniapp for smoke-testing and benchmarking dbm_multiply.
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 s_poissonsolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, pot, zf, scal, mpi_group)
!HERE POT MUST BE THE KERNEL (BEWARE THE HALF DIMENSION) ****h* BigDFT/S_PoissonSolver (Based on suit...
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...
subroutine, public f_poissonsolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, pot, zf, scal, mpi_group)
(Based on suitable modifications of S.Goedecker routines) Applies the local FFT space Kernel to the d...
subroutine, public p_poissonsolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, zf, scal, hx, hy, hz, mpi_group)
...