32#include "../base/base_uses.f90"
38 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'ps_wavelet_methods'
62 CHARACTER(len=*),
PARAMETER :: routinen =
'ps_wavelet_create'
65 REAL(kind=
dp) :: hx, hy, hz
67 CALL timeset(routinen, handle)
72 IF (
ASSOCIATED(wavelet))
THEN
79 NULLIFY (wavelet%karray, wavelet%rho_z_sliced)
81 wavelet%geocode = poisson_params%wavelet_geocode
82 wavelet%method = poisson_params%wavelet_method
83 wavelet%special_dimension = poisson_params%wavelet_special_dimension
84 wavelet%itype_scf = poisson_params%wavelet_scf_type
85 wavelet%datacode =
"D"
87 CALL set_wavelet_axis(wavelet)
88 hx = pw_grid%dr(wavelet%axis(1))
89 hy = pw_grid%dr(wavelet%axis(2))
90 hz = pw_grid%dr(wavelet%axis(3))
92 IF (poisson_params%wavelet_method ==
wavelet0d)
THEN
94 cpabort(
"Poisson solver for non cubic cells not yet implemented")
96 cpabort(
"Poisson solver for non cubic cells not yet implemented")
99 CALL rs_z_slice_distribution(wavelet, pw_grid)
101 CALL timestop(handle)
109 SUBROUTINE rs_z_slice_distribution(wavelet, pw_grid)
114 CHARACTER(len=*),
PARAMETER :: routinen =
'RS_z_slice_distribution'
116 CHARACTER(LEN=1) :: geocode
117 INTEGER :: handle, iproc, m1, m2, m3, md1, md2, &
118 md3, n1, n2, n3, nd1, nd2, nd3, nproc, &
120 REAL(kind=
dp) :: hx, hy, hz
122 CALL timeset(routinen, handle)
123 nproc = product(pw_grid%para%group%num_pe_cart)
124 iproc = pw_grid%para%group%mepos
125 geocode = wavelet%geocode
126 CALL get_wavelet_grid(wavelet, pw_grid, nx, ny, nz, hx, hy, hz)
130 IF (geocode ==
'P')
THEN
131 CALL p_fft_dimensions(nx, ny, nz, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
132 ELSE IF (geocode ==
'S')
THEN
133 CALL s_fft_dimensions(nx, ny, nz, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
134 ELSE IF (geocode ==
'F')
THEN
135 CALL f_fft_dimensions(nx, ny, nz, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
138 wavelet%PS_grid(1) = md1
139 wavelet%PS_grid(2) = md3
140 wavelet%PS_grid(3) = md2
143 ALLOCATE (wavelet%rho_z_sliced(md1, md3, z_dim))
145 CALL createkernel(geocode, nx, ny, nz, hx, hy, hz, wavelet%itype_scf, iproc, nproc, wavelet%karray, &
148 CALL timestop(handle)
149 END SUBROUTINE rs_z_slice_distribution
163 CHARACTER(len=*),
PARAMETER :: routinen =
'cp2k_distribution_to_z_slices'
165 INTEGER :: dest, handle, i, ii, iproc, j, k, l, &
166 local_z_dim, loz, m, m2, md2, nproc, &
168 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rcount, rdispl, scount, sdispl, tmp
169 INTEGER,
DIMENSION(2) :: cart_pos, lox, loy
170 INTEGER,
DIMENSION(3) :: lb, ub
171 REAL(kind=
dp) :: max_val_low, max_val_up
172 REAL(kind=
dp),
DIMENSION(:),
POINTER :: rbuf, sbuf
174 CALL timeset(routinen, handle)
176 cpassert(
ASSOCIATED(wavelet))
178 IF (.NOT. wavelet_axis_is_identity(wavelet))
THEN
179 CALL warn_density_edges(density, wavelet, pw_grid)
180 CALL cp2k_distribution_to_z_slices_permuted(density, wavelet, pw_grid)
181 CALL timestop(handle)
185 nproc = product(pw_grid%para%group%num_pe_cart)
186 iproc = pw_grid%para%group%mepos
187 md2 = wavelet%PS_grid(3)
189 lb(:) = pw_grid%bounds_local(1, :)
190 ub(:) = pw_grid%bounds_local(2, :)
191 local_z_dim = max((md2/nproc), 1)
193 ALLOCATE (sbuf(product(pw_grid%npts_local)))
194 ALLOCATE (rbuf(product(wavelet%PS_grid)/nproc))
195 ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), tmp(nproc))
202 sbuf(ii) = density%array(i, j, k)
209 IF (wavelet%geocode ==
'S' .OR. wavelet%geocode ==
'F')
THEN
212 IF (lb(2) == pw_grid%bounds(1, 2)) max_val_low = maxval(abs(density%array(:, lb(2), :)))
213 IF (ub(2) == pw_grid%bounds(2, 2)) max_val_up = maxval(abs(density%array(:, ub(2), :)))
214 IF (max_val_low >= 0.0001_dp) should_warn = 1
215 IF (max_val_up >= 0.0001_dp) should_warn = 1
216 IF (wavelet%geocode ==
'F')
THEN
219 IF (lb(1) == pw_grid%bounds(1, 1)) max_val_low = maxval(abs(density%array(lb(1), :, :)))
220 IF (ub(1) == pw_grid%bounds(2, 1)) max_val_up = maxval(abs(density%array(ub(1), :, :)))
221 IF (max_val_low >= 0.0001_dp) should_warn = 1
222 IF (max_val_up >= 0.0001_dp) should_warn = 1
225 IF (lb(3) == pw_grid%bounds(1, 3)) max_val_low = maxval(abs(density%array(:, :, lb(3))))
226 IF (ub(3) == pw_grid%bounds(2, 3)) max_val_up = maxval(abs(density%array(:, :, ub(3))))
227 IF (max_val_low >= 0.0001_dp) should_warn = 1
228 IF (max_val_up >= 0.0001_dp) should_warn = 1
232 CALL pw_grid%para%group%max(should_warn)
233 IF (should_warn > 0 .AND. iproc == 0)
THEN
234 cpwarn(
"Density non-zero on the edges of the unit cell: wrong results in WAVELET solver")
236 DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
237 DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
239 CALL pw_grid%para%group%rank_cart(cart_pos, dest)
240 IF ((ub(1) >= lb(1)) .AND. (ub(2) >= lb(2)))
THEN
241 IF (dest*local_z_dim <= m2)
THEN
242 IF ((dest + 1)*local_z_dim <= m2)
THEN
243 scount(dest + 1) = abs((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*local_z_dim)
245 scount(dest + 1) = abs((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*mod(m2, local_z_dim))
253 lox =
get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), i)
254 loy =
get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), j)
255 IF ((lox(2) >= lox(1)) .AND. (loy(2) >= loy(1)))
THEN
256 IF (iproc*local_z_dim <= m2)
THEN
257 IF ((iproc + 1)*local_z_dim <= m2)
THEN
258 rcount(dest + 1) = abs((lox(2) - lox(1) + 1)*(loy(2) - loy(1) + 1)*local_z_dim)
260 rcount(dest + 1) = abs((lox(2) - lox(1) + 1)*(loy(2) - loy(1) + 1)*mod(m2, local_z_dim))
274 sdispl(i) = sdispl(i - 1) + scount(i - 1)
275 rdispl(i) = rdispl(i - 1) + rcount(i - 1)
277 CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
280 wavelet%rho_z_sliced = 0.0_dp
282 DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
283 DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
285 CALL pw_grid%para%group%rank_cart(cart_pos, dest)
287 lox =
get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), i)
288 loy =
get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), j)
289 IF (iproc*local_z_dim <= m2)
THEN
290 IF ((iproc + 1)*local_z_dim <= m2)
THEN
293 loz = mod(m2, local_z_dim)
297 DO l = loy(1), loy(2)
298 DO m = lox(1), lox(2)
299 wavelet%rho_z_sliced(m, l, k) = rbuf(ii + rdispl(dest + 1))
308 DEALLOCATE (sbuf, rbuf, scount, sdispl, rcount, rdispl, tmp)
310 CALL timestop(handle)
326 INTEGER :: dest, i, ii, iproc, j, k, l, &
327 local_z_dim, loz, m, m2, md2, nproc
328 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rcount, rdispl, scount, sdispl, tmp
329 INTEGER,
DIMENSION(2) :: cart_pos, lox, loy, min_x, min_y
330 INTEGER,
DIMENSION(3) :: lb, ub
331 REAL(kind=
dp),
DIMENSION(:),
POINTER :: rbuf, sbuf
333 cpassert(
ASSOCIATED(wavelet))
335 IF (.NOT. wavelet_axis_is_identity(wavelet))
THEN
336 CALL z_slices_to_cp2k_distribution_permuted(density, wavelet, pw_grid)
340 nproc = product(pw_grid%para%group%num_pe_cart)
341 iproc = pw_grid%para%group%mepos
342 md2 = wavelet%PS_grid(3)
345 lb(:) = pw_grid%bounds_local(1, :)
346 ub(:) = pw_grid%bounds_local(2, :)
348 local_z_dim = max((md2/nproc), 1)
350 ALLOCATE (rbuf(product(pw_grid%npts_local)))
351 ALLOCATE (sbuf(product(wavelet%PS_grid)/nproc))
352 ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), tmp(nproc))
357 IF (iproc*local_z_dim <= m2)
THEN
358 IF ((iproc + 1)*local_z_dim <= m2)
THEN
361 loz = mod(m2, local_z_dim)
367 min_x =
get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), 0)
368 min_y =
get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), 0)
369 DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
370 DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
372 CALL pw_grid%para%group%rank_cart(cart_pos, dest)
373 IF ((ub(1) >= lb(1)) .AND. (ub(2) >= lb(2)))
THEN
374 IF (dest*local_z_dim <= m2)
THEN
375 IF ((dest + 1)*local_z_dim <= m2)
THEN
376 rcount(dest + 1) = abs((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*local_z_dim)
378 rcount(dest + 1) = abs((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*mod(m2, local_z_dim))
386 lox =
get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), i)
387 loy =
get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), j)
388 IF ((lox(2) >= lox(1)) .AND. (loy(2) >= loy(1)))
THEN
389 scount(dest + 1) = abs((lox(2) - lox(1) + 1)*(loy(2) - loy(1) + 1)*loz)
390 DO k = lox(1) - min_x(1) + 1, lox(2) - min_x(1) + 1
391 DO l = loy(1) - min_y(1) + 1, loy(2) - min_y(1) + 1
393 sbuf(ii) = wavelet%rho_z_sliced(k, l, m)
406 sdispl(i) = sdispl(i - 1) + scount(i - 1)
407 rdispl(i) = rdispl(i - 1) + rcount(i - 1)
409 CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
413 DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
414 DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
416 CALL pw_grid%para%group%rank_cart(cart_pos, dest)
417 IF (dest*local_z_dim <= m2)
THEN
418 IF ((dest + 1)*local_z_dim <= m2)
THEN
421 loz = mod(m2, local_z_dim)
424 IF (lb(3) + (dest*local_z_dim) <= ub(3))
THEN
427 DO k = lb(3) + (dest*local_z_dim), lb(3) + (dest*local_z_dim) + loz - 1
428 density%array(m, l, k) = rbuf(ii + rdispl(dest + 1))
437 DEALLOCATE (sbuf, rbuf, scount, sdispl, rcount, rdispl, tmp)
445 SUBROUTINE set_wavelet_axis(wavelet)
449 wavelet%axis = [1, 2, 3]
452 SELECT CASE (wavelet%special_dimension)
454 wavelet%axis = [2, 1, 3]
456 wavelet%axis = [1, 2, 3]
458 wavelet%axis = [1, 3, 2]
460 cpabort(
"Invalid isolated dimension for WAVELET 2D")
464 END SUBROUTINE set_wavelet_axis
477 SUBROUTINE get_wavelet_grid(wavelet, pw_grid, nx, ny, nz, hx, hy, hz)
481 INTEGER,
INTENT(OUT) :: nx, ny, nz
482 REAL(kind=
dp),
INTENT(OUT) :: hx, hy, hz
484 nx = pw_grid%npts(wavelet%axis(1))
485 ny = pw_grid%npts(wavelet%axis(2))
486 nz = pw_grid%npts(wavelet%axis(3))
487 hx = pw_grid%dr(wavelet%axis(1))
488 hy = pw_grid%dr(wavelet%axis(2))
489 hz = pw_grid%dr(wavelet%axis(3))
491 END SUBROUTINE get_wavelet_grid
498 FUNCTION wavelet_axis_is_identity(wavelet)
RESULT(is_identity)
501 LOGICAL :: is_identity
503 is_identity = all(wavelet%axis == [1, 2, 3])
505 END FUNCTION wavelet_axis_is_identity
513 SUBROUTINE warn_density_edges(density, wavelet, pw_grid)
519 INTEGER :: idir, iproc, should_warn
522 iproc = pw_grid%para%group%mepos
524 IF (wavelet%geocode ==
'S')
THEN
525 CALL update_edge_warning(density, pw_grid, wavelet%special_dimension, should_warn)
526 ELSE IF (wavelet%geocode ==
'F')
THEN
528 CALL update_edge_warning(density, pw_grid, idir, should_warn)
532 CALL pw_grid%para%group%max(should_warn)
533 IF (should_warn > 0 .AND. iproc == 0)
THEN
534 cpwarn(
"Density non-zero on the edges of the unit cell: wrong results in WAVELET solver")
537 END SUBROUTINE warn_density_edges
546 SUBROUTINE update_edge_warning(density, pw_grid, direction, should_warn)
550 INTEGER,
INTENT(IN) :: direction
551 INTEGER,
INTENT(INOUT) :: should_warn
553 INTEGER,
DIMENSION(3) :: lb, ub
554 REAL(kind=
dp) :: max_val_low, max_val_up
556 lb(:) = pw_grid%bounds_local(1, :)
557 ub(:) = pw_grid%bounds_local(2, :)
558 IF (.NOT. all(ub >= lb))
RETURN
562 SELECT CASE (direction)
564 IF (lb(1) == pw_grid%bounds(1, 1)) max_val_low = maxval(abs(density%array(lb(1), :, :)))
565 IF (ub(1) == pw_grid%bounds(2, 1)) max_val_up = maxval(abs(density%array(ub(1), :, :)))
567 IF (lb(2) == pw_grid%bounds(1, 2)) max_val_low = maxval(abs(density%array(:, lb(2), :)))
568 IF (ub(2) == pw_grid%bounds(2, 2)) max_val_up = maxval(abs(density%array(:, ub(2), :)))
570 IF (lb(3) == pw_grid%bounds(1, 3)) max_val_low = maxval(abs(density%array(:, :, lb(3))))
571 IF (ub(3) == pw_grid%bounds(2, 3)) max_val_up = maxval(abs(density%array(:, :, ub(3))))
573 cpabort(
"Invalid WAVELET isolated dimension")
576 IF (max_val_low >= 0.0001_dp) should_warn = 1
577 IF (max_val_up >= 0.0001_dp) should_warn = 1
579 END SUBROUTINE update_edge_warning
586 SUBROUTINE set_displacements(counts, displacements)
588 INTEGER,
DIMENSION(:),
INTENT(IN) :: counts
589 INTEGER,
DIMENSION(:),
INTENT(OUT) :: displacements
594 DO i = 2,
SIZE(counts)
595 displacements(i) = displacements(i - 1) + counts(i - 1)
598 END SUBROUTINE set_displacements
607 FUNCTION grid_owner(index, npts, nparts)
RESULT(owner)
609 INTEGER,
INTENT(IN) :: index, npts, nparts
613 INTEGER,
DIMENSION(2) :: limits
615 DO ipart = 0, nparts - 1
617 IF (index >= limits(1) .AND. index <= limits(2))
THEN
622 cpabort(
"Grid index outside distributed bounds")
624 END FUNCTION grid_owner
633 FUNCTION z_slice_owner(index, local_z_dim, nproc)
RESULT(owner)
635 INTEGER,
INTENT(IN) :: index, local_z_dim, nproc
638 owner = min((index - 1)/local_z_dim, nproc - 1)
640 END FUNCTION z_slice_owner
649 FUNCTION cp2k_rank_owner(ix, iy, pw_grid)
RESULT(rank)
651 INTEGER,
INTENT(IN) :: ix, iy
655 INTEGER,
DIMENSION(2) :: cart_pos
657 cart_pos(1) = grid_owner(ix - pw_grid%bounds(1, 1) + 1, pw_grid%npts(1), &
658 pw_grid%para%group%num_pe_cart(1))
659 cart_pos(2) = grid_owner(iy - pw_grid%bounds(1, 2) + 1, pw_grid%npts(2), &
660 pw_grid%para%group%num_pe_cart(2))
661 CALL pw_grid%para%group%rank_cart(cart_pos, rank)
663 END FUNCTION cp2k_rank_owner
671 SUBROUTINE cp2k_distribution_to_z_slices_permuted(density, wavelet, pw_grid)
677 INTEGER :: dest, i, idir, ii, j, k, local_z_dim, &
678 md2, nproc, nrecv, nsend
679 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: coord_rbuf, coord_rcount, coord_rdispl, coord_sbuf, &
680 coord_scount, coord_sdispl, rcount, rdispl, scount, sdispl, send_pos
681 INTEGER,
DIMENSION(3) :: lb, q, u, ub
682 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: rbuf, sbuf
684 nproc = product(pw_grid%para%group%num_pe_cart)
685 md2 = wavelet%PS_grid(3)
686 local_z_dim = max(md2/nproc, 1)
687 lb(:) = pw_grid%bounds_local(1, :)
688 ub(:) = pw_grid%bounds_local(2, :)
690 ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), send_pos(nproc))
697 q(idir) = u(wavelet%axis(idir)) - pw_grid%bounds(1, wavelet%axis(idir)) + 1
699 dest = z_slice_owner(q(3), local_z_dim, nproc)
700 scount(dest + 1) = scount(dest + 1) + 1
705 CALL pw_grid%para%group%alltoall(scount, rcount, 1)
706 CALL set_displacements(scount, sdispl)
707 CALL set_displacements(rcount, rdispl)
711 ALLOCATE (sbuf(max(nsend, 1)), rbuf(max(nrecv, 1)))
712 ALLOCATE (coord_sbuf(max(3*nsend, 1)), coord_rbuf(max(3*nrecv, 1)))
713 ALLOCATE (coord_scount(nproc), coord_sdispl(nproc), coord_rcount(nproc), coord_rdispl(nproc))
714 coord_scount(:) = 3*scount(:)
715 coord_rcount(:) = 3*rcount(:)
716 coord_sdispl(:) = 3*sdispl(:)
717 coord_rdispl(:) = 3*rdispl(:)
718 send_pos(:) = sdispl(:) + 1
725 q(idir) = u(wavelet%axis(idir)) - pw_grid%bounds(1, wavelet%axis(idir)) + 1
727 dest = z_slice_owner(q(3), local_z_dim, nproc)
728 ii = send_pos(dest + 1)
729 sbuf(ii) = density%array(i, j, k)
730 coord_sbuf(3*ii - 2) = q(1)
731 coord_sbuf(3*ii - 1) = q(2)
732 coord_sbuf(3*ii) = q(3)
733 send_pos(dest + 1) = ii + 1
738 CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
739 CALL pw_grid%para%group%alltoall(coord_sbuf, coord_scount, coord_sdispl, &
740 coord_rbuf, coord_rcount, coord_rdispl)
742 wavelet%rho_z_sliced = 0.0_dp
744 q(1) = coord_rbuf(3*ii - 2)
745 q(2) = coord_rbuf(3*ii - 1)
746 q(3) = coord_rbuf(3*ii)
747 wavelet%rho_z_sliced(q(1), q(2), q(3) - pw_grid%para%group%mepos*local_z_dim) = rbuf(ii)
750 DEALLOCATE (sbuf, rbuf, coord_sbuf, coord_rbuf, coord_scount, coord_sdispl, coord_rcount, &
751 coord_rdispl, scount, sdispl, rcount, rdispl, send_pos)
753 END SUBROUTINE cp2k_distribution_to_z_slices_permuted
761 SUBROUTINE z_slices_to_cp2k_distribution_permuted(density, wavelet, pw_grid)
767 INTEGER :: dest, i, idir, ii, j, k, local_z, &
768 local_z_dim, md2, n1, n2, n3, nproc, &
769 nrecv, nsend, z_end, z_start
770 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: coord_rbuf, coord_rcount, coord_rdispl, coord_sbuf, &
771 coord_scount, coord_sdispl, rcount, rdispl, scount, sdispl, send_pos
772 INTEGER,
DIMENSION(3) :: lb, q, u, ub
773 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: rbuf, sbuf
775 nproc = product(pw_grid%para%group%num_pe_cart)
776 md2 = wavelet%PS_grid(3)
777 local_z_dim = max(md2/nproc, 1)
778 n1 = pw_grid%npts(wavelet%axis(1))
779 n2 = pw_grid%npts(wavelet%axis(2))
780 n3 = pw_grid%npts(wavelet%axis(3))
781 z_start = pw_grid%para%group%mepos*local_z_dim + 1
782 z_end = min((pw_grid%para%group%mepos + 1)*local_z_dim, n3)
783 lb(:) = pw_grid%bounds_local(1, :)
784 ub(:) = pw_grid%bounds_local(2, :)
786 ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), send_pos(nproc))
788 DO k = z_start, z_end
793 u(wavelet%axis(idir)) = q(idir) + pw_grid%bounds(1, wavelet%axis(idir)) - 1
795 dest = cp2k_rank_owner(u(1), u(2), pw_grid)
796 scount(dest + 1) = scount(dest + 1) + 1
801 CALL pw_grid%para%group%alltoall(scount, rcount, 1)
802 CALL set_displacements(scount, sdispl)
803 CALL set_displacements(rcount, rdispl)
807 ALLOCATE (sbuf(max(nsend, 1)), rbuf(max(nrecv, 1)))
808 ALLOCATE (coord_sbuf(max(3*nsend, 1)), coord_rbuf(max(3*nrecv, 1)))
809 ALLOCATE (coord_scount(nproc), coord_sdispl(nproc), coord_rcount(nproc), coord_rdispl(nproc))
810 coord_scount(:) = 3*scount(:)
811 coord_rcount(:) = 3*rcount(:)
812 coord_sdispl(:) = 3*sdispl(:)
813 coord_rdispl(:) = 3*rdispl(:)
814 send_pos(:) = sdispl(:) + 1
816 DO k = z_start, z_end
821 u(wavelet%axis(idir)) = q(idir) + pw_grid%bounds(1, wavelet%axis(idir)) - 1
823 dest = cp2k_rank_owner(u(1), u(2), pw_grid)
824 ii = send_pos(dest + 1)
825 local_z = k - pw_grid%para%group%mepos*local_z_dim
826 sbuf(ii) = wavelet%rho_z_sliced(i, j, local_z)
827 coord_sbuf(3*ii - 2) = u(1)
828 coord_sbuf(3*ii - 1) = u(2)
829 coord_sbuf(3*ii) = u(3)
830 send_pos(dest + 1) = ii + 1
835 CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
836 CALL pw_grid%para%group%alltoall(coord_sbuf, coord_scount, coord_sdispl, &
837 coord_rbuf, coord_rcount, coord_rdispl)
840 u(1) = coord_rbuf(3*ii - 2)
841 u(2) = coord_rbuf(3*ii - 1)
842 u(3) = coord_rbuf(3*ii)
843 IF (u(1) >= lb(1) .AND. u(1) <= ub(1) .AND. u(2) >= lb(2) .AND. u(2) <= ub(2) .AND. &
844 u(3) >= lb(3) .AND. u(3) <= ub(3))
THEN
845 density%array(u(1), u(2), u(3)) = rbuf(ii)
849 DEALLOCATE (sbuf, rbuf, coord_sbuf, coord_rbuf, coord_scount, coord_sdispl, coord_rcount, &
850 coord_rdispl, scount, sdispl, rcount, rdispl, send_pos)
852 END SUBROUTINE z_slices_to_cp2k_distribution_permuted
864 CHARACTER(len=*),
PARAMETER :: routinen =
'ps_wavelet_solve'
866 CHARACTER(LEN=1) :: geocode
867 INTEGER :: handle, iproc, nproc, nx, ny, nz
868 REAL(kind=
dp) :: hx, hy, hz
870 CALL timeset(routinen, handle)
871 nproc = product(pw_grid%para%group%num_pe_cart)
872 iproc = pw_grid%para%group%mepos
873 geocode = wavelet%geocode
874 CALL get_wavelet_grid(wavelet, pw_grid, nx, ny, nz, hx, hy, hz)
876 CALL psolver(geocode, iproc, nproc, nx, ny, nz, hx, hy, hz, &
877 wavelet%rho_z_sliced, wavelet%karray, pw_grid)
878 CALL timestop(handle)
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public genovese2006
integer, save, public genovese2007
Defines the basic variable types.
integer, parameter, public dp
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...
Definition and initialisation of the ps_wavelet data type. \history 01.2014 Renamed from ps_wavelet_t...
subroutine, public ps_wavelet_create(poisson_params, wavelet, pw_grid)
creates the ps_wavelet_type which is needed for the link to the Poisson Solver of Luigi Genovese
subroutine, public ps_wavelet_solve(wavelet, pw_grid)
...
subroutine, public z_slices_to_cp2k_distribution(density, wavelet, pw_grid)
...
subroutine, public cp2k_distribution_to_z_slices(density, wavelet, pw_grid)
...
Definition and initialisation of the ps_wavelet data type.
integer, parameter, public wavelet0d
subroutine, public ps_wavelet_release(wavelet)
...
integer, parameter, public wavelet2d
Performs a wavelet based solution of the Poisson equation.
subroutine, public p_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 periodic syste...
subroutine, public psolver(geocode, iproc, nproc, n01, n02, n03, hx, hy, hz, rhopot, karray, pw_grid)
Calculate the Poisson equation $\nabla^2 V(x,y,z)=-4 \pi \rho(x,y,z)$ from a given $\rho$,...
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.
functions related to the poisson solver on regular grids
All kind of helpful little routines.
pure integer function, dimension(2), public get_limit(m, n, me)
divide m entries into n parts, return size of part me
parameters for the poisson solver independet of input_section