23 use,
intrinsic :: iso_fortran_env
51 integer,
parameter :: SERIAL = 1
52 integer,
parameter :: WORLD = 2
53 integer,
parameter :: DOMAIN = 3
54 integer,
parameter :: N_CNF = 3
60 real(real64),
allocatable :: kernel(:, :, :)
61 integer :: nfft1, nfft2, nfft3
62 type(mpi_grp_t) :: mpi_grp
68 type(MPI_Comm) :: all_nodes_comm
69 type(isf_cnf_t) :: cnf(1:N_CNF)
72 integer,
parameter :: order_scaling_function = 8
78 subroutine poisson_isf_init(this, namespace, mesh, cube, all_nodes_comm, init_world)
79 type(poisson_isf_t),
intent(out) :: this
80 type(namespace_t),
target,
intent(in) :: namespace
81 type(mesh_t),
intent(in) :: mesh
82 type(cube_t),
intent(inout) :: cube
83 type(MPI_Comm),
intent(in) :: all_nodes_comm
84 logical,
optional,
intent(in) :: init_world
88 integer :: m1, m2, m3, md1, md2, md3
90 logical :: init_world_
91 integer :: default_nodes
93 integer,
allocatable :: ranks(:)
99 type(MPI_Group) :: world_grp, poisson_grp
105 if (
present(init_world)) init_world_ = init_world
107 if (.not. mesh%parallel_in_domains)
then
112 n1 = this%cnf(
serial)%nfft1/2 + 1
113 n2 = this%cnf(
serial)%nfft2/2 + 1
114 n3 = this%cnf(
serial)%nfft3/2 + 1
116 safe_allocate(this%cnf(
serial)%kernel(1:n1, 1:n2, 1:n3))
118 call build_kernel(cube%rs_n_global(1), cube%rs_n_global(2), cube%rs_n_global(3), &
120 real(cube%spacing(1), real64), order_scaling_function, this%cnf(SERIAL)%kernel)
123#if !defined(HAVE_MPI)
132 this%cnf(
domain)%mpi_grp = mesh%mpi_grp
146 call parse_variable(namespace,
'PoissonSolverNodes', default_nodes, nodes)
148 this%all_nodes_comm = all_nodes_comm
151 call mpi_comm_size(all_nodes_comm, world_size)
154 if (nodes <= 0 .or. nodes > world_size) nodes = world_size
155 this%cnf(
world)%all_nodes = (nodes == world_size)
157 safe_allocate(ranks(1:nodes))
168 call mpi_comm_group(all_nodes_comm, world_grp, ierr)
169 call mpi_group_incl(world_grp, nodes, ranks, poisson_grp, ierr)
170 call mpi_comm_create(all_nodes_comm, poisson_grp, this%cnf(
world)%mpi_grp%comm, ierr)
173 safe_deallocate_a(ranks)
177 if (this%cnf(
world)%mpi_grp%comm /= mpi_comm_null)
then
178 call mpi_comm_rank(this%cnf(
world)%mpi_grp%comm, this%cnf(
world)%mpi_grp%rank, ierr)
179 call mpi_comm_size(this%cnf(
world)%mpi_grp%comm, this%cnf(
world)%mpi_grp%size, ierr)
181 this%cnf(
world)%mpi_grp%rank = -1
182 this%cnf(
world)%mpi_grp%size = -1
190 if ((i_cnf ==
world .and. .not. init_world_) &
191 .or. (i_cnf ==
domain .and. .not. mesh%parallel_in_domains) &
195 if (this%cnf(i_cnf)%mpi_grp%rank /= -1 .or. i_cnf /=
world)
then
197 m1, m2, m3, n1, n2, n3, md1, md2, md3, this%cnf(i_cnf)%nfft1, this%cnf(i_cnf)%nfft2, &
198 this%cnf(i_cnf)%nfft3, this%cnf(i_cnf)%mpi_grp%size)
201 n(1) = this%cnf(i_cnf)%nfft1
202 n(2) = this%cnf(i_cnf)%nfft2
203 n(3) = this%cnf(i_cnf)%nfft3
205 safe_allocate(this%cnf(i_cnf)%kernel(1:n(1), 1:n(2), 1:n(3)/this%cnf(i_cnf)%mpi_grp%size))
207 call par_build_kernel(cube%rs_n_global(1), cube%rs_n_global(2), cube%rs_n_global(3), n1, n2, n3, &
208 this%cnf(i_cnf)%nfft1, this%cnf(i_cnf)%nfft2, this%cnf(i_cnf)%nfft3, &
209 cube%spacing(1), order_scaling_function, &
210 this%cnf(i_cnf)%mpi_grp%rank, this%cnf(i_cnf)%mpi_grp%size, this%cnf(i_cnf)%mpi_grp%comm, &
211 this%cnf(i_cnf)%kernel)
223 type(mesh_t),
intent(in) :: mesh
224 type(cube_t),
intent(in) :: cube
225 real(real64),
contiguous,
intent(out) :: pot(:)
226 real(real64),
contiguous,
intent(in) :: rho(:)
227 logical,
intent(in) :: all_nodes
228 type(submesh_t),
optional,
intent(in) :: sm
230 integer :: i_cnf, nn(1:3)
231 type(cube_function_t) :: rho_cf
233 integer(int64) :: number_points
238 call dcube_function_alloc_rs(cube, rho_cf)
240 if (
present(sm))
then
241 call dsubmesh_to_cube(sm, rho, cube, rho_cf)
243 call dmesh_to_cube(mesh, rho, cube, rho_cf)
252 else if (mesh%parallel_in_domains)
then
257#if !defined(HAVE_MPI)
263 nn(1) = this%cnf(
serial)%nfft1
264 nn(2) = this%cnf(
serial)%nfft2
265 nn(3) = this%cnf(
serial)%nfft3
266 call psolver_kernel(cube%rs_n_global(1), cube%rs_n_global(2), cube%rs_n_global(3), &
267 nn(1), nn(2), nn(3), &
268 real(mesh%spacing(1), real64), this%cnf(
serial)%kernel, rho_cf%drs)
271 nn(1) = this%cnf(i_cnf)%nfft1
272 nn(2) = this%cnf(i_cnf)%nfft2
273 nn(3) = this%cnf(i_cnf)%nfft3
274 if (this%cnf(i_cnf)%mpi_grp%size /= -1 .or. i_cnf /=
world)
then
275 call par_psolver_kernel(cube%rs_n_global(1), cube%rs_n_global(2), cube%rs_n_global(3), &
276 nn(1), nn(2), nn(3), &
277 real(mesh%spacing(1), real64), this%cnf(i_cnf)%kernel, rho_cf%drs, &
278 this%cnf(i_cnf)%mpi_grp%rank, this%cnf(i_cnf)%mpi_grp%size, this%cnf(i_cnf)%mpi_grp%comm)
282 if (i_cnf ==
world .and. .not. this%cnf(
world)%all_nodes)
then
285 number_points = cube%rs_n_global(1) * cube%rs_n_global(2)
286 number_points = number_points * cube%rs_n_global(3)
287 if (number_points >= huge(0))
then
288 message(1) =
"Error: too many points for the normal cube. Please try to use a distributed FFT."
289 call messages_fatal(1)
291 call mpi_bcast(rho_cf%drs(1, 1, 1, 1), cube%rs_n_global(1)*cube%rs_n_global(2)*cube%rs_n_global(3), &
292 mpi_double_precision, 0, this%all_nodes_comm)
297 if (
present(sm))
then
298 call dcube_to_submesh(cube, rho_cf, sm, pot)
300 call dcube_to_mesh(cube, rho_cf, mesh, pot)
303 call dcube_function_free_rs(cube, rho_cf)
320 safe_deallocate_a(this%cnf(i_cnf)%kernel)
322 if (this%cnf(
world)%mpi_grp%comm /= mpi_comm_null)
then
323 call mpi_comm_free(this%cnf(
world)%mpi_grp%comm)
326 safe_deallocate_a(this%cnf(
serial)%kernel)
378 subroutine psolver_kernel(n01, n02, n03, nfft1, nfft2, nfft3, hgrid, karray, rhopot)
379 integer,
intent(in) :: n01
380 integer,
intent(in) :: n02
381 integer,
intent(in) :: n03
382 integer,
intent(in) :: nfft1
383 integer,
intent(in) :: nfft2
384 integer,
intent(in) :: nfft3
385 real(real64),
intent(in) :: hgrid
386 real(real64),
intent(in) :: karray(nfft1/2 + 1,nfft2/2 + 1, nfft3/2 + 1)
387 real(real64),
intent(inout) :: rhopot(n01, n02, n03)
389 real(real64),
allocatable :: zarray(:,:,:)
390 real(real64) :: factor
391 integer :: n1, n2, n3, nd1, nd2, nd3, n1h, nd1h
392 integer :: inzee, i_sign
401 nd1 = n1 + modulo(n1+1,2)
402 nd2 = n2 + modulo(n2+1,2)
403 nd3 = n3 + modulo(n3+1,2)
406 safe_allocate(zarray(1:2, 1:nd1h*nd2*nd3, 1:2))
409 call zarray_in(n01,n02,n03,nd1h,nd2,nd3,rhopot,zarray)
415 call fft(n1h,n2,n3,nd1h,nd2,nd3,zarray,i_sign,inzee)
418 call kernel_application(n1,n2,n3,nd1h,nd2,nd3,nfft1,nfft2,nfft3,zarray,karray,inzee)
423 call fft(n1h,n2,n3,nd1h,nd2,nd3,zarray,i_sign,inzee)
427 factor = hgrid**3/(real(n1*n2, real64)*real(n3, real64))
430 call zarray_out(n01, n02, n03, nd1h, nd2, nd3, rhopot, zarray(1, 1, inzee), factor)
432 safe_deallocate_a(zarray)
463 subroutine kernel_application(n1,n2,n3,nd1h,nd2,nd3,nfft1,nfft2,nfft3,zarray,karray,inzee)
464 integer,
intent(in) :: n1,n2,n3,nd1h,nd2,nd3,nfft1,nfft2,nfft3,inzee
465 real(real64),
intent(in) :: karray(1:nfft1/2 + 1, 1:nfft2/2 + 1, 1:nfft3/2 + 1)
466 real(real64),
intent(inout) :: zarray(1:2, 1:nd1h, 1:nd2, 1:nd3, 1:2)
468 real(real64),
dimension(:),
allocatable :: cos_array,sin_array
469 real(real64) :: a,b,c,d,pi2,g1,cp,sp
470 real(real64) :: rfe,ife,rfo,ifo,rk,ik,rk2,ik2,re,ro,ie,io,rhk,ihk
471 integer :: i1,i2,i3,j1,j2,j3, ouzee,n1h,n2h,n3h
472 integer :: si1,si2,si3
480 safe_allocate(cos_array(1:n1h + 1))
481 safe_allocate(sin_array(1:n1h + 1))
483 pi2 = 8._real64*datan(1._real64)
484 pi2 = pi2/real(n1, real64)
486 cos_array(i1) = dcos(pi2*(i1-1))
487 sin_array(i1) = -dsin(pi2*(i1-1))
509 a = zarray(1,i1,i2,i3,inzee)
510 b = zarray(2,i1,i2,i3,inzee)
511 c = zarray(1,si1,si2,si3,inzee)
512 d = zarray(2,si1,si2,si3,inzee)
513 rfe = .5_real64*(a+c)
514 ife = .5_real64*(b-d)
515 rfo = .5_real64*(a-c)
516 ifo = .5_real64*(b+d)
519 rk = rfe+cp*ifo-sp*rfo
520 ik = ife-cp*rfo-sp*ifo
521 g1 = karray(i1,j2,j3)
525 zarray(1,1,i2,i3,ouzee) = rk2
526 zarray(2,1,i2,i3,ouzee) = ik2
532 a=zarray(1,i1,i2,i3,inzee)
533 b=zarray(2,i1,i2,i3,inzee)
534 c=zarray(1,si1,si2,si3,inzee)
535 d=zarray(2,si1,si2,si3,inzee)
548 zarray(1,i1,i2,i3,ouzee) = rk2
549 zarray(2,i1,i2,i3,ouzee) = ik2
556 a=zarray(1,1,i2,i3,inzee)
557 b=zarray(2,1,i2,i3,inzee)
558 c=zarray(1,si1,si2,si3,inzee)
559 d=zarray(2,si1,si2,si3,inzee)
572 zarray(1,i1,i2,i3,ouzee) = rk2
573 zarray(2,i1,i2,i3,ouzee) = ik2
578 j2=n2h+1-abs(n2h+1-i2)
584 a=zarray(1,i1,i2,i3,inzee)
585 b=zarray(2,i1,i2,i3,inzee)
586 c=zarray(1,si1,si2,si3,inzee)
587 d=zarray(2,si1,si2,si3,inzee)
600 zarray(1,1,i2,i3,ouzee) = rk2
601 zarray(2,1,i2,i3,ouzee) = ik2
607 a=zarray(1,i1,i2,i3,inzee)
608 b=zarray(2,i1,i2,i3,inzee)
609 c=zarray(1,si1,si2,si3,inzee)
610 d=zarray(2,si1,si2,si3,inzee)
623 zarray(1,i1,i2,i3,ouzee) = rk2
624 zarray(2,i1,i2,i3,ouzee) = ik2
631 a=zarray(1,1,i2,i3,inzee)
632 b=zarray(2,1,i2,i3,inzee)
633 c=zarray(1,si1,si2,si3,inzee)
634 d=zarray(2,si1,si2,si3,inzee)
647 zarray(1,i1,i2,i3,ouzee) = rk2
648 zarray(2,i1,i2,i3,ouzee) = ik2
654 j3=n3h+1-abs(n3h+1-i3)
665 a=zarray(1,i1,i2,i3,inzee)
666 b=zarray(2,i1,i2,i3,inzee)
667 c=zarray(1,si1,si2,si3,inzee)
668 d=zarray(2,si1,si2,si3,inzee)
681 zarray(1,1,i2,i3,ouzee) = rk2
682 zarray(2,1,i2,i3,ouzee) = ik2
688 a=zarray(1,i1,i2,i3,inzee)
689 b=zarray(2,i1,i2,i3,inzee)
690 c=zarray(1,si1,si2,si3,inzee)
691 d=zarray(2,si1,si2,si3,inzee)
704 zarray(1,i1,i2,i3,ouzee) = rk2
705 zarray(2,i1,i2,i3,ouzee) = ik2
712 a=zarray(1,1,i2,i3,inzee)
713 b=zarray(2,1,i2,i3,inzee)
714 c=zarray(1,si1,si2,si3,inzee)
715 d=zarray(2,si1,si2,si3,inzee)
728 zarray(1,i1,i2,i3,ouzee) = rk2
729 zarray(2,i1,i2,i3,ouzee) = ik2
734 j2=n2h+1-abs(n2h+1-i2)
740 a=zarray(1,i1,i2,i3,inzee)
741 b=zarray(2,i1,i2,i3,inzee)
742 c=zarray(1,si1,si2,si3,inzee)
743 d=zarray(2,si1,si2,si3,inzee)
756 zarray(1,1,i2,i3,ouzee) = rk2
757 zarray(2,1,i2,i3,ouzee) = ik2
763 a=zarray(1,i1,i2,i3,inzee)
764 b=zarray(2,i1,i2,i3,inzee)
765 c=zarray(1,si1,si2,si3,inzee)
766 d=zarray(2,si1,si2,si3,inzee)
779 zarray(1,i1,i2,i3,ouzee) = rk2
780 zarray(2,i1,i2,i3,ouzee) = ik2
787 a=zarray(1,1,i2,i3,inzee)
788 b=zarray(2,1,i2,i3,inzee)
789 c=zarray(1,si1,si2,si3,inzee)
790 d=zarray(2,si1,si2,si3,inzee)
803 zarray(1,i1,i2,i3,ouzee) = rk2
804 zarray(2,i1,i2,i3,ouzee) = ik2
823 a=zarray(1,i1,i2,i3,ouzee)
824 b=zarray(2,i1,i2,i3,ouzee)
825 c=zarray(1,j1,j2,j3,ouzee)
826 d=-zarray(2,j1,j2,j3,ouzee)
836 zarray(1,i1,i2,i3,inzee)=rhk
837 zarray(2,i1,i2,i3,inzee)=ihk
845 a=zarray(1,i1,i2,i3,ouzee)
846 b=zarray(2,i1,i2,i3,ouzee)
847 c=zarray(1,j1,j2,j3,ouzee)
848 d=-zarray(2,j1,j2,j3,ouzee)
858 zarray(1,i1,i2,i3,inzee)=rhk
859 zarray(2,i1,i2,i3,inzee)=ihk
873 a=zarray(1,i1,i2,i3,ouzee)
874 b=zarray(2,i1,i2,i3,ouzee)
875 c=zarray(1,j1,j2,j3,ouzee)
876 d=-zarray(2,j1,j2,j3,ouzee)
886 zarray(1,i1,i2,i3,inzee)=rhk
887 zarray(2,i1,i2,i3,inzee)=ihk
895 a=zarray(1,i1,i2,i3,ouzee)
896 b=zarray(2,i1,i2,i3,ouzee)
897 c=zarray(1,j1,j2,j3,ouzee)
898 d=-zarray(2,j1,j2,j3,ouzee)
908 zarray(1,i1,i2,i3,inzee)=rhk
909 zarray(2,i1,i2,i3,inzee)=ihk
916 safe_deallocate_a(cos_array)
917 safe_deallocate_a(sin_array)
931 subroutine norm_ind(nd1,nd2,nd3,i1,i2,i3,ind)
932 integer :: nd1,nd2,nd3,i1,i2,i3
952 ind = a1 + nd1 * (a2 - 1) + nd1 * nd2 * (a3 - 1)
966 subroutine symm_ind(nd1,nd2,nd3,i1,i2,i3,ind)
967 integer :: nd1,nd2,nd3,i1,i2,i3
986 ind=a1+nd1*(a2-1)+nd1*nd2*(a3-1)
999 subroutine zarray_in(n01,n02,n03,nd1,nd2,nd3,density,zarray)
1000 integer :: n01,n02,n03,nd1,nd2,nd3
1001 real(real64),
dimension(n01,n02,n03) :: density
1002 real(real64),
dimension(2,nd1,nd2,nd3) :: zarray
1004 integer :: i1,i2,i3,n01h,nd1hm,nd3hm,nd2hm
1017 zarray(1,i1,i2,i3) = 0.0_8
1018 zarray(2,i1,i2,i3) = 0.0_8
1026 zarray(1,i1+nd1hm,i2+nd2hm,i3+nd3hm) = density(2*i1-1,i2,i3)
1027 zarray(2,i1+nd1hm,i2+nd2hm,i3+nd3hm) = density(2*i1,i2,i3)
1031 if (modulo(n01,2) == 1)
then
1034 zarray(1,n01h+1+nd1hm,i2+nd2hm,i3+nd3hm) = density(n01,i2,i3)
1054 subroutine zarray_out(n01, n02, n03, nd1, nd2, nd3, rhopot, zarray, factor)
1055 integer,
intent(in) :: n01,n02,n03,nd1,nd2,nd3
1056 real(real64),
intent(out) :: rhopot(n01,n02,n03)
1057 real(real64),
intent(in) :: zarray(2*nd1,nd2,nd3)
1059 real(real64),
intent(in) :: factor
1068 rhopot(i1, i2, i3) = factor*zarray(i1,i2,i3)
1109 subroutine build_kernel(n01,n02,n03,nfft1,nfft2,nfft3,hgrid,itype_scf,karrayout)
1110 integer,
intent(in) :: n01,n02,n03,nfft1,nfft2,nfft3,itype_scf
1111 real(real64),
intent(in) :: hgrid
1112 real(real64),
dimension(nfft1/2+1,nfft2/2+1,nfft3/2+1),
intent(out) :: karrayout
1115 integer,
parameter :: N_GAUSS = 89
1117 integer,
parameter :: n_points = 2**6
1121 real(real64),
parameter :: p0_ref = 1._real64
1122 real(real64),
dimension(N_GAUSS) :: p_gauss,w_gauss
1124 real(real64),
allocatable :: kernel_scf(:), kern_1_scf(:)
1125 real(real64),
allocatable :: x_scf(:), y_scf(:)
1126 real(real64),
allocatable :: karrayhalf(:, :, :)
1128 real(real64) :: ur_gauss,dr_gauss,acc_gauss,pgauss,kern,a_range
1129 real(real64) :: factor,factor2,dx,absci,p0gauss,p0_cell
1130 real(real64) :: a1,a2,a3
1131 integer :: nd1,nd2,nd3,n1k,n2k,n3k,n_scf
1132 integer :: i_gauss,n_range,n_cell
1133 integer :: i,n_iter,i1,i2,i3,i_kern
1134 integer :: i01,i02,i03,inkee,n1h,n2h,n3h,nd1h
1139 n_scf=2*itype_scf*n_points
1147 nd1 = nfft1 + modulo(nfft1+1,2)
1148 nd2 = nfft2 + modulo(nfft2+1,2)
1149 nd3 = nfft3 + modulo(nfft3+1,2)
1155 safe_allocate(x_scf(0:n_scf))
1156 safe_allocate(y_scf(0:n_scf))
1159 call scaling_function(itype_scf,n_scf,n_range,x_scf,y_scf)
1161 dx = real(n_range, real64)/real(n_scf, real64)
1163 n_cell = max(n01,n02,n03)
1164 n_range = max(n_cell,n_range)
1167 safe_allocate(kernel_scf(-n_range:n_range))
1168 safe_allocate(kern_1_scf(-n_range:n_range))
1171 a1 = hgrid * real(n01, real64)
1172 a2 = hgrid * real(n02, real64)
1173 a3 = hgrid * real(n03, real64)
1175 x_scf(:) = hgrid * x_scf(:)
1176 y_scf(:) = 1._real64/hgrid * y_scf(:)
1179 p0_cell = p0_ref/(hgrid*hgrid)
1182 call gequad(n_gauss,p_gauss,w_gauss,ur_gauss,dr_gauss,acc_gauss)
1186 a_range =
sqrt(a1*a1+a2*a2+a3*a3)
1187 factor = 1._real64/a_range
1189 factor2 = 1._real64/(a1*a1+a2*a2+a3*a3)
1190 do i_gauss=1,n_gauss
1191 p_gauss(i_gauss) = factor2*p_gauss(i_gauss)
1193 do i_gauss=1,n_gauss
1194 w_gauss(i_gauss) = factor*w_gauss(i_gauss)
1197 karrayout(:,:,:) = 0.0_8
1200 loop_gauss:
do i_gauss=n_gauss,1,-1
1202 pgauss = p_gauss(i_gauss)
1205 n_iter = nint((
log(pgauss) -
log(p0_cell))/
log(4._real64))
1206 if (n_iter <= 0)
then
1210 p0gauss = pgauss/4._real64**n_iter
1215 kernel_scf(:) = 0.0_8
1219 absci = x_scf(i) - real(i_kern, real64)*hgrid
1221 kern = kern + y_scf(i)*
exp(-p0gauss*absci)*dx
1223 kernel_scf(i_kern) = kern
1224 kernel_scf(-i_kern) = kern
1225 if (abs(kern) < 1.d-18)
then
1232 call scf_recursion(itype_scf,n_iter,n_range,kernel_scf,kern_1_scf)
1241 karrayout(i1,i2,i3) = karrayout(i1,i2,i3) + w_gauss(i_gauss)* &
1242 kernel_scf(i01)*kernel_scf(i02)*kernel_scf(i03)
1249 safe_deallocate_a(kernel_scf)
1250 safe_deallocate_a(kern_1_scf)
1251 safe_deallocate_a(x_scf)
1252 safe_deallocate_a(y_scf)
1255 safe_allocate(karrayhalf(1:2, 1:nd1h*nd2*nd3, 1:2))
1259 call karrayhalf_in(n01,n02,n03,n1k,n2k,n3k,nfft1,nfft2,nfft3,nd1,nd2,nd3,&
1260 karrayout,karrayhalf)
1261 call fft(n1h,nfft2,nfft3,nd1h,nd2,nd3,karrayhalf,1,inkee)
1263 call kernel_recon(n1k,n2k,n3k,nfft1,nfft2,nfft3,nd1,nd2,nd3,&
1264 karrayhalf(1,1,inkee),karrayout)
1266 safe_deallocate_a(karrayhalf)
1282 integer,
intent(in) :: n01,n02,n03
1283 integer,
intent(out) :: nfft1,nfft2,nfft3
1285 integer :: i1,i2,i3,l1
1295 call fourier_dim(i1,nfft1)
1296 call fourier_dim(nfft1/2,l1)
1297 if (modulo(nfft1,2) == 0 .and. modulo(l1,2) == 0 .and. 2*l1 == nfft1)
then
1303 call fourier_dim(i2,nfft2)
1304 if (modulo(nfft2,2) == 0)
then
1310 call fourier_dim(i3,nfft3)
1311 if (modulo(nfft3,2) == 0)
then
1335 subroutine karrayhalf_in(n01,n02,n03,n1k,n2k,n3k,nfft1,nfft2,nfft3,nd1,nd2,nd3, kernel,karrayhalf)
1336 integer,
intent(in) :: n01,n02,n03,n1k,n2k,n3k,nfft1,nfft2,nfft3,nd1,nd2,nd3
1337 real(real64),
dimension(n1k,n2k,n3k),
intent(in) :: kernel
1338 real(real64),
dimension(2,(nd1+1)/2,nd2,nd3),
intent(out) :: karrayhalf
1340 real(real64),
dimension(:),
allocatable :: karray
1341 integer :: i1,i2,i3,nd1h,n1h,n2h,n3h
1350 safe_allocate(karray(1:nfft1))
1353 karrayhalf(:,:,:,:) = 0.0_8
1358 karray(i1+n1h) = kernel(i1,i2,i3)
1361 karray(n1h-i1+1+nd1-nfft1) = kernel(i1,i2,i3)
1364 karrayhalf(1,i1,i2+n2h,i3+n3h) = karray(2*i1-1)
1365 karrayhalf(2,i1,i2+n2h,i3+n3h) = karray(2*i1)
1370 karrayhalf(:,i1,n2h-i2+1+nd2-nfft2,i3+n3h) = &
1371 karrayhalf(:,i1,i2+n2h,i3+n3h)
1378 karrayhalf(:,i1,i2,n3h-i3+1+nd3-nfft3) = karrayhalf(:,i1,i2,i3+n3h)
1383 safe_deallocate_a(karray)
1399 subroutine kernel_recon(n1k,n2k,n3k,nfft1,nfft2,nfft3,nd1,nd2,nd3,zarray,karray)
1400 integer,
intent(in) :: n1k,n2k,n3k,nfft1,nfft2,nfft3,nd1,nd2,nd3
1401 real(real64),
dimension(2,(nd1+1)/2*nd2*nd3),
intent(in) :: zarray
1402 real(real64),
dimension(n1k,n2k,n3k),
intent(out) :: karray
1404 real(real64),
dimension(:),
allocatable :: cos_array,sin_array
1405 integer :: i1,i2,i3,ind1,ind2,nd1h,n1h,n2h,n3h
1406 real(real64) :: rfe,ife,rfo,ifo,cp,sp,rk,ik,a,b,c,d,pi2
1415 pi2=8._real64*datan(1._real64)
1416 pi2=pi2/real(nfft1, real64)
1418 safe_allocate(cos_array(1:nd1h))
1419 safe_allocate(sin_array(1:nd1h))
1422 cos_array(i1)= dcos(pi2*(i1-1))
1423 sin_array(i1)=-dsin(pi2*(i1-1))
1428 call norm_ind(nd1h,nd2,nd3,i1,i2,i3,ind1)
1429 call symm_ind(nd1h,nd2,nd3,i1,i2,i3,ind2)
1434 rfe=0.5_real64*(a+c)
1435 ife=0.5_real64*(b-d)
1436 rfo=0.5_real64*(a-c)
1437 ifo=0.5_real64*(b+d)
1440 rk=rfe+cp*ifo-sp*rfo
1441 ik=ife-cp*rfo-sp*ifo
1455 safe_deallocate_a(cos_array)
1456 safe_deallocate_a(sin_array)
1499 subroutine par_calculate_dimensions(n01,n02,n03,m1,m2,m3,n1,n2,n3, md1,md2,md3,nd1,nd2,nd3,nproc)
1500 integer,
intent(in) :: n01,n02,n03,nproc
1501 integer,
intent(out) :: m1,m2,m3,n1,n2,n3,md1,md2,md3,nd1,nd2,nd3
1525 call fourier_dim(l1,n1)
1527 if (modulo(n1,2) == 0&
1534 call fourier_dim(l2,n2)
1535 if (modulo(n2,2) == 0)
then
1541 call fourier_dim(l3,n3)
1543 if (modulo(n3,2) == 0 &
1556151
if (nproc*(md2/nproc) < n2/2)
then
1568250
if (modulo(nd3,nproc) /= 0)
then
1615 subroutine par_psolver_kernel(n01, n02, n03, nd1, nd2, nd3, hgrid, kernelLOC, rhopot, iproc, nproc, comm)
1616 integer,
intent(in) :: n01,n02,n03,iproc,nproc
1617 integer,
intent(inout) :: nd1,nd2,nd3
1618 real(real64),
intent(in) :: hgrid
1619 real(real64),
intent(in),
dimension(nd1,nd2,nd3/nproc) :: kernelLOC
1620 real(real64),
intent(inout),
dimension(n01,n02,n03) :: rhopot
1621 type(mpi_comm),
intent(in) :: comm
1623 integer :: m1,m2,m3,n1,n2,n3,md1,md2,md3
1627 call par_calculate_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
1628 call pconvxc_off(m1, m2, m3, n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, iproc, nproc, rhopot, kernelloc, hgrid, comm)
1671 subroutine pconvxc_off(m1, m2, m3, n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, iproc, nproc, rhopot, kernelloc, hgrid, comm)
1672 integer,
intent(in) :: m1,m2,m3,n1,n2,n3,nd1,nd2,nd3,md1,md2,md3,iproc,nproc
1673 real(real64),
dimension(nd1,nd2,nd3/nproc),
intent(in) :: kernelloc
1674 real(real64),
dimension(m1,m3,m2),
intent(inout) :: rhopot
1675 real(real64),
intent(in) :: hgrid
1676 type(mpi_comm),
intent(in) :: comm
1679 integer :: istart,iend,jend,jproc
1680 real(real64) :: scal
1681 real(real64),
dimension(:,:,:),
allocatable :: zf, lrhopot(:, :, :)
1682 integer,
dimension(:),
allocatable :: counts, displs
1687 scal=hgrid**3/(real(n1*n2, real64)*real(n3, real64))
1689 safe_allocate(zf(1:md1, 1:md3, 1:md2/nproc))
1690 safe_allocate(counts(0:nproc-1))
1691 safe_allocate(displs(0:nproc-1))
1694 call enterdensity(rhopot(1,1,1), m1, m2, m3, md1, md2, md3, iproc, nproc, zf(1,1,1))
1697 call convolxc_off(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, kernelloc, zf, scal, comm)
1701 do jproc = 0, nproc - 1
1702 istart = min(jproc*(md2/nproc),m2-1)
1703 jend = max(min(md2/nproc, m2 - md2/nproc*jproc), 0)
1704 counts(jproc) = m1*m3*jend
1705 displs(jproc) = istart*m1*m3
1709 istart=min(iproc*(md2/nproc),m2-1)
1710 jend=max(min(md2/nproc,m2-md2/nproc*iproc),0)
1713 if (jend == 0) jend = 1
1715 safe_allocate(lrhopot(1:m1, 1:m3, 1:jend))
1717 lrhopot(1:m1, 1:m3, 1:jend) = zf(1:m1, 1:m3, 1:jend)
1719 call profiling_in(
"ISF_GATHER")
1720#if defined(HAVE_MPI)
1721 call mpi_allgatherv(lrhopot(1, 1, 1), counts(iproc), mpi_double_precision, rhopot(1, 1, 1), counts,&
1722 displs, mpi_double_precision, comm)
1724 call profiling_out(
"ISF_GATHER")
1726 safe_deallocate_a(zf)
1727 safe_deallocate_a(lrhopot)
1728 safe_deallocate_a(counts)
1729 safe_deallocate_a(displs)
1753 subroutine enterdensity(rhopot,m1,m2,m3,md1,md2,md3,iproc,nproc,zf)
1754 integer,
intent(in) :: m1,m2,m3,md1,md2,md3,iproc,nproc
1755 real(real64),
dimension(0:md1-1,0:md3-1,0:md2/nproc-1),
intent(out) :: zf
1756 real(real64),
dimension(0:m1-1,0:m3-1,0:m2-1),
intent(in) :: rhopot
1758 integer :: j1,j2,j3,jp2
1763 do jp2=0,md2/nproc-1
1764 j2=iproc*(md2/nproc)+jp2
1765 if (j2 <= m2-1)
then
1768 zf(j1,j3,jp2)=rhopot(j1,j3,j2)
1822 subroutine par_build_kernel(n01,n02,n03,nfft1,nfft2,nfft3,n1k,n2k,n3k,hgrid,itype_scf, &
1823 iproc,nproc,comm,karrayoutLOC)
1824 integer,
intent(in) :: n01,n02,n03,nfft1,nfft2,nfft3,n1k,n2k,n3k,itype_scf,iproc,nproc
1825 real(real64),
intent(in) :: hgrid
1826 real(real64),
intent(out) :: karrayoutLOC(1:n1k, 1:n2k, 1:n3k/nproc)
1827 type(mpi_comm),
intent(in) :: comm
1830 integer,
parameter :: N_GAUSS = 89
1832 integer,
parameter :: N_POINTS = 2**6
1836 real(real64),
parameter :: p0_ref = 1._real64
1837 real(real64) :: p_gauss(N_GAUSS), w_gauss(N_GAUSS)
1839 real(real64),
dimension(:),
allocatable :: kernel_scf,kern_1_scf
1840 real(real64),
dimension(:),
allocatable :: x_scf ,y_scf
1841 real(real64),
dimension(:,:,:,:),
allocatable :: karrayfour
1842 real(real64),
dimension(:,:,:),
allocatable :: karray
1844 real(real64) :: ur_gauss,dr_gauss,acc_gauss,pgauss,kern,a_range
1845 real(real64) :: factor,factor2,dx,absci,p0gauss,p0_cell
1846 real(real64) :: a1,a2,a3
1847 integer :: n_scf,nker1,nker2,nker3
1848 integer :: i_gauss,n_range,n_cell,istart,iend,istart1,istart2,iend1,iend2
1849 integer :: i,n_iter,i1,i2,i3,i_kern
1850 integer :: i01,i02,i03,n1h,n2h,n3h
1855 n_scf=2*itype_scf*n_points
1874 if (modulo(nker2,nproc) == 0)
exit
1878 if (modulo(nker3,nproc) == 0)
exit
1883 safe_allocate(karray(1:nker1,1:nfft3,1:nker2/nproc))
1888 istart=iproc*nker2/nproc+1
1889 iend=min((iproc+1)*nker2/nproc,n2h+n03)
1892 if (iproc == 0) istart1=n2h-n03+2
1898 if (istart > n2h)
then
1902 if (iend <= n2h)
then
1915 safe_allocate(x_scf(0:n_scf))
1916 safe_allocate(y_scf(0:n_scf))
1919 call scaling_function(itype_scf, n_scf, n_range, x_scf, y_scf)
1921 dx = real(n_range, real64)/real(n_scf, real64)
1923 n_cell = max(n01,n02,n03)
1924 n_range = max(n_cell,n_range)
1927 safe_allocate(kernel_scf(-n_range:n_range))
1928 safe_allocate(kern_1_scf(-n_range:n_range))
1931 a1 = hgrid * real(n01, real64)
1932 a2 = hgrid * real(n02, real64)
1933 a3 = hgrid * real(n03, real64)
1935 x_scf(:) = hgrid * x_scf(:)
1936 y_scf(:) = 1._real64/hgrid * y_scf(:)
1939 p0_cell = p0_ref/(hgrid*hgrid)
1942 call gequad(n_gauss,p_gauss,w_gauss,ur_gauss,dr_gauss,acc_gauss)
1946 a_range =
sqrt(a1*a1+a2*a2+a3*a3)
1947 factor = 1._real64/a_range
1949 factor2 = 1._real64/(a1*a1+a2*a2+a3*a3)
1950 do i_gauss=1,n_gauss
1951 p_gauss(i_gauss) = factor2*p_gauss(i_gauss)
1953 do i_gauss=1,n_gauss
1954 w_gauss(i_gauss) = factor*w_gauss(i_gauss)
1957 karray(:,:,:) = 0.0_8
1959 loop_gauss:
do i_gauss = n_gauss, 1, -1
1961 pgauss = p_gauss(i_gauss)
1964 n_iter = nint((
log(pgauss) -
log(p0_cell))/
log(4._real64))
1965 if (n_iter <= 0)
then
1969 p0gauss = pgauss/4._real64**n_iter
1974 kernel_scf(:) = 0.0_8
1978 absci = x_scf(i) - real(i_kern, real64)*hgrid
1980 kern = kern + y_scf(i)*
exp(-p0gauss*absci)*dx
1982 kernel_scf(i_kern) = kern
1983 kernel_scf(-i_kern) = kern
1984 if (abs(kern) < 1.d-18)
then
1991 call scf_recursion(itype_scf,n_iter,n_range,kernel_scf,kern_1_scf)
2001 karray(i1+n1h,i2+n3h,i3-istart+1) = karray(i1+n1h,i2+n3h,i3-istart+1) + w_gauss(i_gauss)* &
2002 kernel_scf(i01)*kernel_scf(i02)*kernel_scf(i03)
2012 karray(i1+n1h,i2+n3h,i3-istart+1) = karray(i1+n1h,i2+n3h,i3-istart+1) + w_gauss(i_gauss)* &
2013 kernel_scf(i01)*kernel_scf(i02)*kernel_scf(i03)
2026 karray(n1h+2-i1,i2+n3h,i3-istart+1) = karray(i1+n1h,i2+n3h,i3-istart+1)
2031 karray(i1,n3h+2-i2,i3-istart+1) = karray(i1,i2+n3h,i3-istart+1)
2038 safe_deallocate_a(kernel_scf)
2039 safe_deallocate_a(kern_1_scf)
2040 safe_deallocate_a(x_scf)
2041 safe_deallocate_a(y_scf)
2045 safe_allocate(karrayfour(1:2, 1:nker1, 1:nker2, 1:nker3/nproc))
2049 call kernelfft(nfft1,nfft2,nfft3,nker1,nker2,nker3,nproc,iproc,karray,karrayfour,comm)
2055 karrayoutloc(i1,i2,i3)=karrayfour(1,i1,i2,i3)
2061 safe_deallocate_a(karray)
2062 safe_deallocate_a(karrayfour)
2069 subroutine gequad(n_gauss, p_gauss, w_gauss, ur_gauss, dr_gauss, acc_gauss)
2070 integer,
intent(in) :: n_gauss
2071 real(real64),
intent(out) :: p_gauss(:)
2072 real(real64),
intent(out) :: w_gauss(:)
2073 real(real64),
intent(out) :: ur_gauss
2074 real(real64),
intent(out) :: dr_gauss
2075 real(real64),
intent(out) :: acc_gauss
2077 integer :: iunit, i, idx
2082 dr_gauss = 1.0e-08_8
2083 acc_gauss = 1.0e-08_8
2085 iunit = io_open(trim(conf%share)//
'/gequad.data', action =
'read', status =
'old')
2088 read(iunit, *) idx, p_gauss(i), w_gauss(i)
2091 call io_close(iunit)
double log(double __x) __attribute__((__nothrow__
double exp(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
This module defines the meshes, which are used in Octopus.
subroutine symm_ind(nd1, nd2, nd3, i1, i2, i3, ind)
subroutine zarray_in(n01, n02, n03, nd1, nd2, nd3, density, zarray)
subroutine karrayhalf_in(n01, n02, n03, n1k, n2k, n3k, nfft1, nfft2, nfft3, nd1, nd2, nd3, kernel, karrayhalf)
subroutine pconvxc_off(m1, m2, m3, n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, iproc, nproc, rhopot, kernelloc, hgrid, comm)
subroutine, public poisson_isf_end(this)
subroutine build_kernel(n01, n02, n03, nfft1, nfft2, nfft3, hgrid, itype_scf, karrayout)
integer, parameter serial
subroutine norm_ind(nd1, nd2, nd3, i1, i2, i3, ind)
subroutine enterdensity(rhopot, m1, m2, m3, md1, md2, md3, iproc, nproc, zf)
subroutine par_psolver_kernel(n01, n02, n03, nd1, nd2, nd3, hgrid, kernelLOC, rhopot, iproc, nproc, comm)
subroutine kernel_application(n1, n2, n3, nd1h, nd2, nd3, nfft1, nfft2, nfft3, zarray, karray, inzee)
subroutine, public poisson_isf_init(this, namespace, mesh, cube, all_nodes_comm, init_world)
subroutine, public poisson_isf_solve(this, mesh, cube, pot, rho, all_nodes, sm)
subroutine gequad(n_gauss, p_gauss, w_gauss, ur_gauss, dr_gauss, acc_gauss)
subroutine calculate_dimensions(n01, n02, n03, nfft1, nfft2, nfft3)
subroutine par_build_kernel(n01, n02, n03, nfft1, nfft2, nfft3, n1k, n2k, n3k, hgrid, itype_scf, iproc, nproc, comm, karrayoutLOC)
integer, parameter domain
subroutine zarray_out(n01, n02, n03, nd1, nd2, nd3, rhopot, zarray, factor)
subroutine par_calculate_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
subroutine psolver_kernel(n01, n02, n03, nfft1, nfft2, nfft3, hgrid, karray, rhopot)
subroutine kernel_recon(n1k, n2k, n3k, nfft1, nfft2, nfft3, nd1, nd2, nd3, zarray, karray)
These routines are part of the ISF poisson solver, eventually they will be integrated with the other ...