Octopus
poisson_isf.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2011 M. Marques, A. Castro, X. Andrade, J. Alberdi-Rodriguez, M. Oliveira
2!! Copyright (C) Luigi Genovese, Thierry Deutsch, CEA Grenoble, 2006
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
23 use, intrinsic :: iso_fortran_env
25 use cube_oct_m
26 use debug_oct_m
27 use global_oct_m
28 use io_oct_m
30 use mesh_oct_m
31 use mpi_oct_m
33 use parser_oct_m
36 use sgfft_oct_m
38
39 implicit none
40
41 private
42
43 public :: &
45 isf_cnf_t, &
49
50 ! Indices for the cnf array
51 integer, parameter :: SERIAL = 1
52 integer, parameter :: WORLD = 2
53 integer, parameter :: DOMAIN = 3
54 integer, parameter :: N_CNF = 3
55
56 ! Datatype to store kernel values to solve Poisson equation
57 ! on different communicators (configurations).
58 type isf_cnf_t
59 private
60 real(real64), allocatable :: kernel(:, :, :)
61 integer :: nfft1, nfft2, nfft3
62 type(mpi_grp_t) :: mpi_grp
63 logical :: all_nodes
64 end type isf_cnf_t
65
66 type poisson_isf_t
67 private
68 type(MPI_Comm) :: all_nodes_comm
69 type(isf_cnf_t) :: cnf(1:N_CNF)
70 end type poisson_isf_t
71
72 integer, parameter :: order_scaling_function = 8
73
74
75contains
76
77 ! ---------------------------------------------------------
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
85
86 integer :: n1, n2, n3
87 integer :: i_cnf
88 integer :: m1, m2, m3, md1, md2, md3
89 integer :: n(3)
90 logical :: init_world_
91 integer :: default_nodes
92 integer :: ii
93 integer, allocatable :: ranks(:)
94 !data ranks /0, 1/
95 integer :: world_size
96 integer :: nodes
97#ifdef HAVE_MPI
98 integer :: ierr
99 type(MPI_Group) :: world_grp, poisson_grp
100#endif
101
102 push_sub(poisson_isf_init)
103
104 init_world_ = .true.
105 if (present(init_world)) init_world_ = init_world
106
107 if (.not. mesh%parallel_in_domains) then
108 ! The serial version is always needed (as used, e.g., in the casida runmode)
109 call calculate_dimensions(cube%rs_n_global(1), cube%rs_n_global(2), cube%rs_n_global(3), &
110 this%cnf(serial)%nfft1, this%cnf(serial)%nfft2, this%cnf(serial)%nfft3)
111
112 n1 = this%cnf(serial)%nfft1/2 + 1
113 n2 = this%cnf(serial)%nfft2/2 + 1
114 n3 = this%cnf(serial)%nfft3/2 + 1
115
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), &
119 this%cnf(serial)%nfft1, this%cnf(serial)%nfft2, this%cnf(serial)%nfft3, &
120 real(cube%spacing(1), real64), order_scaling_function, this%cnf(SERIAL)%kernel)
121 end if
122
123#if !defined(HAVE_MPI)
124 pop_sub(poisson_isf_init)
125 return
126#endif
127
128 ! Allocate to configurations. The initialisation, especially the kernel,
129 ! depends on the number of nodes used for the calculations. To avoid
130 ! recalculating the kernel on each call of poisson_isf_solve depending on
131 ! the all_nodes argument, both kernels are calculated.
132 this%cnf(domain)%mpi_grp = mesh%mpi_grp
133
134 ! For the world configuration we build a new communicator
135
136 default_nodes = 0 !All nodes
137
138 !%Variable PoissonSolverNodes
139 !%Type integer
140 !%Section Hamiltonian::Poisson
141 !%Default 0
142 !%Description
143 !% How many nodes to use to solve the Poisson equation. A value of
144 !% 0, the default, implies that all available nodes are used.
145 !%End
146 call parse_variable(namespace, 'PoissonSolverNodes', default_nodes, nodes)
148 this%all_nodes_comm = all_nodes_comm
150#if defined(HAVE_MPI)
151 call mpi_comm_size(all_nodes_comm, world_size)
152#endif
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))
159 do ii = 1, nodes
160 ranks(ii) = ii - 1
161 end do
162
163 !create a new communicator
164 !Extract the original group handle and create new comm.
165 ! NOTE: all of world_size, poisson_grp and the created communicator must be derived from
166 ! all_nodes_comm (the communicator of the poisson group, e.g. mc%master_comm), NOT from mpi_world.
167#if defined(HAVE_MPI)
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)
171#endif
172
173 safe_deallocate_a(ranks)
174
175 !Fill the new data structure, for all nodes
176#if defined(HAVE_MPI)
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)
180 else
181 this%cnf(world)%mpi_grp%rank = -1
182 this%cnf(world)%mpi_grp%size = -1
183 end if
184#endif
185
186 ! Build the kernel for all configurations. At the moment, this is
187 ! solving the poisson equation with all nodes (i_cnf == WORLD) and
188 ! with the domain nodes only (i_cnf == DOMAIN).
189 do i_cnf = 2, n_cnf
190 if ((i_cnf == world .and. .not. init_world_) & ! world is disabled
191 .or. (i_cnf == domain .and. .not. mesh%parallel_in_domains) & ! not parallel in domains
192 ) then
193 cycle
194 end if
195 if (this%cnf(i_cnf)%mpi_grp%rank /= -1 .or. i_cnf /= world) then
196 call par_calculate_dimensions(cube%rs_n_global(1), cube%rs_n_global(2), cube%rs_n_global(3), &
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)
199
200 ! Shortcuts to avoid to "line too long" errors.
201 n(1) = this%cnf(i_cnf)%nfft1
202 n(2) = this%cnf(i_cnf)%nfft2
203 n(3) = this%cnf(i_cnf)%nfft3
204
205 safe_allocate(this%cnf(i_cnf)%kernel(1:n(1), 1:n(2), 1:n(3)/this%cnf(i_cnf)%mpi_grp%size))
206
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)
212 else
213 cycle
214 end if
215 end do
216
217 pop_sub(poisson_isf_init)
218 end subroutine poisson_isf_init
219
220 ! ---------------------------------------------------------
221 subroutine poisson_isf_solve(this, mesh, cube, pot, rho, all_nodes, sm)
222 type(poisson_isf_t), intent(in) :: this
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
229
230 integer :: i_cnf, nn(1:3)
231 type(cube_function_t) :: rho_cf
232#if defined(HAVE_MPI)
233 integer(int64) :: number_points
234#endif
235
236 push_sub(poisson_isf_solve)
237
238 call dcube_function_alloc_rs(cube, rho_cf)
239
240 if (present(sm)) then
241 call dsubmesh_to_cube(sm, rho, cube, rho_cf)
242 else
243 call dmesh_to_cube(mesh, rho, cube, rho_cf)
244 end if
245
246 ! Choose configuration.
247 i_cnf = serial
248
249#if defined(HAVE_MPI)
250 if (all_nodes) then
251 i_cnf = world
252 else if (mesh%parallel_in_domains) then
253 i_cnf = domain
254 end if
255#endif
256
257#if !defined(HAVE_MPI)
258 assert(i_cnf == serial)
259#endif
260
261 if (i_cnf == serial) then
262
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)
269
270 else
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)
279 end if
280 ! we need to be sure that the root of every domain-partition has a copy of the potential
281 ! for the moment we broadcast to all nodes, but this is more than what we really need
282 if (i_cnf == world .and. .not. this%cnf(world)%all_nodes) then
283#if defined(HAVE_MPI)
284 ! make sure we do not run into integer overflow here
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)
290 end if
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)
293#endif
294 end if
295 end if
296
297 if (present(sm)) then
298 call dcube_to_submesh(cube, rho_cf, sm, pot)
299 else
300 call dcube_to_mesh(cube, rho_cf, mesh, pot)
301 end if
302
303 call dcube_function_free_rs(cube, rho_cf)
304
305 pop_sub(poisson_isf_solve)
306 end subroutine poisson_isf_solve
308 ! ---------------------------------------------------------
309 subroutine poisson_isf_end(this)
310 type(poisson_isf_t), intent(inout) :: this
311
312#if defined(HAVE_MPI)
313 integer :: i_cnf
314#endif
315
316 push_sub(poisson_isf_end)
317
318#if defined(HAVE_MPI)
319 do i_cnf = 1, n_cnf
320 safe_deallocate_a(this%cnf(i_cnf)%kernel)
321 end do
322 if (this%cnf(world)%mpi_grp%comm /= mpi_comm_null) then
323 call mpi_comm_free(this%cnf(world)%mpi_grp%comm)
324 end if
325#else
326 safe_deallocate_a(this%cnf(serial)%kernel)
327#endif
328
329 pop_sub(poisson_isf_end)
330 end subroutine poisson_isf_end
331
332 ! --------------------------------------------------------------
333
334 !!****h* BigDFT/psolver_kernel
335 !! NAME
336 !! psolver_kernel
337 !!
338 !! FUNCTION
339 !! Solver of Poisson equation applying a kernel
340 !!
341 !! SYNOPSIS
342 !! Poisson solver applying a kernel and
343 !! using Fourier transform for the convolution.
344 !! rhopot : input -> the density
345 !! output -> the Hartree potential + pot_ion
346 !! The potential pot_ion is ADDED in the array rhopot.
347 !! Calculate also the Hartree potential
348 !!
349 !! Replaces the charge density contained in rhopot
350 !! by the Hartree stored as well in rhopot.
351 !! If xc_on is true, it also adds the XC potential and
352 !! ionic potential pot_ion
353 !!
354 !! We double the size of the mesh except in one dimension
355 !! in order to use the property of the density to be real.
356 !! WARNING
357 !! For the use of FFT routine
358 !! inzee=1: first part of Z is data (output) array,
359 !! second part work array
360 !! inzee=2: first part of Z is work array, second part data array
361 !! real(F(i1,i2,i3))=Z(1,i1,i2,i3,inzee)
362 !! imag(F(i1,i2,i3))=Z(2,i1,i2,i3,inzee)
363 !! inzee on output is in general different from inzee on input
364 !!
365 !! AUTHOR
366 !! Thierry Deutsch, Luigi Genovese
367 !! COPYRIGHT
368 !! Copyright (C) 2005 CEA
369 !! CREATION DATE
370 !! 13/07/2005
371 !!
372 !! MODIFICATION HISTORY
373 !! 12/2005 Kernel stored into memory
374 !! 12/2005 Real Kernel FFT and use less memory
375 !!
376 !! SOURCE
377 !!
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)
388
389 real(real64), allocatable :: zarray(:,:,:)
390 real(real64) :: factor
391 integer :: n1, n2, n3, nd1, nd2, nd3, n1h, nd1h
392 integer :: inzee, i_sign
393
394 push_sub(psolver_kernel)
395
396 !Dimension of the FFT
397 call calculate_dimensions(n01, n02, n03, n1, n2, n3)
398
399 !Half size of nd1
400 n1h=n1/2
401 nd1 = n1 + modulo(n1+1,2)
402 nd2 = n2 + modulo(n2+1,2)
403 nd3 = n3 + modulo(n3+1,2)
404 nd1h=(nd1+1)/2
405
406 safe_allocate(zarray(1:2, 1:nd1h*nd2*nd3, 1:2))
407
408 !Set zarray
409 call zarray_in(n01,n02,n03,nd1h,nd2,nd3,rhopot,zarray)
410
411 !FFT
412 !print *,"Do a 3D HalFFT for the density"
413 i_sign=1
414 inzee=1
415 call fft(n1h,n2,n3,nd1h,nd2,nd3,zarray,i_sign,inzee)
416
417 !print *, "Apply the kernel"
418 call kernel_application(n1,n2,n3,nd1h,nd2,nd3,nfft1,nfft2,nfft3,zarray,karray,inzee)
419
420 !Inverse FFT
421 i_sign=-1
422 !print *,"Do a 3D inverse HalFFT"
423 call fft(n1h,n2,n3,nd1h,nd2,nd3,zarray,i_sign,inzee)
424
425 !Recollect the result
426 !We have to multiply by a factor
427 factor = hgrid**3/(real(n1*n2, real64)*real(n3, real64))
428
429 ! Calling this routine gives only the Hartree potential
430 call zarray_out(n01, n02, n03, nd1h, nd2, nd3, rhopot, zarray(1, 1, inzee), factor)
431
432 safe_deallocate_a(zarray)
433 pop_sub(psolver_kernel)
434 end subroutine psolver_kernel
435 !!***
436
437 !!****h* BigDFT/kernel_application
438 !! NAME
439 !! kernel_application
440 !!
441 !! FUNCTION
442 !! Multiply the FFT of the density by the FFT of the kernel
443 !!
444 !! SYNOPSIS
445 !! zarray(:,:,:,:,inzee) : IN -> FFT of the density with the x dimension divided by two
446 !! (HalFFT), OUT -> FFT of the potential
447 !! karray : kernel FFT (real, 1/8 of the total grid)
448 !! n1h,n2,n3 : dimension of the FFT grid for zarray
449 !! nd1h,nd2,nd3 : dimensions of zarray
450 !! nfft1,nfft2,nfft3 : original FFT grid dimensions, to be used for karray dimensions
451 !!
452 !! WARNING
453 !! We use all the zarray vector, storing the auxiliary part using ouzee=3-inzee
454 !! All the loop are unrolled such to avoid different conditions
455 !! the "min" functions are substituted by kink computed with absolute values
456 !! AUTHOR
457 !! Luigi Genovese
458 !! CREATION DATE
459 !! March 2006
460 !!
461 !! SOURCE
462 !!
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)
467
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
473
474 push_sub(kernel_application)
475
476 n1h = n1/2
477 n2h = n2/2
478 n3h = n3/2
479
480 safe_allocate(cos_array(1:n1h + 1))
481 safe_allocate(sin_array(1:n1h + 1))
482
483 pi2 = 8._real64*datan(1._real64)
484 pi2 = pi2/real(n1, real64)
485 do i1 = 1,n1h+1
486 cos_array(i1) = dcos(pi2*(i1-1))
487 sin_array(i1) = -dsin(pi2*(i1-1))
488 end do
489
490 ouzee = 3-inzee
491
492 !--------------------------------------------!
493 !--- Starting reconstruction half -> full ---!
494 !--------------------------------------------!
495
496 !-------------Case i3 = 1
497 i3 = 1
498 j3 = 1
499 si3 = 1
500
501 !-------------Case i2 = 1, i3 = 1
502 i2 = 1
503 j2 = 1
504 si2 = 1
505
506 !Case i1 == 1
507 i1 = 1
508 si1 = 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)
517 cp = cos_array(i1)
518 sp = sin_array(i1)
519 rk = rfe+cp*ifo-sp*rfo
520 ik = ife-cp*rfo-sp*ifo
521 g1 = karray(i1,j2,j3)
522 rk2 = rk*g1
523 ik2 = ik*g1
524
525 zarray(1,1,i2,i3,ouzee) = rk2
526 zarray(2,1,i2,i3,ouzee) = ik2
527
528 !Case i1=2,n1h
529 do i1=2,n1h
530 si1=n1h+2-i1
531
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)
536 rfe=.5_real64*(a+c)
537 ife=.5_real64*(b-d)
538 rfo=.5_real64*(a-c)
539 ifo=.5_real64*(b+d)
540 cp=cos_array(i1)
541 sp=sin_array(i1)
542 rk=rfe+cp*ifo-sp*rfo
543 ik=ife-cp*rfo-sp*ifo
544 g1=karray(i1,j2,j3)
545 rk2=rk*g1
546 ik2=ik*g1
547
548 zarray(1,i1,i2,i3,ouzee) = rk2
549 zarray(2,i1,i2,i3,ouzee) = ik2
550 end do
551
552 !Case i1=n1h+1
553 i1=n1h+1
554 si1=n1h+2-i1
555
556 a=zarray(1,1,i2,i3,inzee) !beware here i1 -> 1
557 b=zarray(2,1,i2,i3,inzee) !beware here i1 -> 1
558 c=zarray(1,si1,si2,si3,inzee)
559 d=zarray(2,si1,si2,si3,inzee)
560 rfe=.5_real64*(a+c)
561 ife=.5_real64*(b-d)
562 rfo=.5_real64*(a-c)
563 ifo=.5_real64*(b+d)
564 cp=cos_array(i1)
565 sp=sin_array(i1)
566 rk=rfe+cp*ifo-sp*rfo
567 ik=ife-cp*rfo-sp*ifo
568 g1=karray(i1,j2,j3)
569 rk2=rk*g1
570 ik2=ik*g1
571
572 zarray(1,i1,i2,i3,ouzee) = rk2
573 zarray(2,i1,i2,i3,ouzee) = ik2
574 !-------------END case i2 = 1 , i3=1
575
576 !case i2 >=2
577 do i2 = 2, n2
578 j2=n2h+1-abs(n2h+1-i2)
579 si2=n2+2-i2 !if i2 /=1, otherwise si2=1
580
581 !Case i1 == 1
582 i1=1
583 si1=1
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)
588 rfe=.5_real64*(a+c)
589 ife=.5_real64*(b-d)
590 rfo=.5_real64*(a-c)
591 ifo=.5_real64*(b+d)
592 cp=cos_array(i1)
593 sp=sin_array(i1)
594 rk=rfe+cp*ifo-sp*rfo
595 ik=ife-cp*rfo-sp*ifo
596 g1=karray(i1,j2,j3)
597 rk2=rk*g1
598 ik2=ik*g1
599
600 zarray(1,1,i2,i3,ouzee) = rk2
601 zarray(2,1,i2,i3,ouzee) = ik2
602
603 !Case i1=2,n1h
604 do i1=2,n1h
605 si1=n1h+2-i1
606
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)
611 rfe=.5_real64*(a+c)
612 ife=.5_real64*(b-d)
613 rfo=.5_real64*(a-c)
614 ifo=.5_real64*(b+d)
615 cp=cos_array(i1)
616 sp=sin_array(i1)
617 rk=rfe+cp*ifo-sp*rfo
618 ik=ife-cp*rfo-sp*ifo
619 g1=karray(i1,j2,j3)
620 rk2=rk*g1
621 ik2=ik*g1
622
623 zarray(1,i1,i2,i3,ouzee) = rk2
624 zarray(2,i1,i2,i3,ouzee) = ik2
625 end do
626
627 !Case i1=n1h+1
628 i1=n1h+1
629 si1=n1h+2-i1
630
631 a=zarray(1,1,i2,i3,inzee) !beware here i1 -> 1
632 b=zarray(2,1,i2,i3,inzee) !beware here i1 -> 1
633 c=zarray(1,si1,si2,si3,inzee)
634 d=zarray(2,si1,si2,si3,inzee)
635 rfe=.5_real64*(a+c)
636 ife=.5_real64*(b-d)
637 rfo=.5_real64*(a-c)
638 ifo=.5_real64*(b+d)
639 cp=cos_array(i1)
640 sp=sin_array(i1)
641 rk=rfe+cp*ifo-sp*rfo
642 ik=ife-cp*rfo-sp*ifo
643 g1=karray(i1,j2,j3)
644 rk2=rk*g1
645 ik2=ik*g1
646
647 zarray(1,i1,i2,i3,ouzee) = rk2
648 zarray(2,i1,i2,i3,ouzee) = ik2
649 end do
650 !-------------END Case i3 = 1
651
652 !case i3 >=2
653 do i3=2,n3
654 j3=n3h+1-abs(n3h+1-i3)
655 si3=n3+2-i3 !if i3 /=1, otherwise si3=1
656
657 !-------------Case i2 = 1
658 i2=1
659 j2=1
660 si2=1
661
662 !Case i1 == 1
663 i1=1
664 si1=1
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)
669 rfe=.5_real64*(a+c)
670 ife=.5_real64*(b-d)
671 rfo=.5_real64*(a-c)
672 ifo=.5_real64*(b+d)
673 cp=cos_array(i1)
674 sp=sin_array(i1)
675 rk=rfe+cp*ifo-sp*rfo
676 ik=ife-cp*rfo-sp*ifo
677 g1=karray(i1,j2,j3)
678 rk2=rk*g1
679 ik2=ik*g1
680
681 zarray(1,1,i2,i3,ouzee) = rk2
682 zarray(2,1,i2,i3,ouzee) = ik2
683
684 !Case i1=2,n1h
685 do i1=2,n1h
686 si1=n1h+2-i1
687
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)
692 rfe=.5_real64*(a+c)
693 ife=.5_real64*(b-d)
694 rfo=.5_real64*(a-c)
695 ifo=.5_real64*(b+d)
696 cp=cos_array(i1)
697 sp=sin_array(i1)
698 rk=rfe+cp*ifo-sp*rfo
699 ik=ife-cp*rfo-sp*ifo
700 g1=karray(i1,j2,j3)
701 rk2=rk*g1
702 ik2=ik*g1
703
704 zarray(1,i1,i2,i3,ouzee) = rk2
705 zarray(2,i1,i2,i3,ouzee) = ik2
706 end do
707
708 !Case i1=n1h+1
709 i1=n1h+1
710 si1=n1h+2-i1
711
712 a=zarray(1,1,i2,i3,inzee) !beware here i1 -> 1
713 b=zarray(2,1,i2,i3,inzee) !beware here i1 -> 1
714 c=zarray(1,si1,si2,si3,inzee)
715 d=zarray(2,si1,si2,si3,inzee)
716 rfe=.5_real64*(a+c)
717 ife=.5_real64*(b-d)
718 rfo=.5_real64*(a-c)
719 ifo=.5_real64*(b+d)
720 cp=cos_array(i1)
721 sp=sin_array(i1)
722 rk=rfe+cp*ifo-sp*rfo
723 ik=ife-cp*rfo-sp*ifo
724 g1=karray(i1,j2,j3)
725 rk2=rk*g1
726 ik2=ik*g1
727
728 zarray(1,i1,i2,i3,ouzee) = rk2
729 zarray(2,i1,i2,i3,ouzee) = ik2
730 !-------------END case i2 = 1
731
732 !case i2 >=2
733 do i2=2,n2
734 j2=n2h+1-abs(n2h+1-i2)
735 si2=n2+2-i2 !if i2 /=1, otherwise si2=1
736
737 !Case i1 == 1
738 i1=1
739 si1=1
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)
744 rfe=.5_real64*(a+c)
745 ife=.5_real64*(b-d)
746 rfo=.5_real64*(a-c)
747 ifo=.5_real64*(b+d)
748 cp=cos_array(i1)
749 sp=sin_array(i1)
750 rk=rfe+cp*ifo-sp*rfo
751 ik=ife-cp*rfo-sp*ifo
752 g1=karray(i1,j2,j3)
753 rk2=rk*g1
754 ik2=ik*g1
755
756 zarray(1,1,i2,i3,ouzee) = rk2
757 zarray(2,1,i2,i3,ouzee) = ik2
758
759 !Case i1=2,n1h
760 do i1=2,n1h
761 si1=n1h+2-i1
762
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)
767 rfe=.5_real64*(a+c)
768 ife=.5_real64*(b-d)
769 rfo=.5_real64*(a-c)
770 ifo=.5_real64*(b+d)
771 cp=cos_array(i1)
772 sp=sin_array(i1)
773 rk=rfe+cp*ifo-sp*rfo
774 ik=ife-cp*rfo-sp*ifo
775 g1=karray(i1,j2,j3)
776 rk2=rk*g1
777 ik2=ik*g1
778
779 zarray(1,i1,i2,i3,ouzee) = rk2
780 zarray(2,i1,i2,i3,ouzee) = ik2
781 end do
782
783 !Case i1=n1h+1
784 i1=n1h+1
785 si1=n1h+2-i1
786
787 a=zarray(1,1,i2,i3,inzee) !beware here i1 -> 1
788 b=zarray(2,1,i2,i3,inzee) !beware here i1 -> 1
789 c=zarray(1,si1,si2,si3,inzee)
790 d=zarray(2,si1,si2,si3,inzee)
791 rfe=.5_real64*(a+c)
792 ife=.5_real64*(b-d)
793 rfo=.5_real64*(a-c)
794 ifo=.5_real64*(b+d)
795 cp=cos_array(i1)
796 sp=sin_array(i1)
797 rk=rfe+cp*ifo-sp*rfo
798 ik=ife-cp*rfo-sp*ifo
799 g1=karray(i1,j2,j3)
800 rk2=rk*g1
801 ik2=ik*g1
802
803 zarray(1,i1,i2,i3,ouzee) = rk2
804 zarray(2,i1,i2,i3,ouzee) = ik2
805 end do
806
807 end do
808
809
810 !--------------------------------------------!
811 !--- Starting reconstruction full -> half ---!
812 !--------------------------------------------!
813
814 !case i3=1
815 i3=1
816 j3=1
817 !case i2=1
818 i2=1
819 j2=1
820 do i1 = 1,n1h
821 j1=n1h+2-i1
822
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)
827 cp=cos_array(i1)
828 sp=sin_array(i1)
829 re=(a+c)
830 ie=(b+d)
831 ro=(a-c)*cp-(b-d)*sp
832 io=(a-c)*sp+(b-d)*cp
833 rhk=re-io
834 ihk=ie+ro
835
836 zarray(1,i1,i2,i3,inzee)=rhk
837 zarray(2,i1,i2,i3,inzee)=ihk
838 end do
839 !case i2 >= 2
840 do i2=2,n2
841 j2=nd2+1-i2
842 do i1 = 1,n1h
843 j1=n1h+2-i1
844
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)
849 cp=cos_array(i1)
850 sp=sin_array(i1)
851 re=(a+c)
852 ie=(b+d)
853 ro=(a-c)*cp-(b-d)*sp
854 io=(a-c)*sp+(b-d)*cp
855 rhk=re-io
856 ihk=ie+ro
857
858 zarray(1,i1,i2,i3,inzee)=rhk
859 zarray(2,i1,i2,i3,inzee)=ihk
860 end do
861 end do
862
863
864 !case i3 >=2
865 do i3=2,n3
866 j3=nd3+1-i3
867 !case i2=1
868 i2=1
869 j2=1
870 do i1 = 1,n1h
871 j1=n1h+2-i1
872
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)
877 cp=cos_array(i1)
878 sp=sin_array(i1)
879 re=(a+c)
880 ie=(b+d)
881 ro=(a-c)*cp-(b-d)*sp
882 io=(a-c)*sp+(b-d)*cp
883 rhk=re-io
884 ihk=ie+ro
885
886 zarray(1,i1,i2,i3,inzee)=rhk
887 zarray(2,i1,i2,i3,inzee)=ihk
888 end do
889 !case i2 >= 2
890 do i2=2,n2
891 j2=nd2+1-i2
892 do i1 = 1,n1h
893 j1=n1h+2-i1
894
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)
899 cp=cos_array(i1)
900 sp=sin_array(i1)
901 re=(a+c)
902 ie=(b+d)
903 ro=(a-c)*cp-(b-d)*sp
904 io=(a-c)*sp+(b-d)*cp
905 rhk=re-io
906 ihk=ie+ro
907
908 zarray(1,i1,i2,i3,inzee)=rhk
909 zarray(2,i1,i2,i3,inzee)=ihk
910 end do
911 end do
912
913 end do
914
915 !De-allocations
916 safe_deallocate_a(cos_array)
917 safe_deallocate_a(sin_array)
918
919 pop_sub(kernel_application)
920 end subroutine kernel_application
921
922 !!****h* BigDFT/norm_ind
923 !! NAME
924 !! norm_ind
925 !!
926 !! FUNCTION
927 !! Index in zarray
928 !!
929 !! SOURCE
930 !!
931 subroutine norm_ind(nd1,nd2,nd3,i1,i2,i3,ind)
932 integer :: nd1,nd2,nd3,i1,i2,i3
933 integer :: ind
934
935 !Local variables
936 integer :: a1,a2,a3
937 if (i1 == nd1) then
938 a1 = 1
939 else
940 a1 = i1
941 end if
942 if (i2 == nd2) then
943 a2 = 1
944 else
945 a2 = i2
946 end if
947 if (i3 == nd3) then
948 a3 = 1
949 else
950 a3 = i3
951 end if
952 ind = a1 + nd1 * (a2 - 1) + nd1 * nd2 * (a3 - 1)
953 end subroutine norm_ind
954 !!***
955
956
957 !!****h* BigDFT/symm_ind
958 !! NAME
959 !! symm_ind
960 !!
961 !! FUNCTION
962 !! Index in zarray for -g vector
963 !!
964 !! SOURCE
965 !!
966 subroutine symm_ind(nd1,nd2,nd3,i1,i2,i3,ind)
967 integer :: nd1,nd2,nd3,i1,i2,i3
968 integer :: ind
969
970 integer :: a1,a2,a3
971 if (i1 /= 1) then
972 a1=nd1+1-i1
973 else
974 a1=i1
975 end if
976 if (i2 /= 1) then
977 a2=nd2+1-i2
978 else
979 a2=i2
980 end if
981 if (i3 /= 1) then
982 a3=nd3+1-i3
983 else
984 a3=i3
985 end if
986 ind=a1+nd1*(a2-1)+nd1*nd2*(a3-1)
987 end subroutine symm_ind
988 !!***
989
990 !!****h* BigDFT/zarray_in
991 !! NAME
992 !! zarray_in
993 !!
994 !! FUNCTION
995 !! Put the density into zarray
996 !!
997 !! SOURCE
998 !!
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
1003
1004 integer :: i1,i2,i3,n01h,nd1hm,nd3hm,nd2hm
1005
1006 push_sub(zarray_in)
1007
1008 !Half the size of n01
1009 n01h=n01/2
1010 nd1hm=(nd1-1)/2
1011 nd2hm=(nd2-1)/2
1012 nd3hm=(nd3-1)/2
1013 !Set to zero
1014 do i3 = 1,nd3
1015 do i2 = 1,nd2
1016 do i1 = 1,nd1
1017 zarray(1,i1,i2,i3) = 0.0_8
1018 zarray(2,i1,i2,i3) = 0.0_8
1019 end do
1020 end do
1021 end do
1022 !Set zarray
1023 do i3 = 1,n03
1024 do i2 = 1,n02
1025 do i1 = 1,n01h
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)
1028 end do
1029 end do
1030 end do
1031 if (modulo(n01,2) == 1) then
1032 do i3 = 1,n03
1033 do i2 = 1,n02
1034 zarray(1,n01h+1+nd1hm,i2+nd2hm,i3+nd3hm) = density(n01,i2,i3)
1035 end do
1036 end do
1037 end if
1038
1039 pop_sub(zarray_in)
1040 end subroutine zarray_in
1041 !!***
1042
1043
1044 !!****h* BigDFT/zarray_out
1045 !! NAME
1046 !! zarray_out
1047 !!
1048 !! FUNCTION
1049 !! Set the potential (rhopot) from zarray
1050 !! Calculate the Hartree energy.
1051 !!
1052 !! SOURCE
1053 !!
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) ! Convert zarray(2,nd1,nd2,nd3) -> zarray(2*nd1,nd2,nd3) to use i1=1,n01
1058 ! ! instead of i1=1,n1h + special case for modulo(n01,2)
1059 real(real64), intent(in) :: factor
1060
1061 integer :: i1,i2,i3
1062
1063 push_sub(zarray_out)
1064
1065 do i3 = 1,n03
1066 do i2 = 1,n02
1067 do i1 = 1,n01
1068 rhopot(i1, i2, i3) = factor*zarray(i1,i2,i3)
1069 end do
1070 end do
1071 end do
1072
1073 pop_sub(zarray_out)
1074 end subroutine zarray_out
1075 !!***
1076
1077 !!****h* BigDFT/build_kernel
1078 !! NAME
1079 !! build_kernel
1080 !!
1081 !! FUNCTION
1082 !! Build the kernel of a gaussian function
1083 !! for interpolating scaling functions.
1084 !!
1085 !! SYNOPSIS
1086 !! Build the kernel (karrayout) of a gaussian function
1087 !! for interpolating scaling functions
1088 !! $$ K(j) = \int \int \phi(x) g(x`-x) \delta(x`- j) dx dx` $$
1089 !!
1090 !! n01,n02,n03 Mesh dimensions of the density
1091 !! n1k,n2k,n3k Dimensions of the kernel
1092 !! hgrid Mesh step
1093 !! itype_scf Order of the scaling function (8,14,16)
1094 !!
1095 !! AUTHORS
1096 !! T. Deutsch, L. Genovese
1097 !! COPYRIGHT
1098 !! Copyright (C) 2005 CEA
1099 !! CREATION DATE
1100 !! 13/07/2005
1101 !!
1102 !! MODIFICATION HISTORY
1103 !! 13/09/2005 Use hgrid instead of acell
1104 !! 09/12/2005 Real kernel, stocked only half components
1105 !! 13/12/2005 Add routines to simplify the port into Stefan`s code
1106 !!
1107 !! SOURCE
1108 !!
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
1114 !Do not touch !!!!
1115 integer, parameter :: N_GAUSS = 89
1116 !Better if higher (1024 points are enough 10^{-14}: 2*itype_scf*n_points)
1117 integer, parameter :: n_points = 2**6
1118
1119 !Better p_gauss for calculation
1120 !(the support of the exponential should be inside [-n_range/2,n_range/2])
1121 real(real64), parameter :: p0_ref = 1._real64
1122 real(real64), dimension(N_GAUSS) :: p_gauss,w_gauss
1123
1124 real(real64), allocatable :: kernel_scf(:), kern_1_scf(:)
1125 real(real64), allocatable :: x_scf(:), y_scf(:)
1126 real(real64), allocatable :: karrayhalf(:, :, :)
1127
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
1135
1136 push_sub(build_kernel)
1137
1138 !Number of integration points : 2*itype_scf*n_points
1139 n_scf=2*itype_scf*n_points
1140 !Dimensions of Kernel
1141 n1k=nfft1/2+1
1142 n2k=nfft2/2+1
1143 n3k=nfft3/2+1
1144 n1h=nfft1/2
1145 n2h=nfft2/2
1146 n3h=nfft3/2
1147 nd1 = nfft1 + modulo(nfft1+1,2)
1148 nd2 = nfft2 + modulo(nfft2+1,2)
1149 nd3 = nfft3 + modulo(nfft3+1,2)
1150
1151 !Half size for the half FFT
1152 nd1h=(nd1+1)/2
1153
1154 !Allocations
1155 safe_allocate(x_scf(0:n_scf))
1156 safe_allocate(y_scf(0:n_scf))
1157
1158 !Build the scaling function
1159 call scaling_function(itype_scf,n_scf,n_range,x_scf,y_scf)
1160 !Step grid for the integration
1161 dx = real(n_range, real64)/real(n_scf, real64)
1162 !Extend the range (no more calculations because fill in by 0.0_8)
1163 n_cell = max(n01,n02,n03)
1164 n_range = max(n_cell,n_range)
1165
1166 !Allocations
1167 safe_allocate(kernel_scf(-n_range:n_range))
1168 safe_allocate(kern_1_scf(-n_range:n_range))
1169
1170 !Lengthes of the box (use FFT dimension)
1171 a1 = hgrid * real(n01, real64)
1172 a2 = hgrid * real(n02, real64)
1173 a3 = hgrid * real(n03, real64)
1174
1175 x_scf(:) = hgrid * x_scf(:)
1176 y_scf(:) = 1._real64/hgrid * y_scf(:)
1177 dx = hgrid * dx
1178 !To have a correct integration
1179 p0_cell = p0_ref/(hgrid*hgrid)
1180
1181 !Initialisation of the gaussian (Beylkin)
1182 call gequad(n_gauss,p_gauss,w_gauss,ur_gauss,dr_gauss,acc_gauss)
1183 !In order to have a range from a_range=sqrt(a1*a1+a2*a2+a3*a3)
1184 !(biggest length in the cube)
1185 !We divide the p_gauss by a_range**2 and a_gauss by a_range
1186 a_range = sqrt(a1*a1+a2*a2+a3*a3)
1187 factor = 1._real64/a_range
1188 !factor2 = factor*factor
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)
1192 end do
1193 do i_gauss=1,n_gauss
1194 w_gauss(i_gauss) = factor*w_gauss(i_gauss)
1195 end do
1196
1197 karrayout(:,:,:) = 0.0_8
1198
1199 !Use in this order (better for accuracy).
1200 loop_gauss: do i_gauss=n_gauss,1,-1
1201 !Gaussian
1202 pgauss = p_gauss(i_gauss)
1203
1204 !We calculate the number of iterations to go from pgauss to p0_ref
1205 n_iter = nint((log(pgauss) - log(p0_cell))/log(4._real64))
1206 if (n_iter <= 0) then
1207 n_iter = 0
1208 p0gauss = pgauss
1209 else
1210 p0gauss = pgauss/4._real64**n_iter
1211 end if
1212
1213 !Stupid integration
1214 !Do the integration with the exponential centered in i_kern
1215 kernel_scf(:) = 0.0_8
1216 do i_kern=0,n_range
1217 kern = 0.0_8
1218 do i=0,n_scf
1219 absci = x_scf(i) - real(i_kern, real64)*hgrid
1220 absci = absci*absci
1221 kern = kern + y_scf(i)*exp(-p0gauss*absci)*dx
1222 end do
1223 kernel_scf(i_kern) = kern
1224 kernel_scf(-i_kern) = kern
1225 if (abs(kern) < 1.d-18) then
1226 !Too small not useful to calculate
1227 exit
1228 end if
1229 end do
1230
1231 !Start the iteration to go from p0gauss to pgauss
1232 call scf_recursion(itype_scf,n_iter,n_range,kernel_scf,kern_1_scf)
1233
1234 !Add to the kernel.
1235 do i3 = 1,n03
1236 i03 = i3-1
1237 do i2 = 1,n02
1238 i02 = i2-1
1239 do i1 = 1,n01
1240 i01 = i1-1
1241 karrayout(i1,i2,i3) = karrayout(i1,i2,i3) + w_gauss(i_gauss)* &
1242 kernel_scf(i01)*kernel_scf(i02)*kernel_scf(i03)
1243 end do
1244 end do
1245 end do
1246
1247 end do loop_gauss
1248
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)
1253
1254 !Set karray
1255 safe_allocate(karrayhalf(1:2, 1:nd1h*nd2*nd3, 1:2))
1256
1257 !Set karray : use mirror symmetries
1258 inkee=1
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)
1262 !Reconstruct the real kernel
1263 call kernel_recon(n1k,n2k,n3k,nfft1,nfft2,nfft3,nd1,nd2,nd3,&
1264 karrayhalf(1,1,inkee),karrayout)
1265
1266 safe_deallocate_a(karrayhalf)
1267 pop_sub(build_kernel)
1268 end subroutine build_kernel
1269 !!***
1270
1271
1272 !!****h* BigDFT/calculate_dimensions
1273 !! NAME
1274 !! calculate_dimensions
1275 !!
1276 !! FUNCTION
1277 !! Give the dimensions of the FFT
1278 !!
1279 !! SOURCE
1280 !!
1281 subroutine calculate_dimensions(n01,n02,n03,nfft1,nfft2,nfft3)
1282 integer, intent(in) :: n01,n02,n03
1283 integer, intent(out) :: nfft1,nfft2,nfft3
1284
1285 integer :: i1,i2,i3,l1
1286
1287 push_sub(calculate_dimensions)
1288
1289 !Test 2*n01, 2*n02, 2*n03
1290 !write(*,*) 'in dimensions_fft',n01,n02,n03
1291 i1=2*n01
1292 i2=2*n02
1293 i3=2*n03
1294 do
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
1298 exit
1299 end if
1300 i1=i1+1
1301 end do
1302 do
1303 call fourier_dim(i2,nfft2)
1304 if (modulo(nfft2,2) == 0) then
1305 exit
1306 end if
1307 i2=i2+1
1308 end do
1309 do
1310 call fourier_dim(i3,nfft3)
1311 if (modulo(nfft3,2) == 0) then
1312 exit
1313 end if
1314 i3=i3+1
1315 end do
1316 !nd1 = nfft1 + modulo(nfft1+1,2)
1317 !nd2 = nfft2 + modulo(nfft2+1,2)
1318 !nd3 = nfft3 + modulo(nfft3+1,2)
1319 !write(*,*) 'out dimensions_fft',nfft1,nfft2,nfft3
1320
1321 pop_sub(calculate_dimensions)
1322 end subroutine calculate_dimensions
1323 !!***
1324
1325
1326 !!****h* BigDFT/karrayhalf_in
1327 !! NAME
1328 !! karrayhalf_in
1329 !!
1330 !! FUNCTION
1331 !! Put in the array for4446666444 FFT
1332 !!
1333 !! SOURCE
1334 !!
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
1339
1340 real(real64), dimension(:), allocatable :: karray
1341 integer :: i1,i2,i3,nd1h,n1h,n2h,n3h
1342
1343 push_sub(karrayhalf_in)
1344
1345 !Body
1346 n1h=nfft1/2
1347 n2h=nfft2/2
1348 n3h=nfft3/2
1349
1350 safe_allocate(karray(1:nfft1))
1351
1352 nd1h=(nd1+1)/2
1353 karrayhalf(:,:,:,:) = 0.0_8
1354 do i3 = 1,n03
1355 do i2 = 1,n02
1356 karray(:) = 0.0_8
1357 do i1 = 1,n01
1358 karray(i1+n1h) = kernel(i1,i2,i3)
1359 end do
1360 do i1 = 2,n01
1361 karray(n1h-i1+1+nd1-nfft1) = kernel(i1,i2,i3)
1362 end do
1363 do i1 = 1,n1h
1364 karrayhalf(1,i1,i2+n2h,i3+n3h) = karray(2*i1-1)
1365 karrayhalf(2,i1,i2+n2h,i3+n3h) = karray(2*i1)
1366 end do
1367 end do
1368 do i2 = 2,n02
1369 do i1 = 1,nd1h
1370 karrayhalf(:,i1,n2h-i2+1+nd2-nfft2,i3+n3h) = &
1371 karrayhalf(:,i1,i2+n2h,i3+n3h)
1372 end do
1373 end do
1374 end do
1375 do i3 = 2,n03
1376 do i2 = 1,nd2
1377 do i1 = 1,nd1h
1378 karrayhalf(:,i1,i2,n3h-i3+1+nd3-nfft3) = karrayhalf(:,i1,i2,i3+n3h)
1379 end do
1380 end do
1381 end do
1382
1383 safe_deallocate_a(karray)
1384 pop_sub(karrayhalf_in)
1385 end subroutine karrayhalf_in
1386 !!***
1387
1388
1389 !!****h* BigDFT/kernel_recon
1390 !! NAME
1391 !! kernel_recon
1392 !!
1393 !! FUNCTION
1394 !! Reconstruction of the kernel from the FFT array zarray
1395 !! We keep only the half kernel in each direction (x,y,z).
1396 !!
1397 !! SOURCE
1398 !!
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
1403
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
1407
1408 push_sub(kernel_recon)
1409
1410 !Body
1411 n1h=nfft1/2
1412 n2h=nfft2/2
1413 n3h=nfft3/2
1414 nd1h=(nd1+1)/2
1415 pi2=8._real64*datan(1._real64)
1416 pi2=pi2/real(nfft1, real64)
1417
1418 safe_allocate(cos_array(1:nd1h))
1419 safe_allocate(sin_array(1:nd1h))
1420
1421 do i1 = 1,nd1h
1422 cos_array(i1)= dcos(pi2*(i1-1))
1423 sin_array(i1)=-dsin(pi2*(i1-1))
1424 end do
1425 do i3 = 1,n3h+1
1426 do i2 = 1,n2h+1
1427 do i1 = 1,nd1h
1428 call norm_ind(nd1h,nd2,nd3,i1,i2,i3,ind1)
1429 call symm_ind(nd1h,nd2,nd3,i1,i2,i3,ind2)
1430 a=zarray(1,ind1)
1431 b=zarray(2,ind1)
1432 c=zarray(1,ind2)
1433 d=zarray(2,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)
1438 cp=cos_array(i1)
1439 sp=sin_array(i1)
1440 rk=rfe+cp*ifo-sp*rfo
1441 ik=ife-cp*rfo-sp*ifo
1442 !For big dimension 1.d-9 otherwise 1.d-10
1443 !Remove the test
1444 !if (abs(ik) >= 1.d-10) then
1445 ! print *,"non real kernel FFT",i1,i2,i3,ik
1446 ! stop
1447 !end if
1448 !Build the intermediate FFT convolution (full)
1449 !call norm_ind(nd1,nd2,nd3,i1,i2,i3,indA)
1450 karray(i1,i2,i3)=rk
1451 end do
1452 end do
1453 end do
1454
1455 safe_deallocate_a(cos_array)
1456 safe_deallocate_a(sin_array)
1457
1459 end subroutine kernel_recon
1460 !!***
1461
1462 !!****h* BigDFT/par_calculate_dimensions
1463 !! NAME
1464 !! par_calculate_dimensions
1465 !!
1466 !! FUNCTION
1467 !! Calculate four sets of dimension needed for the calculation of the
1468 !! zero-padded convolution
1469 !!
1470 !! SYNOPSIS
1471 !! n01,n02,n03 original real dimensions (input)
1472 !!
1473 !! m1,m2,m3 original real dimension with the dimension 2 and 3 exchanged
1474 !!
1475 !! n1,n2 the first FFT even dimensions greater that 2*m1, 2*m2
1476 !! n3 the double of the first FFT even dimension greater than m3
1477 !! (improved for the HalFFT procedure)
1478 !!
1479 !! md1,md2,md3 half of n1,n2,n3 dimension. They contain the real unpadded space,
1480 !! properly enlarged to be compatible with the FFT dimensions n_i.
1481 !! md2 is further enlarged to be a multiple of nproc
1482 !!
1483 !! nd1,nd2,nd3 fourier dimensions for which the kernel FFT is injective,
1484 !! formally 1/8 of the fourier grid. Here the dimension nd3 is
1485 !! enlarged to be a multiple of nproc
1486 !!
1487 !! WARNING
1488 !! The dimension m2 and m3 correspond to n03 and n02 respectively
1489 !! this is needed since the convolution routine manage arrays of dimension
1490 !! (md1,md3,md2/nproc)
1491 !!
1492 !! AUTHOR
1493 !! Luigi Genovese
1494 !! CREATION DATE
1495 !! February 2006
1496 !!
1497 !! SOURCE
1498 !!
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
1502
1503 integer :: l1,l2,l3
1504
1505 push_sub(par_calculate_dimensions)
1506
1507 !dimensions of the density in the real space, inverted for convenience
1508
1509 m1=n01
1510 m2=n03
1511 m3=n02
1512
1513 ! real space grid dimension (suitable for number of processors)
1514
1515 ! n1=2*m1
1516 ! n2=2*m2
1517 ! n3=2*m3
1518
1519 l1=2*m1
1520 l2=2*m2
1521 l3=m3 !beware of the half dimension
1522 do
1523 !this is for the FFT of the kernel
1524 !one can erase it when the kernel is parallelized
1525 call fourier_dim(l1,n1)
1526 !call fourier_dim(n1/2,l1A)
1527 if (modulo(n1,2) == 0&! .and. 2*l1A == n1
1528 ) then
1529 exit
1530 end if
1531 l1=l1+1
1532 end do
1533 do
1534 call fourier_dim(l2,n2)
1535 if (modulo(n2,2) == 0) then
1536 exit
1537 end if
1538 l2=l2+1
1539 end do
1540 do
1541 call fourier_dim(l3,n3)
1542 !call fourier_dim(n3/2,l3A)
1543 if (modulo(n3,2) == 0 &!.and. 2*l3A == n3 .and. modulo(l3A,2) == 0
1544 ) then
1545 exit
1546 end if
1547 l3=l3+1
1548 end do
1549 n3=2*n3
1550
1551 !dimensions that contain the unpadded real space,
1552 ! compatible with the number of processes
1553 md1=n1/2
1554 md2=n2/2
1555 md3=n3/2
1556151 if (nproc*(md2/nproc) < n2/2) then
1557 md2=md2+1
1558 goto 151
1559 end if
1560
1561
1562 !dimensions of the kernel, 1/8 of the total volume,
1563 !compatible with nproc
1564
1565 nd1=n1/2+1
1566 nd2=n2/2+1
1567 nd3=n3/2+1
1568250 if (modulo(nd3,nproc) /= 0) then
1569 nd3=nd3+1
1570 goto 250
1571 end if
1572
1574 end subroutine par_calculate_dimensions
1575 !!***
1576
1577
1578 !!****h* BigDFT/par_psolver_kernel
1579 !! NAME
1580 !! par_psolver_kernel
1581 !!
1582 !! FUNCTION
1583 !! Solver of Poisson equation applying a kernel, parallel computation
1584 !!
1585 !! SYNOPSIS
1586 !! Poisson solver applying a kernel and
1587 !! using Fourier transform for the convolution.
1588 !! rhopot : input -> the density
1589 !! output -> the Hartree potential + pot_ion
1590 !! All the processes manage the same global rhopot array
1591 !! The potential pot_ion is ADDED in the array rhopot.
1592 !! Calculate also the Hartree potential
1593 !!
1594 !! Replaces the charge density contained in rhopot
1595 !! by the Hartree stored as well in rhopot.
1596 !! If xc_on is true, it also adds the XC potential and
1597 !! ionic potential pot_ion
1598 !!
1599 !! kernelLOC: the kernel in fourier space, calculated from ParBuil_Kernel routine
1600 !! it is a local vector (each process have its own part)
1601 !!
1602 !! comm: MPI communicator to use
1603 !!
1604 !! We double the size of the mesh except in one dimension
1605 !! in order to use the property of the density to be real.
1606 !! WARNING
1607 !!
1608 !! AUTHOR
1609 !! Luigi Genovese
1610 !! CREATION DATE
1611 !! February 2006
1612 !!
1613 !! SOURCE
1614 !!
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
1622
1623 integer :: m1,m2,m3,n1,n2,n3,md1,md2,md3
1624
1625 push_sub(par_psolver_kernel)
1626
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)
1629
1630 pop_sub(par_psolver_kernel)
1631 end subroutine par_psolver_kernel
1632 !!***
1633
1634
1635 !!****h* BigDFT/pconvxc_off
1636 !! NAME
1637 !! pconvxc_off
1638 !!
1639 !! FUNCTION
1640 !! Calculate the parallel convolution with the kernel
1641 !! without the exchange-correlation part
1642 !!
1643 !! SYNOPSIS
1644 !! Poisson solver applying a kernel and
1645 !! using Fourier transform for the convolution.
1646 !! rhopot : input -> the density
1647 !! output -> the Hartree potential + pot_ion
1648 !! All the processes manage the same global rhopot array
1649 !! The potential pot_ion is ADDED in the array rhopot.
1650 !! Calculate also the Hartree potential
1651 !!
1652 !! Replaces the charge density contained in rhopot
1653 !! by the Hartree stored as well in rhopot.
1654 !!
1655 !! kernelLOC: the kernel in fourier space, calculated from ParBuild_Kernel routine
1656 !! it is a local vector (each process have its own part)
1657 !!
1658 !! comm: MPI communicator to use
1659 !!
1660 !! We double the size of the mesh except in one dimension
1661 !! in order to use the property of the density to be real.
1662 !! WARNING
1663 !!
1664 !! AUTHOR
1665 !! Luigi Genovese
1666 !! CREATION DATE
1667 !! February 2006
1668 !!
1669 !! SOURCE
1670 !!
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
1677
1678 !Local variables
1679 integer :: istart,iend,jend,jproc
1680 real(real64) :: scal
1681 real(real64), dimension(:,:,:), allocatable :: zf, lrhopot(:, :, :)
1682 integer, dimension(:), allocatable :: counts, displs
1683
1684 push_sub(pconvxc_off)
1685
1686 !factor to be used to keep unitarity
1687 scal=hgrid**3/(real(n1*n2, real64)*real(n3, real64))
1688
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))
1692
1693 !Here we insert the process-related values of the density, starting from the total density
1694 call enterdensity(rhopot(1,1,1), m1, m2, m3, md1, md2, md3, iproc, nproc, zf(1,1,1))
1695
1696 !this routine builds the values for each process of the potential (zf), multiplying by the factor
1697 call convolxc_off(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, kernelloc, zf, scal, comm)
1698
1699 !building the array of the data to be sent from each process
1700 !and the array of the displacement
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
1706 end do
1707
1708 !assign the distributed density to the rhopot array
1709 istart=min(iproc*(md2/nproc),m2-1)
1710 jend=max(min(md2/nproc,m2-md2/nproc*iproc),0)
1711 iend=istart+jend
1712
1713 if (jend == 0) jend = 1
1714
1715 safe_allocate(lrhopot(1:m1, 1:m3, 1:jend))
1716
1717 lrhopot(1:m1, 1:m3, 1:jend) = zf(1:m1, 1:m3, 1:jend)
1718
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)
1723#endif
1724 call profiling_out("ISF_GATHER")
1725
1726 safe_deallocate_a(zf)
1727 safe_deallocate_a(lrhopot)
1728 safe_deallocate_a(counts)
1729 safe_deallocate_a(displs)
1731 pop_sub(pconvxc_off)
1732 end subroutine pconvxc_off
1733!!***
1734
1735
1736 !!****h* BigDFT/enterdensity
1737 !! NAME
1738 !! enterdensity
1739 !!
1740 !! FUNCTION
1741 !!
1742 !! Define a real space process-dependent vector zf with the global dimensions that are half of the FFT grid
1743 !! in order to perform convolution. The dimension md2 is a multiple of nproc
1744 !! Can be used also to define the local part of pot_ion
1745 !!
1746 !! AUTHOR
1747 !! L. Genovese
1748 !! CREATION DATE
1749 !! February 2006
1750 !!
1751 !! SOURCE
1752 !!
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
1757
1758 integer :: j1,j2,j3,jp2
1759
1760 push_sub(enterdensity)
1761
1762 !Body
1763 do jp2=0,md2/nproc-1
1764 j2=iproc*(md2/nproc)+jp2
1765 if (j2 <= m2-1) then
1766 do j3=0,m3-1
1767 do j1=0,m1-1
1768 zf(j1,j3,jp2)=rhopot(j1,j3,j2)
1769 end do
1770 do j1=m1,md1-1
1771 zf(j1,j3,jp2)=0.0_8
1772 end do
1773 end do
1774 do j3=m3,md3-1
1775 do j1=0,md1-1
1776 zf(j1,j3,jp2)=0.0_8
1777 end do
1778 end do
1779 else
1780 do j3=0,md3-1
1781 do j1=0,md1-1
1782 zf(j1,j3,jp2)=0.0_8
1783 end do
1784 end do
1785 end if
1786 end do
1787
1788 pop_sub(enterdensity)
1789 end subroutine enterdensity
1790 !!***
1791
1792
1793 !!****h* BigDFT/par_build_kernel
1794 !! NAME
1795 !! par_build_kernel
1796 !!
1797 !! FUNCTION
1798 !! Build the kernel of a gaussian function
1799 !! for interpolating scaling functions.
1800 !! Do the parallel HalFFT of the symmetrized function and stores into
1801 !! memory only 1/8 of the grid divided by the number of processes nproc
1802 !!
1803 !! SYNOPSIS
1804 !! Build the kernel (karray) of a gaussian function
1805 !! for interpolating scaling functions
1806 !! $$ K(j) = \sum_k \omega_k \int \int \phi(x) g_k(y-x) \delta(y-j) dx dy $$
1807 !!
1808 !! n01,n02,n03 Mesh dimensions of the density
1809 !! nfft1,nfft2,nfft3 Dimensions of the FFT grid (HalFFT in the third direction)
1810 !! n1k,n2k,n3k Dimensions of the kernel FFT
1811 !! hgrid Mesh step
1812 !! itype_scf Order of the scaling function (8,14,16)
1813 !! comm MPI communicator to use
1814 !!
1815 !! AUTHORS
1816 !! T. Deutsch, L. Genovese
1817 !! CREATION DATE
1818 !! February 2006
1819 !!
1820 !! SOURCE
1821 !!
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
1828
1829 !Do not touch !!!!
1830 integer, parameter :: N_GAUSS = 89
1831 !Better if higher (1024 points are enough 10^{-14}: 2*itype_scf*n_points)
1832 integer, parameter :: N_POINTS = 2**6
1833
1834 !Better p_gauss for calculation
1835 !(the support of the exponential should be inside [-n_range/2,n_range/2])
1836 real(real64), parameter :: p0_ref = 1._real64
1837 real(real64) :: p_gauss(N_GAUSS), w_gauss(N_GAUSS)
1838
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
1843
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
1851
1852 push_sub(par_build_kernel)
1853
1854 !Number of integration points : 2*itype_scf*n_points
1855 n_scf=2*itype_scf*n_points
1856 !Set karray
1857 !dimension test
1858
1859 !here we must set the dimensions for the fft part, starting from the nfft
1860 !remember that actually nfft2 is associated with n03 and viceversa
1861
1862 !dimensions that define the center of symmetry
1863 n1h=nfft1/2
1864 n2h=nfft2/2
1865 n3h=nfft3/2
1866
1867 !Auxiliary dimensions only for building the FFT part
1868 nker1=nfft1
1869 nker2=nfft2
1870 nker3=nfft3/2+1
1871
1872 !adjusting the last two dimensions to be multiples of nproc
1873 do
1874 if (modulo(nker2,nproc) == 0) exit
1875 nker2=nker2+1
1876 end do
1877 do
1878 if (modulo(nker3,nproc) == 0) exit
1879 nker3=nker3+1
1880 end do
1882 !this will be the array of the kernel in the real space
1883 safe_allocate(karray(1:nker1,1:nfft3,1:nker2/nproc))
1884
1885 !defining proper extremes for the calculation of the
1886 !local part of the kernel
1887
1888 istart=iproc*nker2/nproc+1
1889 iend=min((iproc+1)*nker2/nproc,n2h+n03)
1890
1891 istart1=istart
1892 if (iproc == 0) istart1=n2h-n03+2
1893
1894 iend2=iend
1895
1896 iend1=n2h
1897 istart2=n2h+1
1898 if (istart > n2h) then
1899 iend1=istart1-1
1900 istart2=istart
1901 end if
1902 if (iend <= n2h) then
1903 istart2=iend2+1
1904 iend1=iend
1905 end if
1906
1907!!!!!START KERNEL CONSTRUCTION
1908 ! if (iproc == 0) then
1909 ! write(unit=*,fmt="(1x,a,i0,a)") &
1910 ! "Build the kernel in parallel using a sum of ",N_GAUSS," gaussians"
1911 ! write(unit=*,fmt="(1x,a,i0,a)") &
1912 ! "Use interpolating scaling functions of ",itype_scf," order"
1913 ! end if
1914
1915 safe_allocate(x_scf(0:n_scf))
1916 safe_allocate(y_scf(0:n_scf))
1917
1918 !Build the scaling function
1919 call scaling_function(itype_scf, n_scf, n_range, x_scf, y_scf)
1920 !Step grid for the integration
1921 dx = real(n_range, real64)/real(n_scf, real64)
1922 !Extend the range (no more calculations because fill in by 0.0_8)
1923 n_cell = max(n01,n02,n03)
1924 n_range = max(n_cell,n_range)
1925
1926 !Allocations
1927 safe_allocate(kernel_scf(-n_range:n_range))
1928 safe_allocate(kern_1_scf(-n_range:n_range))
1929
1930 !Lengthes of the box (use FFT dimension)
1931 a1 = hgrid * real(n01, real64)
1932 a2 = hgrid * real(n02, real64)
1933 a3 = hgrid * real(n03, real64)
1934
1935 x_scf(:) = hgrid * x_scf(:)
1936 y_scf(:) = 1._real64/hgrid * y_scf(:)
1937 dx = hgrid * dx
1938 !To have a correct integration
1939 p0_cell = p0_ref/(hgrid*hgrid)
1940
1941 !Initialization of the gaussian (Beylkin)
1942 call gequad(n_gauss,p_gauss,w_gauss,ur_gauss,dr_gauss,acc_gauss)
1943 !In order to have a range from a_range=sqrt(a1*a1+a2*a2+a3*a3)
1944 !(biggest length in the cube)
1945 !We divide the p_gauss by a_range**2 and a_gauss by a_range
1946 a_range = sqrt(a1*a1+a2*a2+a3*a3)
1947 factor = 1._real64/a_range
1948 !factor2 = factor*factor
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)
1952 end do
1953 do i_gauss=1,n_gauss
1954 w_gauss(i_gauss) = factor*w_gauss(i_gauss)
1955 end do
1956
1957 karray(:,:,:) = 0.0_8
1958 !Use in this order (better for accuracy).
1959 loop_gauss: do i_gauss = n_gauss, 1, -1
1960 !Gaussian
1961 pgauss = p_gauss(i_gauss)
1962
1963 !We calculate the number of iterations to go from pgauss to p0_ref
1964 n_iter = nint((log(pgauss) - log(p0_cell))/log(4._real64))
1965 if (n_iter <= 0) then
1966 n_iter = 0
1967 p0gauss = pgauss
1968 else
1969 p0gauss = pgauss/4._real64**n_iter
1970 end if
1971
1972 !Stupid integration
1973 !Do the integration with the exponential centered in i_kern
1974 kernel_scf(:) = 0.0_8
1975 do i_kern=0,n_range
1976 kern = 0.0_8
1977 do i=0,n_scf
1978 absci = x_scf(i) - real(i_kern, real64)*hgrid
1979 absci = absci*absci
1980 kern = kern + y_scf(i)*exp(-p0gauss*absci)*dx
1981 end do
1982 kernel_scf(i_kern) = kern
1983 kernel_scf(-i_kern) = kern
1984 if (abs(kern) < 1.d-18) then
1985 !Too small not useful to calculate
1986 exit
1987 end if
1988 end do
1989
1990 !Start the iteration to go from p0gauss to pgauss
1991 call scf_recursion(itype_scf,n_iter,n_range,kernel_scf,kern_1_scf)
1992
1993 !Add to the kernel (only the local part)
1994
1995 do i3=istart1,iend1
1996 i03 = n2h - i3 + 1
1997 do i2 = 1,n02
1998 i02 = i2-1
1999 do i1 = 1,n01
2000 i01 = i1-1
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)
2003 end do
2004 end do
2005 end do
2006 do i3=istart2,iend2
2007 i03 = i3 - n2h -1
2008 do i2 = 1,n02
2009 i02 = i2-1
2010 do i1 = 1,n01
2011 i01 = i1-1
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)
2014 end do
2015 end do
2016 end do
2017
2018
2019 end do loop_gauss
2020
2021 !Build the kernel in the real space as an even function, thus having a real FFT
2022
2023 do i3=istart1,iend2
2024 do i2 = 1,n02
2025 do i1=2,n01
2026 karray(n1h+2-i1,i2+n3h,i3-istart+1) = karray(i1+n1h,i2+n3h,i3-istart+1)
2027 end do
2028 end do
2029 do i2=2,n02
2030 do i1 = 1,nker1
2031 karray(i1,n3h+2-i2,i3-istart+1) = karray(i1,i2+n3h,i3-istart+1)
2032 end do
2033 end do
2034 end do
2035
2036
2037 !De-allocations
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)
2042
2043!!!!END KERNEL CONSTRUCTION
2044
2045 safe_allocate(karrayfour(1:2, 1:nker1, 1:nker2, 1:nker3/nproc))
2046
2047 ! if (iproc == 0) print *,"Do a 3D PHalFFT for the kernel"
2048
2049 call kernelfft(nfft1,nfft2,nfft3,nker1,nker2,nker3,nproc,iproc,karray,karrayfour,comm)
2050
2051 !Reconstruct the real kernel FFT
2052 do i3 = 1,n3k/nproc
2053 do i2 = 1,n2k
2054 do i1 = 1,n1k
2055 karrayoutloc(i1,i2,i3)=karrayfour(1,i1,i2,i3)
2056 end do
2057 end do
2058 end do
2059
2060 !De-allocations
2061 safe_deallocate_a(karray)
2062 safe_deallocate_a(karrayfour)
2063 pop_sub(par_build_kernel)
2064 end subroutine par_build_kernel
2065 !!***
2066
2067 ! -------------------------------------------------------------------------
2068
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
2076
2077 integer :: iunit, i, idx
2078
2079 push_sub(gequad)
2080
2081 ur_gauss = 1.0_8
2082 dr_gauss = 1.0e-08_8
2083 acc_gauss = 1.0e-08_8
2084
2085 iunit = io_open(trim(conf%share)//'/gequad.data', action = 'read', status = 'old')
2086
2087 do i = 1, n_gauss
2088 read(iunit, *) idx, p_gauss(i), w_gauss(i)
2089 end do
2090
2091 call io_close(iunit)
2092
2093 pop_sub(gequad)
2094 end subroutine gequad
2095
2096end module poisson_isf_oct_m
2097
2098!! Local Variables:
2099!! mode: f90
2100!! coding: utf-8
2101!! End:
double log(double __x) __attribute__((__nothrow__
double exp(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
Definition: io.F90:116
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
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)
integer, parameter n_cnf
integer, parameter world
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 ...
Definition: sgfft.F90:119
int true(void)