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")
97 cpabort(
"Poisson solver for non cubic cells not yet implemented")
101 CALL rs_z_slice_distribution(wavelet, pw_grid)
103 CALL timestop(handle)
111 SUBROUTINE rs_z_slice_distribution(wavelet, pw_grid)
116 CHARACTER(len=*),
PARAMETER :: routinen =
'RS_z_slice_distribution'
118 CHARACTER(LEN=1) :: geocode
119 INTEGER :: handle, iproc, m1, m2, m3, md1, md2, &
120 md3, n1, n2, n3, nd1, nd2, nd3, nproc, &
122 REAL(kind=
dp) :: hx, hy, hz
124 CALL timeset(routinen, handle)
125 nproc = product(pw_grid%para%group%num_pe_cart)
126 iproc = pw_grid%para%group%mepos
127 geocode = wavelet%geocode
128 CALL get_wavelet_grid(wavelet, pw_grid, nx, ny, nz, hx, hy, hz)
132 IF (geocode ==
'P')
THEN
133 CALL p_fft_dimensions(nx, ny, nz, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
134 ELSE IF (geocode ==
'S')
THEN
135 CALL s_fft_dimensions(nx, ny, nz, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
136 ELSE IF (geocode ==
'F')
THEN
137 CALL f_fft_dimensions(nx, ny, nz, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
140 wavelet%PS_grid(1) = md1
141 wavelet%PS_grid(2) = md3
142 wavelet%PS_grid(3) = md2
145 ALLOCATE (wavelet%rho_z_sliced(md1, md3, z_dim))
147 CALL createkernel(geocode, nx, ny, nz, hx, hy, hz, wavelet%itype_scf, iproc, nproc, wavelet%karray, &
150 CALL timestop(handle)
151 END SUBROUTINE rs_z_slice_distribution
165 CHARACTER(len=*),
PARAMETER :: routinen =
'cp2k_distribution_to_z_slices'
167 INTEGER :: dest, handle, i, ii, iproc, j, k, l, &
168 local_z_dim, loz, m, m2, md2, nproc, &
170 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rcount, rdispl, scount, sdispl, tmp
171 INTEGER,
DIMENSION(2) :: cart_pos, lox, loy
172 INTEGER,
DIMENSION(3) :: lb, ub
173 REAL(kind=
dp) :: max_val_low, max_val_up
174 REAL(kind=
dp),
DIMENSION(:),
POINTER :: rbuf, sbuf
176 CALL timeset(routinen, handle)
178 cpassert(
ASSOCIATED(wavelet))
180 IF (.NOT. wavelet_axis_is_identity(wavelet))
THEN
181 CALL warn_density_edges(density, wavelet, pw_grid)
182 CALL cp2k_distribution_to_z_slices_permuted(density, wavelet, pw_grid)
183 CALL timestop(handle)
187 nproc = product(pw_grid%para%group%num_pe_cart)
188 iproc = pw_grid%para%group%mepos
189 md2 = wavelet%PS_grid(3)
191 lb(:) = pw_grid%bounds_local(1, :)
192 ub(:) = pw_grid%bounds_local(2, :)
193 local_z_dim = max((md2/nproc), 1)
195 ALLOCATE (sbuf(product(pw_grid%npts_local)))
196 ALLOCATE (rbuf(product(wavelet%PS_grid)/nproc))
197 ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), tmp(nproc))
204 sbuf(ii) = density%array(i, j, k)
211 IF (wavelet%geocode ==
'S' .OR. wavelet%geocode ==
'F')
THEN
214 IF (lb(2) == pw_grid%bounds(1, 2)) max_val_low = maxval(abs(density%array(:, lb(2), :)))
215 IF (ub(2) == pw_grid%bounds(2, 2)) max_val_up = maxval(abs(density%array(:, ub(2), :)))
216 IF (max_val_low >= 0.0001_dp) should_warn = 1
217 IF (max_val_up >= 0.0001_dp) should_warn = 1
218 IF (wavelet%geocode ==
'F')
THEN
221 IF (lb(1) == pw_grid%bounds(1, 1)) max_val_low = maxval(abs(density%array(lb(1), :, :)))
222 IF (ub(1) == pw_grid%bounds(2, 1)) max_val_up = maxval(abs(density%array(ub(1), :, :)))
223 IF (max_val_low >= 0.0001_dp) should_warn = 1
224 IF (max_val_up >= 0.0001_dp) should_warn = 1
227 IF (lb(3) == pw_grid%bounds(1, 3)) max_val_low = maxval(abs(density%array(:, :, lb(3))))
228 IF (ub(3) == pw_grid%bounds(2, 3)) max_val_up = maxval(abs(density%array(:, :, ub(3))))
229 IF (max_val_low >= 0.0001_dp) should_warn = 1
230 IF (max_val_up >= 0.0001_dp) should_warn = 1
234 CALL pw_grid%para%group%max(should_warn)
235 IF (should_warn > 0 .AND. iproc == 0)
THEN
236 cpwarn(
"Density non-zero on the edges of the unit cell: wrong results in WAVELET solver")
238 DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
239 DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
241 CALL pw_grid%para%group%rank_cart(cart_pos, dest)
242 IF ((ub(1) >= lb(1)) .AND. (ub(2) >= lb(2)))
THEN
243 IF (dest*local_z_dim <= m2)
THEN
244 IF ((dest + 1)*local_z_dim <= m2)
THEN
245 scount(dest + 1) = abs((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*local_z_dim)
247 scount(dest + 1) = abs((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*mod(m2, local_z_dim))
255 lox =
get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), i)
256 loy =
get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), j)
257 IF ((lox(2) >= lox(1)) .AND. (loy(2) >= loy(1)))
THEN
258 IF (iproc*local_z_dim <= m2)
THEN
259 IF ((iproc + 1)*local_z_dim <= m2)
THEN
260 rcount(dest + 1) = abs((lox(2) - lox(1) + 1)*(loy(2) - loy(1) + 1)*local_z_dim)
262 rcount(dest + 1) = abs((lox(2) - lox(1) + 1)*(loy(2) - loy(1) + 1)*mod(m2, local_z_dim))
276 sdispl(i) = sdispl(i - 1) + scount(i - 1)
277 rdispl(i) = rdispl(i - 1) + rcount(i - 1)
279 CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
282 wavelet%rho_z_sliced = 0.0_dp
284 DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
285 DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
287 CALL pw_grid%para%group%rank_cart(cart_pos, dest)
289 lox =
get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), i)
290 loy =
get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), j)
291 IF (iproc*local_z_dim <= m2)
THEN
292 IF ((iproc + 1)*local_z_dim <= m2)
THEN
295 loz = mod(m2, local_z_dim)
299 DO l = loy(1), loy(2)
300 DO m = lox(1), lox(2)
301 wavelet%rho_z_sliced(m, l, k) = rbuf(ii + rdispl(dest + 1))
310 DEALLOCATE (sbuf, rbuf, scount, sdispl, rcount, rdispl, tmp)
312 CALL timestop(handle)
328 INTEGER :: dest, i, ii, iproc, j, k, l, &
329 local_z_dim, loz, m, m2, md2, nproc
330 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rcount, rdispl, scount, sdispl, tmp
331 INTEGER,
DIMENSION(2) :: cart_pos, lox, loy, min_x, min_y
332 INTEGER,
DIMENSION(3) :: lb, ub
333 REAL(kind=
dp),
DIMENSION(:),
POINTER :: rbuf, sbuf
335 cpassert(
ASSOCIATED(wavelet))
337 IF (.NOT. wavelet_axis_is_identity(wavelet))
THEN
338 CALL z_slices_to_cp2k_distribution_permuted(density, wavelet, pw_grid)
342 nproc = product(pw_grid%para%group%num_pe_cart)
343 iproc = pw_grid%para%group%mepos
344 md2 = wavelet%PS_grid(3)
347 lb(:) = pw_grid%bounds_local(1, :)
348 ub(:) = pw_grid%bounds_local(2, :)
350 local_z_dim = max((md2/nproc), 1)
352 ALLOCATE (rbuf(product(pw_grid%npts_local)))
353 ALLOCATE (sbuf(product(wavelet%PS_grid)/nproc))
354 ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), tmp(nproc))
359 IF (iproc*local_z_dim <= m2)
THEN
360 IF ((iproc + 1)*local_z_dim <= m2)
THEN
363 loz = mod(m2, local_z_dim)
369 min_x =
get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), 0)
370 min_y =
get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), 0)
371 DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
372 DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
374 CALL pw_grid%para%group%rank_cart(cart_pos, dest)
375 IF ((ub(1) >= lb(1)) .AND. (ub(2) >= lb(2)))
THEN
376 IF (dest*local_z_dim <= m2)
THEN
377 IF ((dest + 1)*local_z_dim <= m2)
THEN
378 rcount(dest + 1) = abs((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*local_z_dim)
380 rcount(dest + 1) = abs((ub(1) - lb(1) + 1)*(ub(2) - lb(2) + 1)*mod(m2, local_z_dim))
388 lox =
get_limit(pw_grid%npts(1), pw_grid%para%group%num_pe_cart(1), i)
389 loy =
get_limit(pw_grid%npts(2), pw_grid%para%group%num_pe_cart(2), j)
390 IF ((lox(2) >= lox(1)) .AND. (loy(2) >= loy(1)))
THEN
391 scount(dest + 1) = abs((lox(2) - lox(1) + 1)*(loy(2) - loy(1) + 1)*loz)
392 DO k = lox(1) - min_x(1) + 1, lox(2) - min_x(1) + 1
393 DO l = loy(1) - min_y(1) + 1, loy(2) - min_y(1) + 1
395 sbuf(ii) = wavelet%rho_z_sliced(k, l, m)
408 sdispl(i) = sdispl(i - 1) + scount(i - 1)
409 rdispl(i) = rdispl(i - 1) + rcount(i - 1)
411 CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
415 DO i = 0, pw_grid%para%group%num_pe_cart(1) - 1
416 DO j = 0, pw_grid%para%group%num_pe_cart(2) - 1
418 CALL pw_grid%para%group%rank_cart(cart_pos, dest)
419 IF (dest*local_z_dim <= m2)
THEN
420 IF ((dest + 1)*local_z_dim <= m2)
THEN
423 loz = mod(m2, local_z_dim)
426 IF (lb(3) + (dest*local_z_dim) <= ub(3))
THEN
429 DO k = lb(3) + (dest*local_z_dim), lb(3) + (dest*local_z_dim) + loz - 1
430 density%array(m, l, k) = rbuf(ii + rdispl(dest + 1))
439 DEALLOCATE (sbuf, rbuf, scount, sdispl, rcount, rdispl, tmp)
447 SUBROUTINE set_wavelet_axis(wavelet)
451 wavelet%axis = [1, 2, 3]
454 SELECT CASE (wavelet%special_dimension)
456 wavelet%axis = [2, 1, 3]
458 wavelet%axis = [1, 2, 3]
460 wavelet%axis = [1, 3, 2]
462 cpabort(
"Invalid isolated dimension for WAVELET 2D")
466 END SUBROUTINE set_wavelet_axis
479 SUBROUTINE get_wavelet_grid(wavelet, pw_grid, nx, ny, nz, hx, hy, hz)
483 INTEGER,
INTENT(OUT) :: nx, ny, nz
484 REAL(kind=
dp),
INTENT(OUT) :: hx, hy, hz
486 nx = pw_grid%npts(wavelet%axis(1))
487 ny = pw_grid%npts(wavelet%axis(2))
488 nz = pw_grid%npts(wavelet%axis(3))
489 hx = pw_grid%dr(wavelet%axis(1))
490 hy = pw_grid%dr(wavelet%axis(2))
491 hz = pw_grid%dr(wavelet%axis(3))
493 END SUBROUTINE get_wavelet_grid
500 FUNCTION wavelet_axis_is_identity(wavelet)
RESULT(is_identity)
503 LOGICAL :: is_identity
505 is_identity = all(wavelet%axis == [1, 2, 3])
507 END FUNCTION wavelet_axis_is_identity
515 SUBROUTINE warn_density_edges(density, wavelet, pw_grid)
521 INTEGER :: idir, iproc, should_warn
524 iproc = pw_grid%para%group%mepos
526 IF (wavelet%geocode ==
'S')
THEN
527 CALL update_edge_warning(density, pw_grid, wavelet%special_dimension, should_warn)
528 ELSE IF (wavelet%geocode ==
'F')
THEN
530 CALL update_edge_warning(density, pw_grid, idir, should_warn)
534 CALL pw_grid%para%group%max(should_warn)
535 IF (should_warn > 0 .AND. iproc == 0)
THEN
536 cpwarn(
"Density non-zero on the edges of the unit cell: wrong results in WAVELET solver")
539 END SUBROUTINE warn_density_edges
548 SUBROUTINE update_edge_warning(density, pw_grid, direction, should_warn)
552 INTEGER,
INTENT(IN) :: direction
553 INTEGER,
INTENT(INOUT) :: should_warn
555 INTEGER,
DIMENSION(3) :: lb, ub
556 REAL(kind=
dp) :: max_val_low, max_val_up
558 lb(:) = pw_grid%bounds_local(1, :)
559 ub(:) = pw_grid%bounds_local(2, :)
560 IF (.NOT. all(ub >= lb))
RETURN
564 SELECT CASE (direction)
566 IF (lb(1) == pw_grid%bounds(1, 1)) max_val_low = maxval(abs(density%array(lb(1), :, :)))
567 IF (ub(1) == pw_grid%bounds(2, 1)) max_val_up = maxval(abs(density%array(ub(1), :, :)))
569 IF (lb(2) == pw_grid%bounds(1, 2)) max_val_low = maxval(abs(density%array(:, lb(2), :)))
570 IF (ub(2) == pw_grid%bounds(2, 2)) max_val_up = maxval(abs(density%array(:, ub(2), :)))
572 IF (lb(3) == pw_grid%bounds(1, 3)) max_val_low = maxval(abs(density%array(:, :, lb(3))))
573 IF (ub(3) == pw_grid%bounds(2, 3)) max_val_up = maxval(abs(density%array(:, :, ub(3))))
575 cpabort(
"Invalid WAVELET isolated dimension")
578 IF (max_val_low >= 0.0001_dp) should_warn = 1
579 IF (max_val_up >= 0.0001_dp) should_warn = 1
581 END SUBROUTINE update_edge_warning
588 SUBROUTINE set_displacements(counts, displacements)
590 INTEGER,
DIMENSION(:),
INTENT(IN) :: counts
591 INTEGER,
DIMENSION(:),
INTENT(OUT) :: displacements
596 DO i = 2,
SIZE(counts)
597 displacements(i) = displacements(i - 1) + counts(i - 1)
600 END SUBROUTINE set_displacements
609 FUNCTION grid_owner(index, npts, nparts)
RESULT(owner)
611 INTEGER,
INTENT(IN) :: index, npts, nparts
615 INTEGER,
DIMENSION(2) :: limits
617 DO ipart = 0, nparts - 1
619 IF (index >= limits(1) .AND. index <= limits(2))
THEN
624 cpabort(
"Grid index outside distributed bounds")
626 END FUNCTION grid_owner
635 FUNCTION z_slice_owner(index, local_z_dim, nproc)
RESULT(owner)
637 INTEGER,
INTENT(IN) :: index, local_z_dim, nproc
640 owner = min((index - 1)/local_z_dim, nproc - 1)
642 END FUNCTION z_slice_owner
651 FUNCTION cp2k_rank_owner(ix, iy, pw_grid)
RESULT(rank)
653 INTEGER,
INTENT(IN) :: ix, iy
657 INTEGER,
DIMENSION(2) :: cart_pos
659 cart_pos(1) = grid_owner(ix - pw_grid%bounds(1, 1) + 1, pw_grid%npts(1), &
660 pw_grid%para%group%num_pe_cart(1))
661 cart_pos(2) = grid_owner(iy - pw_grid%bounds(1, 2) + 1, pw_grid%npts(2), &
662 pw_grid%para%group%num_pe_cart(2))
663 CALL pw_grid%para%group%rank_cart(cart_pos, rank)
665 END FUNCTION cp2k_rank_owner
673 SUBROUTINE cp2k_distribution_to_z_slices_permuted(density, wavelet, pw_grid)
679 INTEGER :: dest, i, idir, ii, j, k, local_z_dim, &
680 md2, nproc, nrecv, nsend
681 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: coord_rbuf, coord_rcount, coord_rdispl, coord_sbuf, &
682 coord_scount, coord_sdispl, rcount, rdispl, scount, sdispl, send_pos
683 INTEGER,
DIMENSION(3) :: lb, q, u, ub
684 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: rbuf, sbuf
686 nproc = product(pw_grid%para%group%num_pe_cart)
687 md2 = wavelet%PS_grid(3)
688 local_z_dim = max(md2/nproc, 1)
689 lb(:) = pw_grid%bounds_local(1, :)
690 ub(:) = pw_grid%bounds_local(2, :)
692 ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), send_pos(nproc))
699 q(idir) = u(wavelet%axis(idir)) - pw_grid%bounds(1, wavelet%axis(idir)) + 1
701 dest = z_slice_owner(q(3), local_z_dim, nproc)
702 scount(dest + 1) = scount(dest + 1) + 1
707 CALL pw_grid%para%group%alltoall(scount, rcount, 1)
708 CALL set_displacements(scount, sdispl)
709 CALL set_displacements(rcount, rdispl)
713 ALLOCATE (sbuf(max(nsend, 1)), rbuf(max(nrecv, 1)))
714 ALLOCATE (coord_sbuf(max(3*nsend, 1)), coord_rbuf(max(3*nrecv, 1)))
715 ALLOCATE (coord_scount(nproc), coord_sdispl(nproc), coord_rcount(nproc), coord_rdispl(nproc))
716 coord_scount(:) = 3*scount(:)
717 coord_rcount(:) = 3*rcount(:)
718 coord_sdispl(:) = 3*sdispl(:)
719 coord_rdispl(:) = 3*rdispl(:)
720 send_pos(:) = sdispl(:) + 1
727 q(idir) = u(wavelet%axis(idir)) - pw_grid%bounds(1, wavelet%axis(idir)) + 1
729 dest = z_slice_owner(q(3), local_z_dim, nproc)
730 ii = send_pos(dest + 1)
731 sbuf(ii) = density%array(i, j, k)
732 coord_sbuf(3*ii - 2) = q(1)
733 coord_sbuf(3*ii - 1) = q(2)
734 coord_sbuf(3*ii) = q(3)
735 send_pos(dest + 1) = ii + 1
740 CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
741 CALL pw_grid%para%group%alltoall(coord_sbuf, coord_scount, coord_sdispl, &
742 coord_rbuf, coord_rcount, coord_rdispl)
744 wavelet%rho_z_sliced = 0.0_dp
746 q(1) = coord_rbuf(3*ii - 2)
747 q(2) = coord_rbuf(3*ii - 1)
748 q(3) = coord_rbuf(3*ii)
749 wavelet%rho_z_sliced(q(1), q(2), q(3) - pw_grid%para%group%mepos*local_z_dim) = rbuf(ii)
752 DEALLOCATE (sbuf, rbuf, coord_sbuf, coord_rbuf, coord_scount, coord_sdispl, coord_rcount, &
753 coord_rdispl, scount, sdispl, rcount, rdispl, send_pos)
755 END SUBROUTINE cp2k_distribution_to_z_slices_permuted
763 SUBROUTINE z_slices_to_cp2k_distribution_permuted(density, wavelet, pw_grid)
769 INTEGER :: dest, i, idir, ii, j, k, local_z, &
770 local_z_dim, md2, n1, n2, n3, nproc, &
771 nrecv, nsend, z_end, z_start
772 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: coord_rbuf, coord_rcount, coord_rdispl, coord_sbuf, &
773 coord_scount, coord_sdispl, rcount, rdispl, scount, sdispl, send_pos
774 INTEGER,
DIMENSION(3) :: lb, q, u, ub
775 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: rbuf, sbuf
777 nproc = product(pw_grid%para%group%num_pe_cart)
778 md2 = wavelet%PS_grid(3)
779 local_z_dim = max(md2/nproc, 1)
780 n1 = pw_grid%npts(wavelet%axis(1))
781 n2 = pw_grid%npts(wavelet%axis(2))
782 n3 = pw_grid%npts(wavelet%axis(3))
783 z_start = pw_grid%para%group%mepos*local_z_dim + 1
784 z_end = min((pw_grid%para%group%mepos + 1)*local_z_dim, n3)
785 lb(:) = pw_grid%bounds_local(1, :)
786 ub(:) = pw_grid%bounds_local(2, :)
788 ALLOCATE (scount(nproc), sdispl(nproc), rcount(nproc), rdispl(nproc), send_pos(nproc))
790 DO k = z_start, z_end
795 u(wavelet%axis(idir)) = q(idir) + pw_grid%bounds(1, wavelet%axis(idir)) - 1
797 dest = cp2k_rank_owner(u(1), u(2), pw_grid)
798 scount(dest + 1) = scount(dest + 1) + 1
803 CALL pw_grid%para%group%alltoall(scount, rcount, 1)
804 CALL set_displacements(scount, sdispl)
805 CALL set_displacements(rcount, rdispl)
809 ALLOCATE (sbuf(max(nsend, 1)), rbuf(max(nrecv, 1)))
810 ALLOCATE (coord_sbuf(max(3*nsend, 1)), coord_rbuf(max(3*nrecv, 1)))
811 ALLOCATE (coord_scount(nproc), coord_sdispl(nproc), coord_rcount(nproc), coord_rdispl(nproc))
812 coord_scount(:) = 3*scount(:)
813 coord_rcount(:) = 3*rcount(:)
814 coord_sdispl(:) = 3*sdispl(:)
815 coord_rdispl(:) = 3*rdispl(:)
816 send_pos(:) = sdispl(:) + 1
818 DO k = z_start, z_end
823 u(wavelet%axis(idir)) = q(idir) + pw_grid%bounds(1, wavelet%axis(idir)) - 1
825 dest = cp2k_rank_owner(u(1), u(2), pw_grid)
826 ii = send_pos(dest + 1)
827 local_z = k - pw_grid%para%group%mepos*local_z_dim
828 sbuf(ii) = wavelet%rho_z_sliced(i, j, local_z)
829 coord_sbuf(3*ii - 2) = u(1)
830 coord_sbuf(3*ii - 1) = u(2)
831 coord_sbuf(3*ii) = u(3)
832 send_pos(dest + 1) = ii + 1
837 CALL pw_grid%para%group%alltoall(sbuf, scount, sdispl, rbuf, rcount, rdispl)
838 CALL pw_grid%para%group%alltoall(coord_sbuf, coord_scount, coord_sdispl, &
839 coord_rbuf, coord_rcount, coord_rdispl)
842 u(1) = coord_rbuf(3*ii - 2)
843 u(2) = coord_rbuf(3*ii - 1)
844 u(3) = coord_rbuf(3*ii)
845 IF (u(1) >= lb(1) .AND. u(1) <= ub(1) .AND. u(2) >= lb(2) .AND. u(2) <= ub(2) .AND. &
846 u(3) >= lb(3) .AND. u(3) <= ub(3))
THEN
847 density%array(u(1), u(2), u(3)) = rbuf(ii)
851 DEALLOCATE (sbuf, rbuf, coord_sbuf, coord_rbuf, coord_scount, coord_sdispl, coord_rcount, &
852 coord_rdispl, scount, sdispl, rcount, rdispl, send_pos)
854 END SUBROUTINE z_slices_to_cp2k_distribution_permuted
866 CHARACTER(len=*),
PARAMETER :: routinen =
'ps_wavelet_solve'
868 CHARACTER(LEN=1) :: geocode
869 INTEGER :: handle, iproc, nproc, nx, ny, nz
870 REAL(kind=
dp) :: hx, hy, hz
872 CALL timeset(routinen, handle)
873 nproc = product(pw_grid%para%group%num_pe_cart)
874 iproc = pw_grid%para%group%mepos
875 geocode = wavelet%geocode
876 CALL get_wavelet_grid(wavelet, pw_grid, nx, ny, nz, hx, hy, hz)
878 CALL psolver(geocode, iproc, nproc, nx, ny, nz, hx, hy, hz, &
879 wavelet%rho_z_sliced, wavelet%karray, pw_grid)
880 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