20#include "../base/base_uses.f90"
26 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'ps_wavelet_base'
52 SUBROUTINE p_poissonsolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, zf &
53 , scal, hx, hy, hz, mpi_group)
54 INTEGER,
INTENT(in) :: n1, n2, n3, nd1, nd2, nd3, md1, md2, &
56 REAL(kind=
dp),
DIMENSION(md1, md3, md2/nproc), &
58 REAL(kind=
dp),
INTENT(in) :: scal, hx, hy, hz
62 INTEGER,
PARAMETER :: ncache_optimal = 8*1024
64 INTEGER :: i, i1, i3, ic1, ic2, ic3, inzee, j, j2, &
65 j2stb, j2stf, j3, jp2stb, jp2stf, lot, &
66 lzt, ma, mb, ncache, nfft
67 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: after1, after2, after3, before1, &
68 before2, before3, now1, now2, now3
69 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: btrig1, btrig2, btrig3, ftrig1, ftrig2, &
71 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: zt, zw
72 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :, :) :: zmpi2
73 REAL(kind=
dp),
ALLOCATABLE, &
74 DIMENSION(:, :, :, :, :) :: zmpi1
76 IF (nd1 < n1/2 + 1) cpabort(
"Parallel convolution:ERROR:nd1")
77 IF (nd2 < n2/2 + 1) cpabort(
"Parallel convolution:ERROR:nd2")
78 IF (nd3 < n3/2 + 1) cpabort(
"Parallel convolution:ERROR:nd3")
79 IF (md1 < n1) cpabort(
"Parallel convolution:ERROR:md1")
80 IF (md2 < n2) cpabort(
"Parallel convolution:ERROR:md2")
81 IF (md3 < n3) cpabort(
"Parallel convolution:ERROR:md3")
82 IF (mod(nd3, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:nd3")
83 IF (mod(md2, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:md2")
86 ncache = ncache_optimal
87 IF (ncache <= max(n1, n2, n3)*4) ncache = max(n1, n2, n3)*4
90 IF (mod(n2, 2) == 0) lzt = lzt + 1
91 IF (mod(n2, 4) == 0) lzt = lzt + 1
103 ALLOCATE (before2(7))
108 ALLOCATE (before3(7))
109 ALLOCATE (zw(2, ncache/4, 2))
110 ALLOCATE (zt(2, lzt, n1))
111 ALLOCATE (zmpi2(2, n1, md2/nproc, nd3))
112 IF (nproc > 1)
ALLOCATE (zmpi1(2, n1, md2/nproc, nd3/nproc, nproc))
115 CALL ctrig(n3, btrig3, after3, before3, now3, 1, ic3)
116 CALL ctrig(n1, btrig1, after1, before1, now1, 1, ic1)
117 CALL ctrig(n2, btrig2, after2, before2, now2, 1, ic2)
119 ftrig1(1, j) = btrig1(1, j)
120 ftrig1(2, j) = -btrig1(2, j)
123 ftrig2(1, j) = btrig2(1, j)
124 ftrig2(2, j) = -btrig2(2, j)
127 ftrig3(1, j) = btrig3(1, j)
128 ftrig3(2, j) = -btrig3(2, j)
134 CALL cp_abort(__location__, &
135 'convolxc_off:ncache has to be enlarged to be able to hold at '// &
136 'least one 1-d FFT of this size even though this will '// &
137 'reduce the performance for shorter transform lengths')
141 IF (iproc*(md2/nproc) + j2 <= n2)
THEN
144 mb = min(i1 + (lot - 1), n1)
147 CALL p_fill_upcorn(md1, md3, lot, nfft, n3, zf(i1, 1, j2), zw(1, 1, 1))
153 CALL fftstp(lot, nfft, n3, lot, n3, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
154 btrig3, after3(i), now3(i), before3(i), 1)
161 CALL scramble_p(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zw(1, 1, inzee), zmpi2)
171 CALL mpi_group%alltoall(zmpi2, zmpi1, 2*n1*(md2/nproc)*(nd3/nproc))
178 IF (iproc*(nd3/nproc) + j3 <= n3/2 + 1)
THEN
187 CALL cp_abort(__location__, &
188 'convolxc_off:ncache has to be enlarged to be able to hold at '// &
189 'least one 1-d FFT of this size even though this will '// &
190 'reduce the performance for shorter transform lengths')
195 mb = min(j + (lot - 1), n2)
201 CALL p_mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot, n1, md2, nd3, nproc, zmpi2, zw(1, 1, 1))
203 CALL p_mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot, n1, md2, nd3, nproc, zmpi1, zw(1, 1, 1))
211 CALL fftstp(lot, nfft, n1, lot, n1, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
212 btrig1, after1(i), now1(i), before1(i), 1)
218 CALL fftstp(lot, nfft, n1, lzt, n1, zw(1, 1, inzee), zt(1, j, 1), &
219 btrig1, after1(i), now1(i), before1(i), 1)
226 CALL cp_abort(__location__, &
227 'convolxc_off:ncache has to be enlarged to be able to hold at '// &
228 'least one 1-d FFT of this size even though this will '// &
229 'reduce the performance for shorter transform lengths')
234 mb = min(j + (lot - 1), n1)
239 CALL p_switch_upcorn(nfft, n2, lot, n1, lzt, zt(1, 1, j), zw(1, 1, 1))
246 CALL fftstp(lot, nfft, n2, lot, n2, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
247 btrig2, after2(i), now2(i), before2(i), 1)
253 i3 = iproc*(nd3/nproc) + j3
254 CALL p_multkernel(n1, n2, n3, lot, nfft, j, i3, zw(1, 1, inzee), hx, hy, hz)
261 CALL fftstp(lot, nfft, n2, lot, n2, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
262 ftrig2, after2(i), now2(i), before2(i), -1)
268 CALL p_unswitch_downcorn(nfft, n2, lot, n1, lzt, zw(1, 1, inzee), zt(1, 1, j))
277 mb = min(j + (lot - 1), n2)
282 CALL fftstp(lzt, nfft, n1, lot, n1, zt(1, j, 1), zw(1, 1, 1), &
283 ftrig1, after1(i), now1(i), before1(i), -1)
287 CALL fftstp(lot, nfft, n1, lot, n1, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
288 ftrig1, after1(i), now1(i), before1(i), -1)
296 CALL p_unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot, n1, md2, nd3, nproc, zw(1, 1, inzee), zmpi2)
298 CALL p_unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot, n1, md2, nd3, nproc, zw(1, 1, inzee), zmpi1)
309 CALL mpi_group%alltoall(zmpi1, zmpi2, 2*n1*(md2/nproc)*(nd3/nproc))
317 IF (iproc*(md2/nproc) + j2 <= n2)
THEN
320 mb = min(i1 + (lot - 1), n1)
325 CALL unscramble_p(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zmpi2, zw(1, 1, 1))
332 CALL fftstp(lot, nfft, n3, lot, n3, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
333 ftrig3, after3(i), now3(i), before3(i), -1)
339 CALL p_unfill_downcorn(md1, md3, lot, nfft, n3, zw(1, 1, inzee), zf(i1, 1, j2), scal)
364 IF (nproc > 1)
DEALLOCATE (zmpi1)
382 SUBROUTINE p_mpiswitch_upcorn(j3, nfft, Jp2stb, J2stb, lot, n1, md2, nd3, nproc, zmpi1, zw)
383 INTEGER,
INTENT(in) :: j3, nfft
384 INTEGER,
INTENT(inout) :: jp2stb, j2stb
385 INTEGER,
INTENT(in) :: lot, n1, md2, nd3, nproc
387 DIMENSION(2, n1, md2/nproc, nd3/nproc, nproc), &
389 REAL(kind=
dp),
DIMENSION(2, lot, n1), &
392 INTEGER :: i1, j2, jp2, mfft
395 DO jp2 = jp2stb, nproc
396 DO j2 = j2stb, md2/nproc
398 IF (mfft > nfft)
THEN
404 zw(1, mfft, i1) = zmpi1(1, i1, j2, j3, jp2)
405 zw(2, mfft, i1) = zmpi1(2, i1, j2, j3, jp2)
410 END SUBROUTINE p_mpiswitch_upcorn
422 SUBROUTINE p_switch_upcorn(nfft, n2, lot, n1, lzt, zt, zw)
423 INTEGER,
INTENT(in) :: nfft, n2, lot, n1, lzt
424 REAL(kind=
dp),
DIMENSION(2, lzt, n1),
INTENT(in) :: zt
425 REAL(kind=
dp),
DIMENSION(2, lot, n2), &
432 zw(1, j, i) = zt(1, i, j)
433 zw(2, j, i) = zt(2, i, j)
437 END SUBROUTINE p_switch_upcorn
449 SUBROUTINE p_unswitch_downcorn(nfft, n2, lot, n1, lzt, zw, zt)
450 INTEGER,
INTENT(in) :: nfft, n2, lot, n1, lzt
451 REAL(kind=
dp),
DIMENSION(2, lot, n2),
INTENT(in) :: zw
452 REAL(kind=
dp),
DIMENSION(2, lzt, n1), &
459 zt(1, i, j) = zw(1, j, i)
460 zt(2, i, j) = zw(2, j, i)
464 END SUBROUTINE p_unswitch_downcorn
480 SUBROUTINE p_unmpiswitch_downcorn(j3, nfft, Jp2stf, J2stf, lot, n1, md2, nd3, nproc, zw, zmpi1)
481 INTEGER,
INTENT(in) :: j3, nfft
482 INTEGER,
INTENT(inout) :: jp2stf, j2stf
483 INTEGER,
INTENT(in) :: lot, n1, md2, nd3, nproc
484 REAL(kind=
dp),
DIMENSION(2, lot, n1),
INTENT(in) :: zw
486 DIMENSION(2, n1, md2/nproc, nd3/nproc, nproc), &
487 INTENT(inout) :: zmpi1
489 INTEGER :: i1, j2, jp2, mfft
492 DO jp2 = jp2stf, nproc
493 DO j2 = j2stf, md2/nproc
495 IF (mfft > nfft)
THEN
501 zmpi1(1, i1, j2, j3, jp2) = zw(1, mfft, i1)
502 zmpi1(2, i1, j2, j3, jp2) = zw(2, mfft, i1)
507 END SUBROUTINE p_unmpiswitch_downcorn
533 SUBROUTINE p_unfill_downcorn(md1, md3, lot, nfft, n3, zw, zf, scal)
534 INTEGER,
INTENT(in) :: md1, md3, lot, nfft, n3
535 REAL(kind=
dp),
DIMENSION(2, lot, n3),
INTENT(in) :: zw
536 REAL(kind=
dp),
DIMENSION(md1, md3),
INTENT(inout) :: zf
537 REAL(kind=
dp),
INTENT(in) :: scal
540 REAL(kind=
dp) :: pot1
544 pot1 = scal*zw(1, i1, i3)
549 END SUBROUTINE p_unfill_downcorn
561 SUBROUTINE p_fill_upcorn(md1, md3, lot, nfft, n3, zf, zw)
562 INTEGER,
INTENT(in) :: md1, md3, lot, nfft, n3
563 REAL(kind=
dp),
DIMENSION(md1, md3),
INTENT(in) :: zf
564 REAL(kind=
dp),
DIMENSION(2, lot, n3), &
571 zw(1, i1, i3) = zf(i1, i3)
572 zw(2, i1, i3) = 0._dp
576 END SUBROUTINE p_fill_upcorn
603 SUBROUTINE scramble_p(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zw, zmpi2)
604 INTEGER,
INTENT(in) :: i1, j2, lot, nfft, n1, n3, md2, nproc, &
606 REAL(kind=
dp),
DIMENSION(2, lot, n3),
INTENT(in) :: zw
607 REAL(kind=
dp),
DIMENSION(2, n1, md2/nproc, nd3), &
608 INTENT(inout) :: zmpi2
614 zmpi2(1, i1 + i, j2, i3) = zw(1, i + 1, i3)
615 zmpi2(2, i1 + i, j2, i3) = zw(2, i + 1, i3)
619 END SUBROUTINE scramble_p
646 SUBROUTINE unscramble_p(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zmpi2, zw)
647 INTEGER,
INTENT(in) :: i1, j2, lot, nfft, n1, n3, md2, nproc, &
649 REAL(kind=
dp),
DIMENSION(2, n1, md2/nproc, nd3), &
651 REAL(kind=
dp),
DIMENSION(2, lot, n3), &
658 zw(1, i + 1, i3) = zmpi2(1, i1 + i, j2, i3)
659 zw(2, i + 1, i3) = zmpi2(2, i1 + i, j2, i3)
665 zw(1, i + 1, j3) = zmpi2(1, i1 + i, j2, i3)
666 zw(2, i + 1, j3) = -zmpi2(2, i1 + i, j2, i3)
667 zw(1, i + 1, i3) = zmpi2(1, i1 + i, j2, i3)
668 zw(2, i + 1, i3) = zmpi2(2, i1 + i, j2, i3)
672 END SUBROUTINE unscramble_p
702 SUBROUTINE p_multkernel(n1, n2, n3, lot, nfft, jS, i3, zw, hx, hy, hz)
703 INTEGER,
INTENT(in) :: n1, n2, n3, lot, nfft, js, i3
704 REAL(kind=
dp),
DIMENSION(2, lot, n2), &
706 REAL(kind=
dp),
INTENT(in) :: hx, hy, hz
708 INTEGER :: i1, i2, j1, j2, j3
709 REAL(kind=
dp) :: fourpi2, ker, mu3, p1, p2
711 fourpi2 = 4._dp*
pi**2
713 mu3 = real(j3 - 1, kind=
dp)/real(n3, kind=
dp)
720 j1 = j1 - (j1/(n1/2 + 2))*n1
721 j2 = i2 - (i2/(n2/2 + 2))*n2
722 p1 = real(j1 - 1, kind=
dp)/real(n1, kind=
dp)
723 p2 = real(j2 - 1, kind=
dp)/real(n2, kind=
dp)
724 ker = -fourpi2*((p1/hx)**2 + (p2/hz)**2 + mu3)
725 IF (ker /= 0._dp) ker = 1._dp/ker
726 zw(1, i1, i2) = zw(1, i1, i2)*ker
727 zw(2, i1, i2) = zw(2, i1, i2)*ker
731 END SUBROUTINE p_multkernel
759 SUBROUTINE multkernel(nd1, nd2, n1, n2, lot, nfft, jS, pot, zw)
760 INTEGER,
INTENT(in) :: nd1, nd2, n1, n2, lot, nfft, js
761 REAL(kind=
dp),
DIMENSION(nd1, nd2),
INTENT(in) :: pot
762 REAL(kind=
dp),
DIMENSION(2, lot, n2), &
765 INTEGER :: i2, j, j1, j2
769 j1 = j1 + (j1/(n1/2 + 2))*(n1 + 2 - 2*j1)
770 zw(1, j, 1) = zw(1, j, 1)*pot(j1, 1)
771 zw(2, j, 1) = zw(2, j, 1)*pot(j1, 1)
778 j1 = j1 + (j1/(n1/2 + 2))*(n1 + 2 - 2*j1)
780 zw(1, j, i2) = zw(1, j, i2)*pot(j1, i2)
781 zw(2, j, i2) = zw(2, j, i2)*pot(j1, i2)
782 zw(1, j, j2) = zw(1, j, j2)*pot(j1, i2)
783 zw(2, j, j2) = zw(2, j, j2)*pot(j1, i2)
790 j1 = j1 + (j1/(n1/2 + 2))*(n1 + 2 - 2*j1)
792 zw(1, j, j2) = zw(1, j, j2)*pot(j1, j2)
793 zw(2, j, j2) = zw(2, j, j2)*pot(j1, j2)
796 END SUBROUTINE multkernel
837 SUBROUTINE s_poissonsolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, pot, zf, &
839 INTEGER,
INTENT(in) :: n1, n2, n3, nd1, nd2, nd3, md1, md2, &
841 REAL(kind=
dp),
DIMENSION(nd1, nd2, nd3/nproc), &
843 REAL(kind=
dp),
DIMENSION(md1, md3, md2/nproc), &
845 REAL(kind=
dp),
INTENT(in) :: scal
849 CHARACTER(len=*),
PARAMETER :: routinen =
'S_PoissonSolver'
850 INTEGER,
PARAMETER :: ncache_optimal = 8*1024
852 INTEGER :: handle, i, i1, i3, ic1, ic2, ic3, inzee, &
853 j, j2, j2stb, j2stf, j3, jp2stb, &
854 jp2stf, lot, lzt, ma, mb, ncache, nfft
855 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: after1, after2, after3, before1, &
856 before2, before3, now1, now2, now3
857 REAL(kind=
dp) :: twopion
858 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: btrig1, btrig2, btrig3, cosinarr, &
859 ftrig1, ftrig2, ftrig3
860 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: zt, zw
861 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :, :) :: zmpi2
862 REAL(kind=
dp),
ALLOCATABLE, &
863 DIMENSION(:, :, :, :, :) :: zmpi1
865 CALL timeset(routinen, handle)
867 IF (mod(n3, 2) /= 0) cpabort(
"Parallel convolution:ERROR:n3")
868 IF (nd1 < n1/2 + 1) cpabort(
"Parallel convolution:ERROR:nd1")
869 IF (nd2 < n2/2 + 1) cpabort(
"Parallel convolution:ERROR:nd2")
870 IF (nd3 < n3/2 + 1) cpabort(
"Parallel convolution:ERROR:nd3")
871 IF (md1 < n1) cpabort(
"Parallel convolution:ERROR:md1")
872 IF (md2 < n2) cpabort(
"Parallel convolution:ERROR:md2")
873 IF (md3 < n3/2) cpabort(
"Parallel convolution:ERROR:md3")
874 IF (mod(nd3, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:nd3")
875 IF (mod(md2, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:md2")
878 ncache = ncache_optimal
879 IF (ncache <= max(n1, n2, n3/2)*4) ncache = max(n1, n2, n3/2)*4
884 IF (mod(n2, 2) == 0) lzt = lzt + 1
885 IF (mod(n2, 4) == 0) lzt = lzt + 1
892 ALLOCATE (before1(7))
897 ALLOCATE (before2(7))
902 ALLOCATE (before3(7))
903 ALLOCATE (zw(2, ncache/4, 2))
904 ALLOCATE (zt(2, lzt, n1))
905 ALLOCATE (zmpi2(2, n1, md2/nproc, nd3))
906 ALLOCATE (cosinarr(2, n3/2))
908 ALLOCATE (zmpi1(2, n1, md2/nproc, nd3/nproc, nproc))
916 CALL ctrig(n3/2, btrig3, after3, before3, now3, 1, ic3)
917 CALL ctrig(n1, btrig1, after1, before1, now1, 1, ic1)
918 CALL ctrig(n2, btrig2, after2, before2, now2, 1, ic2)
920 ftrig1(1, j) = btrig1(1, j)
921 ftrig1(2, j) = -btrig1(2, j)
924 ftrig2(1, j) = btrig2(1, j)
925 ftrig2(2, j) = -btrig2(2, j)
928 ftrig3(1, j) = btrig3(1, j)
929 ftrig3(2, j) = -btrig3(2, j)
933 twopion = 8._dp*atan(1._dp)/real(n3, kind=
dp)
935 cosinarr(1, i3) = cos(twopion*(i3 - 1))
936 cosinarr(2, i3) = -sin(twopion*(i3 - 1))
945 CALL cp_abort(__location__, &
946 'convolxc_off:ncache has to be enlarged to be able to hold at '// &
947 'least one 1-d FFT of this size even though this will '// &
948 'reduce the performance for shorter transform lengths')
953 IF (iproc*(md2/nproc) + j2 <= n2)
THEN
956 mb = min(i1 + (lot - 1), n1)
960 CALL halfill_upcorn(md1, md3, lot, nfft, n3, zf(i1, 1, j2), zw(1, 1, 1))
966 CALL fftstp(lot, nfft, n3/2, lot, n3/2, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
967 btrig3, after3(i), now3(i), before3(i), 1)
974 CALL scramble_unpack(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zw(1, 1, inzee), zmpi2, cosinarr)
982 CALL mpi_group%alltoall(zmpi2, zmpi1, 2*n1*(md2/nproc)*(nd3/nproc))
989 IF (iproc*(nd3/nproc) + j3 <= n3/2 + 1)
THEN
998 CALL cp_abort(__location__, &
999 'convolxc_off:ncache has to be enlarged to be able to hold at '// &
1000 'least one 1-d FFT of this size even though this will '// &
1001 'reduce the performance for shorter transform lengths')
1006 mb = min(j + (lot - 1), n2)
1011 IF (nproc == 1)
THEN
1012 CALL s_mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot, n1, md2, nd3, nproc, zmpi2, zw(1, 1, 1))
1014 CALL s_mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot, n1, md2, nd3, nproc, zmpi1, zw(1, 1, 1))
1022 CALL fftstp(lot, nfft, n1, lot, n1, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1023 btrig1, after1(i), now1(i), before1(i), 1)
1029 CALL fftstp(lot, nfft, n1, lzt, n1, zw(1, 1, inzee), zt(1, j, 1), &
1030 btrig1, after1(i), now1(i), before1(i), 1)
1037 CALL cp_abort(__location__, &
1038 'convolxc_off:ncache has to be enlarged to be able to hold at '// &
1039 'least one 1-d FFT of this size even though this will '// &
1040 'reduce the performance for shorter transform lengths')
1045 mb = min(j + (lot - 1), n1)
1050 CALL s_switch_upcorn(nfft, n2, lot, n1, lzt, zt(1, 1, j), zw(1, 1, 1))
1057 CALL fftstp(lot, nfft, n2, lot, n2, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1058 btrig2, after2(i), now2(i), before2(i), 1)
1064 CALL multkernel(nd1, nd2, n1, n2, lot, nfft, j, pot(1, 1, j3), zw(1, 1, inzee))
1071 CALL fftstp(lot, nfft, n2, lot, n2, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1072 ftrig2, after2(i), now2(i), before2(i), -1)
1078 CALL s_unswitch_downcorn(nfft, n2, lot, n1, lzt, zw(1, 1, inzee), zt(1, 1, j))
1087 mb = min(j + (lot - 1), n2)
1092 CALL fftstp(lzt, nfft, n1, lot, n1, zt(1, j, 1), zw(1, 1, 1), &
1093 ftrig1, after1(i), now1(i), before1(i), -1)
1097 CALL fftstp(lot, nfft, n1, lot, n1, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1098 ftrig1, after1(i), now1(i), before1(i), -1)
1105 IF (nproc == 1)
THEN
1106 CALL s_unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot, n1, md2, nd3, nproc, zw(1, 1, inzee), zmpi2)
1108 CALL s_unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot, n1, md2, nd3, nproc, zw(1, 1, inzee), zmpi1)
1119 CALL mpi_group%alltoall(zmpi1, zmpi2, 2*n1*(md2/nproc)*(nd3/nproc))
1127 DO j2 = 1, md2/nproc
1129 IF (iproc*(md2/nproc) + j2 <= n2)
THEN
1132 mb = min(i1 + (lot - 1), n1)
1137 CALL unscramble_pack(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zmpi2, zw(1, 1, 1), cosinarr)
1144 CALL fftstp(lot, nfft, n3/2, lot, n3/2, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1145 ftrig3, after3(i), now3(i), before3(i), -1)
1151 CALL unfill_downcorn(md1, md3, lot, nfft, n3, zw(1, 1, inzee), zf(i1, 1, j2) &
1165 DEALLOCATE (before1)
1170 DEALLOCATE (before2)
1175 DEALLOCATE (before3)
1179 DEALLOCATE (cosinarr)
1180 IF (nproc > 1)
DEALLOCATE (zmpi1)
1183 CALL timestop(handle)
1200 SUBROUTINE s_mpiswitch_upcorn(j3, nfft, Jp2stb, J2stb, lot, n1, md2, nd3, nproc, zmpi1, zw)
1201 INTEGER,
INTENT(in) :: j3, nfft
1202 INTEGER,
INTENT(inout) :: jp2stb, j2stb
1203 INTEGER,
INTENT(in) :: lot, n1, md2, nd3, nproc
1205 DIMENSION(2, n1, md2/nproc, nd3/nproc, nproc), &
1207 REAL(kind=
dp),
DIMENSION(2, lot, n1), &
1210 INTEGER :: i1, j2, jp2, mfft
1213 DO jp2 = jp2stb, nproc
1214 DO j2 = j2stb, md2/nproc
1216 IF (mfft > nfft)
THEN
1222 zw(1, mfft, i1) = zmpi1(1, i1, j2, j3, jp2)
1223 zw(2, mfft, i1) = zmpi1(2, i1, j2, j3, jp2)
1228 END SUBROUTINE s_mpiswitch_upcorn
1240 SUBROUTINE s_switch_upcorn(nfft, n2, lot, n1, lzt, zt, zw)
1241 INTEGER,
INTENT(in) :: nfft, n2, lot, n1, lzt
1242 REAL(kind=
dp),
DIMENSION(2, lzt, n1),
INTENT(in) :: zt
1243 REAL(kind=
dp),
DIMENSION(2, lot, n2), &
1250 zw(1, j, i) = zt(1, i, j)
1251 zw(2, j, i) = zt(2, i, j)
1254 END SUBROUTINE s_switch_upcorn
1266 SUBROUTINE s_unswitch_downcorn(nfft, n2, lot, n1, lzt, zw, zt)
1267 INTEGER,
INTENT(in) :: nfft, n2, lot, n1, lzt
1268 REAL(kind=
dp),
DIMENSION(2, lot, n2),
INTENT(in) :: zw
1269 REAL(kind=
dp),
DIMENSION(2, lzt, n1), &
1276 zt(1, i, j) = zw(1, j, i)
1277 zt(2, i, j) = zw(2, j, i)
1280 END SUBROUTINE s_unswitch_downcorn
1296 SUBROUTINE s_unmpiswitch_downcorn(j3, nfft, Jp2stf, J2stf, lot, n1, md2, nd3, nproc, zw, zmpi1)
1297 INTEGER,
INTENT(in) :: j3, nfft
1298 INTEGER,
INTENT(inout) :: jp2stf, j2stf
1299 INTEGER,
INTENT(in) :: lot, n1, md2, nd3, nproc
1300 REAL(kind=
dp),
DIMENSION(2, lot, n1),
INTENT(in) :: zw
1302 DIMENSION(2, n1, md2/nproc, nd3/nproc, nproc), &
1303 INTENT(inout) :: zmpi1
1305 INTEGER :: i1, j2, jp2, mfft
1308 DO jp2 = jp2stf, nproc
1309 DO j2 = j2stf, md2/nproc
1311 IF (mfft > nfft)
THEN
1317 zmpi1(1, i1, j2, j3, jp2) = zw(1, mfft, i1)
1318 zmpi1(2, i1, j2, j3, jp2) = zw(2, mfft, i1)
1323 END SUBROUTINE s_unmpiswitch_downcorn
1350 SUBROUTINE unfill_downcorn(md1, md3, lot, nfft, n3, zw, zf, scal)
1351 INTEGER,
INTENT(in) :: md1, md3, lot, nfft, n3
1352 REAL(kind=
dp),
DIMENSION(2, lot, n3/2),
INTENT(in) :: zw
1353 REAL(kind=
dp),
DIMENSION(md1, md3),
INTENT(inout) :: zf
1354 REAL(kind=
dp),
INTENT(in) :: scal
1357 REAL(kind=
dp) :: pot1
1361 pot1 = scal*zw(1, i1, i3)
1363 zf(i1, 2*i3 - 1) = pot1
1364 pot1 = scal*zw(2, i1, i3)
1369 END SUBROUTINE unfill_downcorn
1381 SUBROUTINE halfill_upcorn(md1, md3, lot, nfft, n3, zf, zw)
1382 INTEGER :: md1, md3, lot, nfft, n3
1383 REAL(kind=
dp) :: zf(md1, md3), zw(2, lot, n3/2)
1392 zw(1, i1, i3) = 0._dp
1393 zw(2, i1, i3) = 0._dp
1396 DO i3 = n3/4 + 1, n3/2
1398 zw(1, i1, i3) = zf(i1, 2*i3 - 1 - n3/2)
1399 zw(2, i1, i3) = zf(i1, 2*i3 - n3/2)
1403 END SUBROUTINE halfill_upcorn
1433 SUBROUTINE scramble_unpack(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zw, zmpi2, cosinarr)
1434 INTEGER,
INTENT(in) :: i1, j2, lot, nfft, n1, n3, md2, nproc, &
1436 REAL(kind=
dp),
DIMENSION(2, lot, n3/2),
INTENT(in) :: zw
1437 REAL(kind=
dp),
DIMENSION(2, n1, md2/nproc, nd3), &
1438 INTENT(inout) :: zmpi2
1439 REAL(kind=
dp),
DIMENSION(2, n3/2),
INTENT(in) :: cosinarr
1441 INTEGER :: i, i3, ind1, ind2
1442 REAL(kind=
dp) :: a, b, c, cp, d, fei, fer, fi, foi,
for, &
1450 zmpi2(1, i1 + i, j2, 1) = a + b
1451 zmpi2(2, i1 + i, j2, 1) = 0._dp
1452 zmpi2(1, i1 + i, j2, n3/2 + 1) = a - b
1453 zmpi2(2, i1 + i, j2, n3/2 + 1) = 0._dp
1458 ind2 = n3/2 - i3 + 2
1459 cp = cosinarr(1, i3)
1460 sp = cosinarr(2, i3)
1462 a = zw(1, i + 1, ind1)
1463 b = zw(2, i + 1, ind1)
1464 c = zw(1, i + 1, ind2)
1465 d = zw(2, i + 1, ind2)
1470 fr = fer + cp*foi -
sp*
for
1471 fi = fei - cp*
for -
sp*foi
1472 zmpi2(1, i1 + i, j2, ind1) = fr
1473 zmpi2(2, i1 + i, j2, ind1) = fi
1507 SUBROUTINE unscramble_pack(i1, j2, lot, nfft, n1, n3, md2, nproc, nd3, zmpi2, zw, cosinarr)
1508 INTEGER,
INTENT(in) :: i1, j2, lot, nfft, n1, n3, md2, nproc, &
1510 REAL(kind=
dp),
DIMENSION(2, n1, md2/nproc, nd3), &
1512 REAL(kind=
dp),
DIMENSION(2, lot, n3/2), &
1514 REAL(kind=
dp),
DIMENSION(2, n3/2),
INTENT(in) :: cosinarr
1516 INTEGER :: i, i3, inda, indb
1517 REAL(kind=
dp) :: a, b, c, cp, d, ie, ih, io, re, rh, ro, &
1522 indb = n3/2 + 2 - i3
1523 cp = cosinarr(1, i3)
1524 sp = cosinarr(2, i3)
1526 a = zmpi2(1, i1 + i, j2, inda)
1527 b = zmpi2(2, i1 + i, j2, inda)
1528 c = zmpi2(1, i1 + i, j2, indb)
1529 d = -zmpi2(2, i1 + i, j2, indb)
1532 ro = (a - c)*cp - (b - d)*
sp
1533 io = (a - c)*
sp + (b - d)*cp
1536 zw(1, i + 1, inda) = rh
1537 zw(2, i + 1, inda) = ih
1541 END SUBROUTINE unscramble_pack
1581 SUBROUTINE f_poissonsolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, pot, zf, &
1583 INTEGER,
INTENT(in) :: n1, n2, n3, nd1, nd2, nd3, md1, md2, &
1585 REAL(kind=
dp),
DIMENSION(nd1, nd2, nd3/nproc), &
1587 REAL(kind=
dp),
DIMENSION(md1, md3, md2/nproc), &
1589 REAL(kind=
dp),
INTENT(in) :: scal
1593 INTEGER,
PARAMETER :: ncache_optimal = 8*1024
1595 INTEGER :: i, i1, i3, ic1, ic2, ic3, inzee, j, j2, &
1596 j2stb, j2stf, j3, jp2stb, jp2stf, lot, &
1597 lzt, ma, mb, ncache, nfft
1598 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: after1, after2, after3, before1, &
1599 before2, before3, now1, now2, now3
1600 REAL(kind=
dp) :: twopion
1601 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: btrig1, btrig2, btrig3, cosinarr, &
1602 ftrig1, ftrig2, ftrig3
1603 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: zt, zw
1604 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :, :) :: zmpi2
1605 REAL(kind=
dp),
ALLOCATABLE, &
1606 DIMENSION(:, :, :, :, :) :: zmpi1
1608 IF (mod(n1, 2) /= 0) cpabort(
"Parallel convolution:ERROR:n1")
1609 IF (mod(n2, 2) /= 0) cpabort(
"Parallel convolution:ERROR:n2")
1610 IF (mod(n3, 2) /= 0) cpabort(
"Parallel convolution:ERROR:n3")
1611 IF (nd1 < n1/2 + 1) cpabort(
"Parallel convolution:ERROR:nd1")
1612 IF (nd2 < n2/2 + 1) cpabort(
"Parallel convolution:ERROR:nd2")
1613 IF (nd3 < n3/2 + 1) cpabort(
"Parallel convolution:ERROR:nd3")
1614 IF (md1 < n1/2) cpabort(
"Parallel convolution:ERROR:md1")
1615 IF (md2 < n2/2) cpabort(
"Parallel convolution:ERROR:md2")
1616 IF (md3 < n3/2) cpabort(
"Parallel convolution:ERROR:md3")
1617 IF (mod(nd3, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:nd3")
1618 IF (mod(md2, nproc) /= 0) cpabort(
"Parallel convolution:ERROR:md2")
1622 ncache = ncache_optimal
1623 IF (ncache <= max(n1, n2, n3/2)*4) ncache = max(n1, n2, n3/2)*4
1625 IF (mod(n2/2, 2) == 0) lzt = lzt + 1
1626 IF (mod(n2/2, 4) == 0) lzt = lzt + 1
1631 ALLOCATE (after1(7))
1633 ALLOCATE (before1(7))
1636 ALLOCATE (after2(7))
1638 ALLOCATE (before2(7))
1641 ALLOCATE (after3(7))
1643 ALLOCATE (before3(7))
1644 ALLOCATE (zw(2, ncache/4, 2))
1645 ALLOCATE (zt(2, lzt, n1))
1646 ALLOCATE (zmpi2(2, n1, md2/nproc, nd3))
1648 ALLOCATE (cosinarr(2, n3/2))
1649 IF (nproc > 1)
ALLOCATE (zmpi1(2, n1, md2/nproc, nd3/nproc, nproc))
1652 CALL ctrig(n3/2, btrig3, after3, before3, now3, 1, ic3)
1653 CALL ctrig(n1, btrig1, after1, before1, now1, 1, ic1)
1654 CALL ctrig(n2, btrig2, after2, before2, now2, 1, ic2)
1656 ftrig1(1, j) = btrig1(1, j)
1657 ftrig1(2, j) = -btrig1(2, j)
1660 ftrig2(1, j) = btrig2(1, j)
1661 ftrig2(2, j) = -btrig2(2, j)
1664 ftrig3(1, j) = btrig3(1, j)
1665 ftrig3(2, j) = -btrig3(2, j)
1669 twopion = 8._dp*atan(1._dp)/real(n3, kind=
dp)
1671 cosinarr(1, i3) = cos(twopion*(i3 - 1))
1672 cosinarr(2, i3) = -sin(twopion*(i3 - 1))
1678 CALL cp_abort(__location__, &
1679 'convolxc_on:ncache has to be enlarged to be able to hold at '// &
1680 'least one 1-d FFT of this size even though this will '// &
1681 'reduce the performance for shorter transform lengths')
1684 DO j2 = 1, md2/nproc
1686 IF (iproc*(md2/nproc) + j2 <= n2/2)
THEN
1687 DO i1 = 1, (n1/2), lot
1689 mb = min(i1 + (lot - 1), (n1/2))
1693 CALL halfill_upcorn(md1, md3, lot, nfft, n3, zf(i1, 1, j2), zw(1, 1, 1))
1699 CALL fftstp(lot, nfft, n3/2, lot, n3/2, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1700 btrig3, after3(i), now3(i), before3(i), 1)
1708 CALL scramble_unpack(i1, j2, lot, nfft, n1/2, n3, md2, nproc, nd3, zw(1, 1, inzee), zmpi2, cosinarr)
1718 CALL mpi_group%alltoall(zmpi2, zmpi1, n1*(md2/nproc)*(nd3/nproc))
1723 DO j3 = 1, nd3/nproc
1725 IF (iproc*(nd3/nproc) + j3 <= n3/2 + 1)
THEN
1734 CALL cp_abort(__location__, &
1735 'convolxc_on:ncache has to be enlarged to be able to hold at '// &
1736 'least one 1-d FFT of this size even though this will '// &
1737 'reduce the performance for shorter transform lengths')
1742 mb = min(j + (lot - 1), n2/2)
1747 IF (nproc == 1)
THEN
1748 CALL mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot, n1, md2, nd3, nproc, zmpi2, zw(1, 1, 1))
1750 CALL mpiswitch_upcorn(j3, nfft, jp2stb, j2stb, lot, n1, md2, nd3, nproc, zmpi1, zw(1, 1, 1))
1758 CALL fftstp(lot, nfft, n1, lot, n1, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1759 btrig1, after1(i), now1(i), before1(i), 1)
1765 CALL fftstp(lot, nfft, n1, lzt, n1, zw(1, 1, inzee), zt(1, j, 1), &
1766 btrig1, after1(i), now1(i), before1(i), 1)
1773 CALL cp_abort(__location__, &
1774 'convolxc_on:ncache has to be enlarged to be able to hold at '// &
1775 'least one 1-d FFT of this size even though this will '// &
1776 'reduce the performance for shorter transform lengths')
1781 mb = min(j + (lot - 1), n1)
1786 CALL switch_upcorn(nfft, n2, lot, n1, lzt, zt(1, 1, j), zw(1, 1, 1))
1793 CALL fftstp(lot, nfft, n2, lot, n2, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1794 btrig2, after2(i), now2(i), before2(i), 1)
1800 CALL multkernel(nd1, nd2, n1, n2, lot, nfft, j, pot(1, 1, j3), zw(1, 1, inzee))
1807 CALL fftstp(lot, nfft, n2, lot, n2, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1808 ftrig2, after2(i), now2(i), before2(i), -1)
1814 CALL unswitch_downcorn(nfft, n2, lot, n1, lzt, zw(1, 1, inzee), zt(1, 1, j))
1823 mb = min(j + (lot - 1), n2/2)
1828 CALL fftstp(lzt, nfft, n1, lot, n1, zt(1, j, 1), zw(1, 1, 1), &
1829 ftrig1, after1(i), now1(i), before1(i), -1)
1833 CALL fftstp(lot, nfft, n1, lot, n1, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1834 ftrig1, after1(i), now1(i), before1(i), -1)
1841 IF (nproc == 1)
THEN
1842 CALL unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot, n1, md2, nd3, nproc, zw(1, 1, inzee), zmpi2)
1844 CALL unmpiswitch_downcorn(j3, nfft, jp2stf, j2stf, lot, n1, md2, nd3, nproc, zw(1, 1, inzee), zmpi1)
1855 CALL mpi_group%alltoall(zmpi1, zmpi2, n1*(md2/nproc)*(nd3/nproc))
1862 DO j2 = 1, md2/nproc
1864 IF (iproc*(md2/nproc) + j2 <= n2/2)
THEN
1865 DO i1 = 1, (n1/2), lot
1867 mb = min(i1 + (lot - 1), (n1/2))
1872 CALL unscramble_pack(i1, j2, lot, nfft, n1/2, n3, md2, nproc, nd3, zmpi2, zw(1, 1, 1), cosinarr)
1879 CALL fftstp(lot, nfft, n3/2, lot, n3/2, zw(1, 1, inzee), zw(1, 1, 3 - inzee), &
1880 ftrig3, after3(i), now3(i), before3(i), -1)
1886 CALL unfill_downcorn(md1, md3, lot, nfft, n3, zw(1, 1, inzee), zf(i1, 1, j2) &
1900 DEALLOCATE (before1)
1905 DEALLOCATE (before2)
1910 DEALLOCATE (before3)
1914 DEALLOCATE (cosinarr)
1915 IF (nproc > 1)
DEALLOCATE (zmpi1)
1929 SUBROUTINE switch_upcorn(nfft, n2, lot, n1, lzt, zt, zw)
1930 INTEGER :: nfft, n2, lot, n1, lzt
1931 REAL(kind=
dp) :: zt(2, lzt, n1), zw(2, lot, n2)
1941 zw(1, j, i) = zt(1, i - n2/2, j)
1942 zw(2, j, i) = zt(2, i - n2/2, j)
1952 END SUBROUTINE switch_upcorn
1968 SUBROUTINE mpiswitch_upcorn(j3, nfft, Jp2stb, J2stb, lot, n1, md2, nd3, nproc, zmpi1, zw)
1969 INTEGER :: j3, nfft, jp2stb, j2stb, lot, n1, md2, &
1971 REAL(kind=
dp) :: zmpi1(2, n1/2, md2/nproc, nd3/nproc, nproc), zw(2, lot, n1)
1973 INTEGER :: i1, j2, jp2, mfft
1979 main:
DO jp2 = jp2stb, nproc
1980 DO j2 = j2stb, md2/nproc
1982 IF (mfft > nfft)
THEN
1988 zw(1, mfft, i1) = 0._dp
1989 zw(2, mfft, i1) = 0._dp
1991 DO i1 = n1/2 + 1, n1
1992 zw(1, mfft, i1) = zmpi1(1, i1 - n1/2, j2, j3, jp2)
1993 zw(2, mfft, i1) = zmpi1(2, i1 - n1/2, j2, j3, jp2)
1998 END SUBROUTINE mpiswitch_upcorn
2010 SUBROUTINE unswitch_downcorn(nfft, n2, lot, n1, lzt, zw, zt)
2011 INTEGER :: nfft, n2, lot, n1, lzt
2012 REAL(kind=
dp) :: zw(2, lot, n2), zt(2, lzt, n1)
2022 zt(1, i, j) = zw(1, j, i)
2023 zt(2, i, j) = zw(2, j, i)
2027 END SUBROUTINE unswitch_downcorn
2043 SUBROUTINE unmpiswitch_downcorn(j3, nfft, Jp2stf, J2stf, lot, n1, md2, nd3, nproc, zw, zmpi1)
2044 INTEGER :: j3, nfft, jp2stf, j2stf, lot, n1, md2, &
2046 REAL(kind=
dp) :: zw(2, lot, n1), zmpi1(2, n1/2, md2/nproc, nd3/nproc, nproc)
2048 INTEGER :: i1, j2, jp2, mfft
2054 main:
DO jp2 = jp2stf, nproc
2055 DO j2 = j2stf, md2/nproc
2057 IF (mfft > nfft)
THEN
2063 zmpi1(1, i1, j2, j3, jp2) = zw(1, mfft, i1)
2064 zmpi1(2, i1, j2, j3, jp2) = zw(2, mfft, i1)
2069 END SUBROUTINE unmpiswitch_downcorn
2097 SUBROUTINE f_unfill_downcorn(md1, md3, lot, nfft, n3, zw, zf, scal, ehartreetmp)
2098 INTEGER,
INTENT(in) :: md1, md3, lot, nfft, n3
2099 REAL(kind=
dp),
DIMENSION(2, lot, n3/2),
INTENT(in) :: zw
2100 REAL(kind=
dp),
DIMENSION(md1, md3),
INTENT(inout) :: zf
2101 REAL(kind=
dp),
INTENT(in) :: scal
2102 REAL(kind=
dp),
INTENT(out) :: ehartreetmp
2105 REAL(kind=
dp) :: pot1
2110 pot1 = scal*zw(1, i1, i3)
2111 ehartreetmp = ehartreetmp + pot1*zf(i1, 2*i3 - 1)
2112 zf(i1, 2*i3 - 1) = pot1
2113 pot1 = scal*zw(2, i1, i3)
2114 ehartreetmp = ehartreetmp + pot1*zf(i1, 2*i3)
2118 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++)
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)
...
integer, parameter, public ctrig_length
subroutine, public fftstp(mm, nfft, m, nn, n, zin, zout, trig, after, now, before, isign)
...
subroutine, public ctrig(n, trig, after, before, now, isign, ic)
...