Line data Source code
1 : !!****m* ABINIT/m_dfti
2 : !! NAME
3 : !! m_dfti
4 : !!
5 : !! FUNCTION
6 : !! This module provides wrappers for the MKL DFTI routines: in-place and out-of-place version.
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 2009-2026 ABINIT group (MG)
10 : !! This file is distributed under the terms of the
11 : !! GNU General Public License, see ~abinit/COPYING
12 : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : !!
14 : !! NOTES
15 : !! 1) MPI parallelism is not supported
16 : !! 2) For better performance the FFT divisions should contain small factors (/2, 3, 5, 7, 11, 13/)
17 : !! see http://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_userguide_lnx/index.htm
18 : !!
19 : !! SOURCE
20 :
21 : #if defined HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 :
25 : #include "abi_common.h"
26 :
27 : #ifdef HAVE_DFTI
28 :
29 : ! Include MKL_DFTI fortran module
30 : #include "mkl_dfti.f90"
31 :
32 : ! Macros for template files.
33 : #define FFTLIB "DFTI"
34 : #define FFT_PREF_fftrisc dfti_fftrisc
35 : #define FFT_PREF_fftrisc_mixprec dfti_fftrisc_mixprec
36 : #define FFT_PREF_fftpad dfti_fftpad
37 : #define FFT_PREF_fftug_dp dfti_fftug_dp
38 : #define FFT_PREF_fftur_dp dfti_fftur_dp
39 : #define FFT_PREF_fftug dfti_fftug
40 : #define FFT_PREF_fftur dfti_fftur
41 : #define SPAWN_THREADS_HERE(ndat, nthreads) dfti_spawn_threads_here(ndat, nthreads)
42 :
43 : #define FFT_DOUBLE 1
44 : #define FFT_SINGLE 2
45 : #define FFT_MIXPREC 3
46 :
47 : #endif
48 :
49 : MODULE m_dfti
50 :
51 : use, intrinsic :: iso_c_binding
52 : use defs_basis
53 : use m_abicore
54 : use m_errors
55 : use m_xomp
56 : use m_cgtools
57 : use m_cplxtools
58 : use m_fftcore
59 : use m_fft_mesh
60 : #ifdef HAVE_DFTI
61 : use MKL_DFTI
62 : #endif
63 :
64 : use m_fstrings, only : basename, strcat, int2char10, itoa, sjoin
65 : use m_hide_blas, only : xcopy
66 :
67 : implicit none
68 :
69 : private
70 :
71 : ! Entry points for client code
72 : public :: dfti_seqfourdp ! 3D FFT of lengths nx, ny, nz. Mainly used for densities or potentials.
73 : public :: dfti_seqfourwf ! FFT transform of wavefunctions (high-level interface).
74 : public :: dfti_fftrisc
75 : public :: dfti_fftrisc_mixprec ! Mixed precision version of fftrisc: input/output in dp, computation done in sp.
76 : public :: dfti_fftug ! G-->R, 3D zero-padded FFT of lengths nx, ny, nz. Mainly used for wavefunctions
77 : public :: dfti_fftur ! R-->G, 3D zero-padded FFT of lengths nx, ny, nz. Mainly used for wavefunctions
78 :
79 : ! Low-level routines.
80 : public :: dfti_r2c_op ! Real to complex transform (out-of-place version).
81 : public :: dfti_c2r_op ! Complex to real transform (out-of-place version).
82 : public :: dfti_c2c_op ! complex to complex transform (out-of-place version).
83 : public :: dfti_c2c_ip ! complex to complex transform (in-place version).
84 : public :: dfti_many_dft_op ! Driver routine for many out-of-place 3D complex-to-complex FFTs.
85 : public :: dfti_many_dft_ip ! Driver routine for many in-place 3D complex-to-complex FFTs.
86 : public :: dfti_fftpad ! Driver routines for zero-padded FFT of wavefunctions.
87 :
88 : !FIXME I don't know why gcc does not recognize this one
89 : ! Perhaps I have to provide an interfaces for fofr(:,:,:,:)
90 : public :: dfti_fftpad_dp ! Driver routines for zero-padded FFT of wavefunctions.
91 : public :: dfti_fftug_dp ! Driver routines for zero-padded FFT of wavefunctions.
92 : public :: dfti_use_lib_threads
93 : !!***
94 :
95 : interface dfti_fftrisc
96 : module procedure dfti_fftrisc_sp
97 : module procedure dfti_fftrisc_dp
98 : end interface dfti_fftrisc
99 :
100 : interface dfti_fftug
101 : module procedure dfti_fftug_dp
102 : module procedure dfti_fftug_spc
103 : module procedure dfti_fftug_dpc
104 : end interface dfti_fftug
105 :
106 : interface dfti_fftur
107 : module procedure dfti_fftur_dp
108 : module procedure dfti_fftur_spc
109 : module procedure dfti_fftur_dpc
110 : end interface dfti_fftur
111 :
112 : interface dfti_r2c_op
113 : module procedure dfti_r2c_op_dp
114 : module procedure dfti_r2c_op_dpc
115 : end interface dfti_r2c_op
116 :
117 : interface dfti_c2r_op
118 : module procedure dfti_c2r_op_dp
119 : module procedure dfti_c2r_op_dpc
120 : end interface dfti_c2r_op
121 :
122 : interface dfti_c2c_op
123 : module procedure dfti_c2c_op_spc
124 : module procedure dfti_c2c_op_dpc
125 : end interface dfti_c2c_op
126 :
127 : interface dfti_c2c_ip
128 : module procedure dfti_c2c_ip_spc
129 : module procedure dfti_c2c_ip_dpc
130 : end interface dfti_c2c_ip
131 :
132 : !interface dfti_many_dft_op
133 : ! module procedure dfti_many_dft_op
134 : ! module procedure dfti_many_dft_op
135 : !end interface dfti_many_dft_op
136 :
137 : !interface dfti_many_dft_ip
138 : ! module procedure dfti_many_dft_ip
139 : ! module procedure dfti_many_dft_ip
140 : !end interface dfti_many_dft_ip
141 :
142 : interface dfti_fftpad
143 : module procedure dfti_fftpad_dp
144 : module procedure dfti_fftpad_spc
145 : module procedure dfti_fftpad_dpc
146 : end interface dfti_fftpad
147 :
148 : logical,private,save :: USE_LIB_THREADS = .FALSE.
149 :
150 : #ifdef HAVE_DFTI
151 : ! dfti_alloc_* allocates arrays aligned on DFTI_DEFAULT_ALIGNMENT boundaries.
152 : integer(C_INT),private,parameter :: DFTI_DEFAULT_ALIGNMENT_SP = 64
153 : integer(C_INT),private,parameter :: DFTI_DEFAULT_ALIGNMENT_DP = 64
154 :
155 : interface dfti_alloc_real
156 : !module procedure dfti_alloc_real_sp
157 : module procedure dfti_alloc_real_dp
158 : end interface dfti_alloc_real
159 :
160 : interface dfti_alloc_complex
161 : module procedure dfti_alloc_complex_spc
162 : module procedure dfti_alloc_complex_dpc
163 : end interface dfti_alloc_complex
164 :
165 : ! Fortran binding for MKL_malloc
166 : interface mkl_malloc
167 : type(C_PTR) function mkl_malloc(alloc_size, alignment) bind(C, name='MKL_malloc')
168 : import
169 : integer(C_SIZE_T), value :: alloc_size
170 : integer(C_INT), value :: alignment
171 : end function mkl_malloc
172 : end interface mkl_malloc
173 :
174 : ! Fortran binding for MKL_free
175 : interface dfti_free
176 : subroutine mkl_free(cptr) bind(C, name='MKL_free')
177 : import
178 : type(C_PTR), value :: cptr
179 : end subroutine mkl_free
180 : end interface dfti_free
181 : #endif
182 :
183 : !----------------------------------------------------------------------
184 :
185 : CONTAINS !===========================================================
186 : !!***
187 :
188 : !!****f* m_dfti/dfti_seqfourdp
189 : !! NAME
190 : !! dfti_seqfourdp
191 : !!
192 : !! FUNCTION
193 : !! Driver routine for 3D FFT of lengths nx, ny, nz. Mainly used for densities or potentials.
194 : !! FFT Transform is out-of-place
195 : !!
196 : !! INPUTS
197 : !! cplex=1 if fofr is real, 2 if fofr is complex
198 : !! nx,ny,nz=Number of point along the three directions.
199 : !! ldx,ldy,ldz=Leading dimensions of the array.
200 : !! ndat = Number of FFTS
201 : !! isign= +1 : fofg(G) => fofr(R);
202 : !! -1 : fofr(R) => fofg(G)
203 : !! fofg(2,ldx*ldy*ldz*ndat)=The array to be transformed.
204 : !!
205 : !! OUTPUT
206 : !! fofr(cplex,ldx*ldy*ldz*ndat)=The FFT of fofg
207 : !!
208 : !! SOURCE
209 :
210 1248302 : subroutine dfti_seqfourdp(cplex,nx,ny,nz,ldx,ldy,ldz,ndat,isign,fofg,fofr)
211 :
212 : !Arguments ------------------------------------
213 : !scalars
214 : integer,intent(in) :: cplex,nx,ny,nz,ldx,ldy,ldz,ndat,isign
215 : !arrays
216 : real(dp),intent(inout) :: fofg(2*ldx*ldy*ldz*ndat)
217 : real(dp),intent(inout) :: fofr(cplex*ldx*ldy*ldz*ndat)
218 :
219 : !Local variables-------------------------------
220 : !scalars
221 : integer,parameter :: iscale1 = 1
222 : integer :: ii,jj
223 1248302 : complex(sp), allocatable :: work_sp(:)
224 : ! *************************************************************************
225 :
226 498031 : select case (cplex)
227 : case (2)
228 : ! Complex to Complex.
229 498031 : if (fftcore_mixprec == 1) then
230 : ! Mixed precision: copy in + in-place + copyout
231 100752 : ABI_MALLOC(work_sp, (ldx*ldy*ldz*ndat))
232 33584 : if (isign == +1) then
233 84745007 : work_sp(:) = cmplx(fofg(1::2), fofg(2::2), kind=sp)
234 9901 : else if (isign == -1) then
235 77821821 : work_sp(:) = cmplx(fofr(1::2), fofr(2::2), kind=sp)
236 : else
237 0 : ABI_BUG("Wrong isign")
238 : end if
239 :
240 33584 : call dfti_c2c_ip_spc(nx, ny, nz, ldx, ldy, ldz, ndat, iscale1, isign, work_sp)
241 :
242 33584 : if (isign == +1) then
243 : jj = 1
244 84745007 : do ii=1,ldx*ldy*ldz*ndat
245 84721324 : fofr(jj) = real(work_sp(ii), kind=dp)
246 84721324 : fofr(jj+1) = aimag(work_sp(ii))
247 84745007 : jj = jj + 2
248 : end do
249 9901 : else if (isign == -1) then
250 : jj = 1
251 77821821 : do ii=1,ldx*ldy*ldz*ndat
252 77811920 : fofg(jj) = real(work_sp(ii), kind=dp)
253 77811920 : fofg(jj+1) = aimag(work_sp(ii))
254 77821821 : jj = jj + 2
255 : end do
256 : end if
257 33584 : ABI_FREE(work_sp)
258 :
259 : else
260 : ! double precision version.
261 699204 : select case (isign)
262 : case (+1)
263 234757 : call dfti_many_dft_op(nx,ny,nz,ldx,ldy,ldz,ndat,isign,fofg,fofr)
264 : case (-1) ! -1
265 229690 : call dfti_many_dft_op(nx,ny,nz,ldx,ldy,ldz,ndat,isign,fofr,fofg)
266 : case default
267 464447 : ABI_BUG("Wrong isign")
268 : end select
269 : end if
270 :
271 : case (1)
272 : ! Real case.
273 :
274 : ! MG: June 24. 2025
275 : ! dfti_seqfourdp does not work as expected when cplex= 1 and ngfft(1:3) != ngfft(4:6)
276 : ! very likely due to the use of r->c, c->r transforms.
277 : ! I don't know if it's a bug as the error seems to depend on the mkl version.
278 : ! To bypass this problem, we change the params on the fly so that ngfft(1:3) == ngfft(4:6)
279 : ! when FFT_DFTI is used.
280 : ! Note however that we never call fourdp with ngfft(1:3) != ngftt(4:6) so this is not a serious problem.
281 : ! An additional check is done inside dfti_seqfourdp
282 :
283 750271 : if (nx /= ldx .or. ny /= ldy .or. nz /= ldz) then
284 0 : ABI_ERROR("dfti_seqfourdp is buggy/not portable when nx /= ldx .or. ny /= ldy .or. nz /= ldz")
285 : end if
286 :
287 1139992 : select case (isign)
288 : case (+1) ! G --> R
289 389721 : call dfti_c2r_op(nx,ny,nz,ldx,ldy,ldz,ndat,fofg,fofr)
290 : case (-1) ! R --> G
291 360550 : call dfti_r2c_op(nx,ny,nz,ldx,ldy,ldz,ndat,fofr,fofg)
292 : case default
293 750271 : ABI_BUG("Wrong isign")
294 : end select
295 :
296 : case default
297 1248302 : ABI_BUG("Wrong value for cplex")
298 : end select
299 :
300 1248302 : end subroutine dfti_seqfourdp
301 : !!***
302 :
303 : !----------------------------------------------------------------------
304 :
305 : !!****f* m_dfti/dfti_seqfourwf
306 : !! NAME
307 : !! dfti_seqfourwf
308 : !!
309 : !! FUNCTION
310 : !! Carry out composite Fourier transforms between real and reciprocal (G) space.
311 : !! Wavefunctions, contained in a sphere in reciprocal space,
312 : !! can be FFT to real space. They can also be FFT from real space
313 : !! to a sphere. Also, the density maybe accumulated, and a local potential can be applied.
314 : !!
315 : !! The different options are :
316 : !! - option=0 --> reciprocal to real space and output the result.
317 : !! - option=1 --> reciprocal to real space and accumulate the density.
318 : !! - option=2 --> reciprocal to real space, apply the local potential to the wavefunction
319 : !! in real space and produce the result in reciprocal space.
320 : !! - option=3 --> real space to reciprocal space.
321 : !! NOTE that in this case, fftalg=1x1 MUST be used. This may be changed in the future.
322 : !!
323 : !! INPUTS
324 : !! cplex= if 1 , denpot is real, if 2 , denpot is complex
325 : !! (cplex=2 only allowed for option=2, and istwf_k=1)
326 : !! not relevant if option=0 or option=3, so cplex=0 can be used to minimize memory
327 : !! fofgin(2,npwin)=holds input wavefunction in G vector basis sphere.
328 : !! (intent(in) but the routine sphere can modify it for another iflag)
329 : !! gboundin(2*mgfft+8,2)=sphere boundary info for reciprocal to real space
330 : !! gboundout(2*mgfft+8,2)=sphere boundary info for real to reciprocal space
331 : !! istwf_k=option parameter that describes the storage of wfs
332 : !! kg_kin(3,npwin)=reduced planewave coordinates, input
333 : !! kg_kout(3,npwout)=reduced planewave coordinates, output
334 : !! mgfft=maximum size of 1D FFTs
335 : !! ndat=number of FFT to do in //
336 : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
337 : !! npwin=number of elements in fofgin array (for option 0, 1 and 2)
338 : !! npwout=number of elements in fofgout array (for option 2 and 3)
339 : !! ldx,ldy,ldz=ngfft(4),ngfft(5),ngfft(6), dimensions of fofr.
340 : !! option= if 0: do direct FFT
341 : !! if 1: do direct FFT, then sum the density
342 : !! if 2: do direct FFT, multiply by the potential, then do reverse FFT
343 : !! if 3: do reverse FFT only
344 : !! weight_r=weight to be used for the accumulation of the density in real space
345 : !! (needed only when option=1)
346 :
347 : !! OUTPUT
348 : !! (see side effects)
349 : !!
350 : !! SIDE EFFECTS
351 : !! Input/Output
352 : !! for option==0, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
353 : !! fofr(2,ldx,ldy,ldz) contains the output Fourier Transform of fofgin;
354 : !! no use of denpot, fofgout and npwout.
355 : !! for option==1, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
356 : !! denpot(cplex*ldx,ldy,ldz) contains the input density at input,
357 : !! and the updated density at output (accumulated);
358 : !! no use of fofgout and npwout.
359 : !! for option==2, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
360 : !! denpot(cplex*ldx,ldy,ldz) contains the input local potential;
361 : !! fofgout(2,npwout*ndat) contains the output function;
362 : !! for option==3, fofr(2,ldx,ldy,ldz*ndat) contains the input real space wavefunction;
363 : !! fofgout(2,npwout*ndat) contains its output Fourier transform;
364 : !! no use of fofgin and npwin.
365 : !!
366 : !! SOURCE
367 :
368 59006717 : subroutine dfti_seqfourwf(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k, &
369 59006717 : kg_kin,kg_kout,mgfft,ndat,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
370 :
371 : !Arguments ------------------------------------
372 : !scalars
373 : integer,intent(in) :: cplex,istwf_k,ldx,ldy,ldz,ndat,npwin,npwout,option,mgfft
374 : real(dp),intent(in) :: weight_i,weight_r
375 : !arrays
376 : integer,intent(in) :: gboundin(2*mgfft+8,2),gboundout(2*mgfft+8,2)
377 : integer,intent(in) :: kg_kin(3,npwin),kg_kout(3,npwout),ngfft(18)
378 : real(dp),intent(inout) :: denpot(cplex*ldx,ldy,ldz),fofgin(2,npwin*ndat)
379 : real(dp),intent(inout) :: fofr(2,ldx*ldy*ldz*ndat)
380 : real(dp),intent(out) :: fofgout(2,npwout*ndat)
381 :
382 : !Local variables-------------------------------
383 : !scalars
384 : integer,parameter :: ndat1=1
385 : integer :: nx,ny,nz,fftalg,fftalga,fftalgc,fftcache,dat,ptg,ptr,ptgin,ptgout,nthreads
386 : logical :: use_fftrisc
387 : character(len=500) :: msg
388 : ! *************************************************************************
389 :
390 160315703 : if (all(option /= [0, 1, 2, 3])) then
391 0 : write(msg,'(a,i0,a)')' Option:',option,' is not allowed. Only option=0, 1, 2 or 3 are allowed presently.'
392 0 : ABI_ERROR(msg)
393 : end if
394 :
395 59006717 : if (option == 1 .and. cplex /= 1) then
396 0 : ABI_ERROR(sjoin("With option number 1, cplex must be 1 but it is cplex:", itoa(cplex)))
397 : end if
398 :
399 59006717 : if (option==2 .and. (cplex/=1 .and. cplex/=2)) then
400 0 : ABI_ERROR(sjoin("With the option number 2, cplex must be 1 or 2, but it is cplex:", itoa(cplex)))
401 : end if
402 :
403 59006717 : nx=ngfft(1); ny=ngfft(2); nz=ngfft(3)
404 59006717 : fftalg=ngfft(7); fftalga=fftalg/100; fftalgc=MOD(fftalg,10)
405 59006717 : fftcache=ngfft(8)
406 :
407 59006717 : use_fftrisc = (fftalgc==2)
408 59006717 : if (istwf_k==2.and.option==3) use_fftrisc = .FALSE.
409 162542388 : if (istwf_k>2.and.ANY(option==(/0,3/))) use_fftrisc = .FALSE.
410 :
411 : nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
412 :
413 59006682 : if (use_fftrisc) then
414 : !call wrtout(std_out, " calls dfti_fftrisc")
415 59006666 : if (ndat == 1) then
416 58239625 : if (fftcore_mixprec == 0) then
417 : call dfti_fftrisc_dp(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
418 58047313 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
419 : else
420 : call dfti_fftrisc_mixprec(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
421 192312 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
422 : end if
423 : else
424 : ! All this boilerplate code is needed because the caller might pass zero-sized arrays
425 : ! for the arguments that are not referenced and we don't want to have problems at run-time.
426 : ! Moreover option 1 requires a special treatment when threads are started at this level.
427 :
428 : SELECT CASE (option)
429 : CASE (0)
430 : !
431 : ! fofgin -> fofr, no use of denpot, fofgout and npwout.
432 : if (.not.dfti_spawn_threads_here(ndat,nthreads)) then
433 1115368 : do dat=1,ndat
434 912847 : ptg = 1 + (dat-1)*npwin
435 912847 : ptr = 1 + (dat-1)*ldx*ldy*ldz
436 : call dfti_fftrisc_dp(cplex,denpot,fofgin(1,ptg),fofgout,fofr(1,ptr),gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
437 1115368 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
438 : end do
439 : else
440 : !$OMP PARALLEL DO PRIVATE(ptg,ptr)
441 : do dat=1,ndat
442 : ptg = 1 + (dat-1)*npwin
443 : ptr = 1 + (dat-1)*ldx*ldy*ldz
444 : call dfti_fftrisc_dp(cplex,denpot,fofgin(1,ptg),fofgout,fofr(1,ptr),gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
445 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
446 : end do
447 : end if
448 :
449 : CASE (1)
450 : !fofgin -> local ur and accumulate density in denpot
451 : ! TODO this is delicate part to do in parallel, as one should OMP reduce denpot.
452 10 : do dat=1,ndat
453 8 : ptg = 1 + (dat-1)*npwin
454 8 : ptr = 1 + (dat-1)*ldx*ldy*ldz
455 : call dfti_fftrisc_dp(cplex,denpot,fofgin(1,ptg),fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
456 10 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
457 : end do
458 :
459 : CASE (2)
460 : ! <G|vloc(r)|fofgin(r)> in fofgout
461 : if (.not.dfti_spawn_threads_here(ndat,nthreads)) then
462 3342418 : do dat=1,ndat
463 2777902 : ptgin = 1 + (dat-1)*npwin
464 2777902 : ptgout = 1 + (dat-1)*npwout
465 3342418 : if (fftcore_mixprec == 0) then
466 : call dfti_fftrisc_dp(cplex,denpot,fofgin(1,ptgin),fofgout(1,ptgout),fofr,gboundin,gboundout,istwf_k,&
467 2777710 : kg_kin,kg_kout,mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
468 : else
469 : call dfti_fftrisc_mixprec(cplex,denpot,fofgin(1,ptgin),fofgout(1,ptgout),fofr,gboundin,gboundout,istwf_k,&
470 192 : kg_kin,kg_kout,mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
471 : end if
472 : end do
473 : else
474 : !$OMP PARALLEL DO PRIVATE(ptgin,ptgout)
475 : do dat=1,ndat
476 : ptgin = 1 + (dat-1)*npwin
477 : ptgout = 1 + (dat-1)*npwout
478 : call dfti_fftrisc_dp(cplex,denpot,fofgin(1,ptgin),fofgout(1,ptgout),fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
479 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
480 : end do
481 : end if
482 :
483 : CASE (3)
484 : ! fofr -> fofgout
485 0 : if (.not.dfti_spawn_threads_here(ndat,nthreads)) then
486 10 : do dat=1,ndat
487 8 : ptr = 1 + (dat-1)*ldx*ldy*ldz
488 8 : ptgout = 1 + (dat-1)*npwout
489 : call dfti_fftrisc_dp(cplex,denpot,fofgin,fofgout(1,ptgout),fofr(1,ptr),gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
490 10 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
491 : end do
492 : else
493 : !$OMP PARALLEL DO PRIVATE(ptr,ptgout)
494 : do dat=1,ndat
495 : ptr = 1 + (dat-1)*ldx*ldy*ldz
496 : ptgout = 1 + (dat-1)*npwout
497 : call dfti_fftrisc_dp(cplex,denpot,fofgin,fofgout(1,ptgout),fofr(1,ptr),gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
498 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
499 : end do
500 : end if
501 :
502 : CASE DEFAULT
503 0 : write(msg,'(a,i0,a)')'Option',option,' is not allowed. Only option=0, 1, 2 or 3 are allowed presently.'
504 767041 : ABI_ERROR(msg)
505 : END SELECT
506 :
507 : end if
508 :
509 : else
510 0 : SELECT CASE (option)
511 : CASE (0)
512 : !
513 : ! FFT u(g) --> u(r)
514 0 : if (.not.dfti_spawn_threads_here(ndat,nthreads)) then
515 0 : call dfti_fftug_dp(fftalg,fftcache,npwin,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_kin,gboundin,fofgin,fofr)
516 : else
517 : !$OMP PARALLEL DO PRIVATE(ptg, ptr)
518 : do dat=1,ndat
519 : ptg = 1 + (dat-1)*npwin
520 : ptr = 1 + (dat-1)*ldx*ldy*ldz
521 : call dfti_fftug_dp(fftalg,fftcache,npwin,nx,ny,nz,ldx,ldy,ldz,ndat1,&
522 : istwf_k,mgfft,kg_kin,gboundin,fofgin(1,ptg),fofr(1,ptr))
523 : end do
524 : end if
525 :
526 : CASE (1)
527 : ! TODO this is delicate part to do in parallel, as one should OMP reduce denpot.
528 0 : call dfti_fftug_dp(fftalg,fftcache,npwin,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_kin,gboundin,fofgin,fofr)
529 0 : call cg_addtorho(nx,ny,nz,ldx,ldy,ldz,ndat,weight_r,weight_i,fofr,denpot)
530 :
531 : CASE (2)
532 :
533 51 : if (.not.dfti_spawn_threads_here(ndat,nthreads)) then
534 0 : call dfti_fftug_dp(fftalg,fftcache,npwin,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_kin,gboundin,fofgin,fofr)
535 0 : call cg_vlocpsi(nx,ny,nz,ldx,ldy,ldz,ndat,cplex,denpot,fofr)
536 :
537 : ! The data for option==2 is now in fofr.
538 0 : call dfti_fftpad_dp(fofr,nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,-1,gboundout)
539 :
540 0 : call cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat,npwout,kg_kout,fofr,fofgout)
541 : else
542 :
543 : !$OMP PARALLEL DO PRIVATE(ptg, ptr)
544 : do dat=1,ndat
545 : ptg = 1 + (dat-1)*npwin
546 : ptr = 1 + (dat-1)*ldx*ldy*ldz
547 : call dfti_fftug_dp(fftalg,fftcache,npwin,nx,ny,nz,ldx,ldy,ldz,ndat1,&
548 : istwf_k,mgfft,kg_kin,gboundin,fofgin(1,ptg),fofr(1,ptr))
549 :
550 : call cg_vlocpsi(nx,ny,nz,ldx,ldy,ldz,ndat1,cplex,denpot,fofr(1,ptr))
551 :
552 : ! The data for option==2 is now in fofr.
553 : call dfti_fftpad_dp(fofr(1,ptr),nx,ny,nz,ldx,ldy,ldz,ndat1,mgfft,-1,gboundout)
554 :
555 : ptg = 1 + (dat-1)*npwout
556 : call cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat1,npwout,kg_kout,fofr(1,ptr),fofgout(1,ptg))
557 : end do
558 : end if
559 :
560 : CASE (3)
561 : ! The data for option==3 is already in fofr.
562 0 : if (.not.dfti_spawn_threads_here(ndat,nthreads)) then
563 51 : call dfti_fftpad_dp(fofr,nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,-1,gboundout)
564 51 : call cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat,npwout,kg_kout,fofr,fofgout)
565 : else
566 : !$OMP PARALLEL DO PRIVATE(ptg, ptr)
567 : do dat=1,ndat
568 : ptg = 1 + (dat-1)*npwout
569 : ptr = 1 + (dat-1)*ldx*ldy*ldz
570 : call dfti_fftpad_dp(fofr(1,ptr),nx,ny,nz,ldx,ldy,ldz,ndat1,mgfft,-1,gboundout)
571 : call cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat1,npwout,kg_kout,fofr(1,ptr),fofgout(1,ptg))
572 : end do
573 : end if
574 :
575 : CASE DEFAULT
576 0 : write(msg,'(a,i0,a)')'Option',option,' is not allowed. Only option=0, 1, 2 or 3 are allowed presently.'
577 51 : ABI_ERROR(msg)
578 : END SELECT
579 : end if
580 :
581 59006717 : end subroutine dfti_seqfourwf
582 : !!***
583 :
584 : !----------------------------------------------------------------------
585 :
586 : !!****f* m_dfti/dfti_fftrisc_sp
587 : !! NAME
588 : !! dfti_fftrisc_sp
589 : !!
590 : !! FUNCTION
591 : !! Carry out Fourier transforms between real and reciprocal (G) space,
592 : !! for wavefunctions, contained in a sphere in reciprocal space,
593 : !! in both directions. Also accomplish some post-processing.
594 : !! See dfti_fftrisc_dp for API doc.
595 : !!
596 : !! SOURCE
597 :
598 15 : subroutine dfti_fftrisc_sp(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
599 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option, &
600 : weight_r,weight_i, abi_convention, iscale)
601 :
602 : !Arguments ------------------------------------
603 : !scalars
604 : integer,intent(in) :: cplex,istwf_k,mgfft,ldx,ldy,ldz,npwin,npwout,option
605 : real(dp),intent(in) :: weight_i,weight_r
606 : !arrays
607 : integer,intent(in) :: gboundin(2*mgfft+8,2),gboundout(2*mgfft+8,2)
608 : integer,intent(in) :: kg_kin(3,npwin),kg_kout(3,npwout),ngfft(18)
609 : real(sp),intent(in) :: fofgin(2,npwin)
610 : real(dp),intent(inout) :: denpot(cplex*ldx,ldy,ldz)
611 : real(sp),intent(inout) :: fofr(2,ldx*ldy*ldz)
612 : real(sp),intent(inout) :: fofgout(2,npwout) !vz_i
613 : logical,optional,intent(in) :: abi_convention
614 : integer,optional,intent(in) :: iscale
615 : ! *************************************************************************
616 :
617 : #ifdef HAVE_DFTI
618 :
619 : #undef FFT_PRECISION
620 : #undef MYKIND
621 : #undef MYCZERO
622 : #undef MYCMPLX
623 : #undef MYCONJG
624 :
625 : #define FFT_PRECISION DFTI_SINGLE
626 : #define MYKIND SP
627 : #define MYCZERO (0._sp,0._sp)
628 : #define MYCMPLX CMPLX
629 : #define MYCONJG CONJG
630 :
631 : #include "dfti_fftrisc.finc"
632 :
633 : #else
634 : ABI_ERROR("DFTI support not activated")
635 : ABI_UNUSED((/cplex,gboundin(1,1),gboundout(1,1),istwf_k,kg_kin(1,1),kg_kout(1,1),iscale/))
636 : ABI_UNUSED((/mgfft,ngfft(1),npwin,npwout,ldx,ldy,ldz,option/))
637 : ABI_UNUSED((/denpot(1,1,1),weight_r,weight_i/))
638 : ABI_UNUSED((/fofgin(1,1),fofgout(1,1),fofr(1,1)/))
639 : ABI_UNUSED(abi_convention)
640 : #endif
641 :
642 : end subroutine dfti_fftrisc_sp
643 : !!***
644 :
645 : !----------------------------------------------------------------------
646 :
647 : !!****f* m_dfti/dfti_fftrisc_dp
648 : !! NAME
649 : !! dfti_fftrisc_dp
650 : !!
651 : !! FUNCTION
652 : !! Carry out Fourier transforms between real and reciprocal (G) space,
653 : !! for wavefunctions, contained in a sphere in reciprocal space,
654 : !! in both directions. Also accomplish some post-processing.
655 : !!
656 : !! NOTES
657 : !! Specifically uses rather sophisticated algorithms, based on S Goedecker
658 : !! routines, specialized for superscalar RISC architecture.
659 : !! Zero padding : saves 7/12 execution time
660 : !! Bi-dimensional data locality in most of the routine : cache reuse
661 : !! For k-point (0 0 0) : takes advantage of symmetry of data.
662 : !! Note however that no blocking is used, in both 1D z-transform
663 : !! or subsequent 2D transform. This should be improved.
664 : !!
665 : !! INPUTS
666 : !! cplex= if 1 , denpot is real, if 2 , denpot is complex
667 : !! (cplex=2 only allowed for option=2 when istwf_k=1)
668 : !! one can also use cplex=0 if option=0 or option=3
669 : !! fofgin(2,npwin)=holds input wavefunction in G vector basis sphere.
670 : !! gboundin(2*mgfft+8,2)=sphere boundary info for reciprocal to real space
671 : !! gboundout(2*mgfft+8,2)=sphere boundary info for real to reciprocal space
672 : !! istwf_k=option parameter that describes the storage of wfs
673 : !! kg_kin(3,npwin)=reduced planewave coordinates, input
674 : !! kg_kout(3,npwout)=reduced planewave coordinates, output
675 : !! mgfft=maximum size of 1D FFTs
676 : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
677 : !! npwin=number of elements in fofgin array (for option 0, 1 and 2)
678 : !! npwout=number of elements in fofgout array (for option 2 and 3)
679 : !! ldx,ldy,ldz=ngfft(4),ngfft(5),ngfft(6), dimensions of fofr.
680 : !! option= if 0: do direct FFT
681 : !! if 1: do direct FFT, then sum the density
682 : !! if 2: do direct FFT, multiply by the potential, then do reverse FFT
683 : !! if 3: do reverse FFT only
684 : !! weight=weight to be used for the accumulation of the density in real space
685 : !! (needed only when option=1)
686 : !!
687 : !! OUTPUT
688 : !! (see side effects)
689 : !!
690 : !! OPTIONS
691 : !! The different options are:
692 : !! - reciprocal to real space and output the result (when option=0),
693 : !! - reciprocal to real space and accumulate the density (when option=1) or
694 : !! - reciprocal to real space, apply the local potential to the wavefunction
695 : !! in real space and produce the result in reciprocal space (when option=2)
696 : !! - real space to reciprocal space (when option=3).
697 : !! option=0 IS NOT ALLOWED when istwf_k>2
698 : !! option=3 IS NOT ALLOWED when istwf_k>=2
699 : !!
700 : !! SIDE EFFECTS
701 : !! for option==0, fofgin(2,npwin)=holds input wavefunction in G sphere;
702 : !! fofr(2,ldx,ldy,ldz) contains the Fourier Transform of fofgin;
703 : !! no use of denpot, fofgout and npwout.
704 : !! for option==1, fofgin(2,npwin)=holds input wavefunction in G sphere;
705 : !! denpot(cplex*ldx,ldy,ldz) contains the input density at input,
706 : !! and the updated density at output;
707 : !! no use of fofgout and npwout.
708 : !! for option==2, fofgin(2,npwin)=holds input wavefunction in G sphere;
709 : !! denpot(cplex*ldx,ldy,ldz) contains the input local potential;
710 : !! fofgout(2,npwout) contains the output function;
711 : !! for option==3, fofr(2,ldx,ldy,ldz) contains the real space wavefunction;
712 : !! fofgout(2,npwout) contains its Fourier transform;
713 : !! no use of fofgin and npwin.
714 : !!
715 : !! SOURCE
716 :
717 62731627 : subroutine dfti_fftrisc_dp(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
718 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option, &
719 : weight_r, weight_i, abi_convention, iscale)
720 :
721 : !Arguments ------------------------------------
722 : !scalars
723 : integer,intent(in) :: cplex,istwf_k,mgfft,ldx,ldy,ldz,npwin,npwout,option
724 : real(dp),intent(in) :: weight_i,weight_r
725 : !arrays
726 : integer,intent(in) :: gboundin(2*mgfft+8,2),gboundout(2*mgfft+8,2)
727 : integer,intent(in) :: kg_kin(3,npwin),kg_kout(3,npwout),ngfft(18)
728 : real(dp),intent(in) :: fofgin(2,npwin)
729 : real(dp),intent(inout) :: denpot(cplex*ldx,ldy,ldz)
730 : real(dp),intent(inout) :: fofr(2,ldx*ldy*ldz)
731 : real(dp),intent(inout) :: fofgout(2,npwout) !vz_i
732 : logical,optional,intent(in) :: abi_convention
733 : integer,optional,intent(in) :: iscale
734 : ! *************************************************************************
735 :
736 : #ifdef HAVE_DFTI
737 :
738 : #undef FFT_PRECISION
739 : #undef MYKIND
740 : #undef MYCZERO
741 : #undef MYCMPLX
742 : #undef MYCONJG
743 :
744 : #define FFT_PRECISION DFTI_DOUBLE
745 : #define MYKIND DP
746 : #define MYCZERO (0._dp,0._dp)
747 : #define MYCMPLX DCMPLX
748 : #define MYCONJG DCONJG
749 :
750 : #include "dfti_fftrisc.finc"
751 :
752 : #else
753 : ABI_ERROR("DFTI support not activated")
754 : ABI_UNUSED((/cplex,gboundin(1,1),gboundout(1,1),istwf_k,kg_kin(1,1),kg_kout(1,1),iscale/))
755 : ABI_UNUSED((/mgfft,ngfft(1),npwin,npwout,ldx,ldy,ldz,option/))
756 : ABI_UNUSED((/denpot(1,1,1),fofgin(1,1),fofgout(1,1),fofr(1,1),weight_r,weight_i/))
757 : ABI_UNUSED(abi_convention)
758 : #endif
759 :
760 : end subroutine dfti_fftrisc_dp
761 : !!***
762 :
763 : !----------------------------------------------------------------------
764 :
765 : !!****f* m_dfti/dfti_fftrisc_mixprec
766 : !! NAME
767 : !! dfti_fftrisc_mixprec
768 : !!
769 : !! FUNCTION
770 : !! Carry out Fourier transforms between real and reciprocal (G) space,
771 : !! for wavefunctions, contained in a sphere in reciprocal space,
772 : !! in both directions. Also accomplish some post-processing.
773 : !! This is the Mixed Precision version (dp in input, FFT done with sp data, output is dp)
774 : !! See dfti_fftrisc_dp for API doc.
775 : !!
776 : !! SOURCE
777 :
778 192504 : subroutine dfti_fftrisc_mixprec(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
779 : mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,&
780 : weight_r,weight_i, abi_convention, iscale) ! optional
781 :
782 : !Arguments ------------------------------------
783 : !scalars
784 : integer,intent(in) :: cplex,istwf_k,mgfft,ldx,ldy,ldz,npwin,npwout,option
785 : real(dp),intent(in) :: weight_i,weight_r
786 : !arrays
787 : integer,intent(in) :: gboundin(2*mgfft+8,2),gboundout(2*mgfft+8,2)
788 : integer,intent(in) :: kg_kin(3,npwin),kg_kout(3,npwout),ngfft(18)
789 : real(dp),intent(in) :: fofgin(2,npwin)
790 : real(dp),intent(inout) :: denpot(cplex*ldx,ldy,ldz)
791 : real(dp),intent(inout) :: fofr(2,ldx*ldy*ldz)
792 : real(dp),intent(inout) :: fofgout(2,npwout) !vz_i
793 : logical,optional,intent(in) :: abi_convention
794 : integer,optional,intent(in) :: iscale
795 : ! *************************************************************************
796 :
797 : #ifdef HAVE_DFTI
798 :
799 : #undef FFT_PRECISION
800 : #undef MYKIND
801 : #undef MYCZERO
802 : #undef MYCMPLX
803 : #undef MYCONJG
804 :
805 : #define FFT_PRECISION DFTI_SINGLE
806 : #define MYKIND SP
807 : #define MYCZERO (0._sp,0._sp)
808 : #define MYCMPLX CMPLX
809 : #define MYCONJG CONJG
810 :
811 : #define HAVE_DFTI_MIXED_PRECISION 1
812 :
813 : #include "dfti_fftrisc.finc"
814 :
815 : #undef HAVE_DFTI_MIXED_PRECISION
816 :
817 : #else
818 : ABI_ERROR("DFTI support not activated")
819 : ABI_UNUSED((/cplex,gboundin(1,1),gboundout(1,1),istwf_k,kg_kin(1,1),kg_kout(1,1),iscale/))
820 : ABI_UNUSED((/mgfft,ngfft(1),npwin,npwout,ldx,ldy,ldz,option/))
821 : ABI_UNUSED((/denpot(1,1,1),fofgin(1,1),fofgout(1,1),fofr(1,1),weight_r,weight_i/))
822 : ABI_UNUSED(abi_convention)
823 : #endif
824 :
825 : end subroutine dfti_fftrisc_mixprec
826 : !!***
827 :
828 : !----------------------------------------------------------------------
829 :
830 : !!****f* m_dfti/dfti_fftug_dp
831 : !! NAME
832 : !! dfti_fftug_dp
833 : !!
834 : !! FUNCTION
835 : !! Compute ndat zero-padded FFTs from G to R space.
836 : !! Mainly used for the transform of wavefunctions.
837 : !! TARGET: dp arrays with real and imaginary part
838 : !!
839 : !! INPUTS
840 : !! fftalg=FFT algorithm (see input variable)
841 : !! fftcache=size of the cache (kB)
842 : !! npw_k=number of plane waves for this k-point.
843 : !! nx,ny,nz=Number of point along the three directions.
844 : !! ldx,ldy,ldz=Leading dimensions of the array.
845 : !! ndat=Number of transforms
846 : !! istwf_k=Option describing the storage of the wavefunction.
847 : !! mgfft=Max number of FFT divisions (used to dimension gbound)
848 : !! kg_k(3,npw_k)=G-vectors in reduced coordinates
849 : !! gbound(2*mgfft+8,2)=Table for padded-FFT. See sphereboundary.
850 : !! ug(npw_k*ndat)=wavefunctions in reciprocal space.
851 : !!
852 : !! OUTPUT
853 : !! ur(ldx*ldy*ldz*ndat)=wavefunctions in real space.
854 : !!
855 : !! SOURCE
856 :
857 0 : subroutine dfti_fftug_dp(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
858 0 : istwf_k, mgfft, kg_k, gbound, ug, ur, &
859 : isign, iscale) ! optional
860 :
861 : !Arguments ------------------------------------
862 : !scalars
863 : integer,intent(in) :: fftalg,fftcache
864 : integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
865 : !arrays
866 : integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
867 : real(dp),target,intent(in) :: ug(2*npw_k*ndat)
868 : real(dp),target,intent(inout) :: ur(2*ldx*ldy*ldz*ndat)
869 : integer,optional,intent(in) :: isign, iscale
870 :
871 : #ifdef HAVE_DFTI
872 : !Local variables-------------------------------
873 : integer,parameter :: dist=2
874 : integer :: iscale__, isign__
875 : real(dp) :: fofgout(2,0)
876 0 : real(dp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
877 : ! *************************************************************************
878 :
879 0 : iscale__ = 0; if (present(iscale)) iscale__ = iscale
880 0 : isign__ = +1; if (present(isign)) isign__ = isign
881 :
882 : #undef TK_PREF
883 : #define TK_PREF(name) CONCAT(cg_,name)
884 : #undef TK_PREF_box2gsph
885 : #define TK_PREF_box2gsph cg_box2gsph
886 : #undef TK_PREF_gsph2box
887 : #define TK_PREF_gsph2box cg_gsph2box
888 :
889 : #undef FFT_PRECISION
890 : #define FFT_PRECISION FFT_DOUBLE
891 :
892 : #include "fftug.finc"
893 :
894 : #undef FFT_PRECISION
895 :
896 : #else
897 : ! Silence compiler warning
898 : ABI_ERROR("FFT_DFTI support not activated")
899 : ABI_UNUSED((/fftalg,fftcache,npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1), isign, iscale/))
900 : ABI_UNUSED((/ug(1),ur(1)/))
901 : #endif
902 :
903 0 : end subroutine dfti_fftug_dp
904 : !!***
905 :
906 : !----------------------------------------------------------------------
907 :
908 : !!****f* m_dfti/dfti_fftug_spc
909 : !! NAME
910 : !! dfti_fftug_spc
911 : !!
912 : !! FUNCTION
913 : !! Compute ndat zero-padded FFTs from G- to R-space .
914 : !! Mainly used for the transform of wavefunctions.
915 : !! TARGET: spc arrays
916 : !!
917 : !! INPUTS
918 : !! fftalg=FFT algorithm (see input variable)
919 : !! fftcache=size of the cache (kB)
920 : !! npw_k=number of plane waves for this k-point.
921 : !! nx,ny,nz=Number of point along the three directions.
922 : !! ldx,ldy,ldz=Leading dimensions of the array.
923 : !! ndat=Number of transforms
924 : !! istwf_k=Option describing the storage of the wavefunction.
925 : !! mgfft=Max number of FFT divisions (used to dimension gbound)
926 : !! kg_k(3,npw_k)=G-vectors in reduced coordinates
927 : !! gbound(2*mgfft+8,2)=Table for padded-FFT. See sphereboundary.
928 : !! ug(npw_k*ndat)=wavefunctions in reciprocal space.
929 : !!
930 : !! OUTPUT
931 : !! ur(ldx*ldy*ldz*ndat)=wavefunctions in real space.
932 : !!
933 : !! SOURCE
934 :
935 18 : subroutine dfti_fftug_spc(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
936 18 : istwf_k, mgfft, kg_k, gbound, ug, ur, &
937 : isign, iscale) ! optional
938 :
939 : !Arguments ------------------------------------
940 : !scalars
941 : integer,intent(in) :: fftalg,fftcache
942 : integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
943 : integer,optional,intent(in) :: isign, iscale
944 : !arrays
945 : integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
946 : complex(sp),target,intent(in) :: ug(npw_k*ndat)
947 : complex(sp),target,intent(inout) :: ur(ldx*ldy*ldz*ndat)
948 :
949 : #ifdef HAVE_DFTI
950 : !Local variables-------------------------------
951 : !scalars
952 : integer,parameter :: dist=1
953 : integer :: iscale__, isign__
954 : real(sp) :: fofgout(2,0)
955 18 : real(sp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
956 : ! *************************************************************************
957 :
958 18 : iscale__ = 0; if (present(iscale)) iscale__ = iscale
959 18 : isign__ = +1; if (present(isign)) isign__ = isign
960 :
961 : #undef TK_PREF
962 : #define TK_PREF(name) CONCAT(cplx_,name)
963 : #undef TK_PREF_box2gsph
964 : #define TK_PREF_box2gsph cplx_box2gsph
965 : #undef TK_PREF_gsph2box
966 : #define TK_PREF_gsph2box cplx_gsph2box
967 :
968 : #undef FFT_PRECISION
969 : #define FFT_PRECISION FFT_SINGLE
970 :
971 : #include "fftug.finc"
972 :
973 : #undef FFT_PRECISION
974 :
975 : #else
976 : ! Silence compiler warning
977 : ABI_ERROR("FFT_DFTI support not activated")
978 : ABI_UNUSED((/fftalg,fftcache,npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1), iscale, isign/))
979 : ABI_UNUSED((/ug(1),ur(1)/))
980 : #endif
981 :
982 18 : end subroutine dfti_fftug_spc
983 : !!***
984 :
985 : !----------------------------------------------------------------------
986 :
987 : !!****f* m_dfti/dfti_fftug_dpc
988 : !! NAME
989 : !! dfti_fftug_dpc
990 : !!
991 : !! FUNCTION
992 : !! Compute ndat zero-padded FFTs from G ro R.
993 : !! Mainly used for the transform of wavefunctions.
994 : !! TARGET: DP arrays
995 : !!
996 : !! INPUTS
997 : !! fftalg=FFT algorithm (see input variable)
998 : !! fftcache=size of the cache (kB)
999 : !! npw_k=number of plane waves for this k-point.
1000 : !! nx,ny,nz=Number of point along the three directions.
1001 : !! ldx,ldy,ldz=Leading dimensions of the array.
1002 : !! ndat=Number of transforms
1003 : !! istwf_k=Option describing the storage of the wavefunction.
1004 : !! mgfft=Max number of FFT divisions (used to dimension gbound)
1005 : !! kg_k(3,npw_k)=G-vectors in reduced coordinates
1006 : !! gbound(2*mgfft+8,2)=Table for padded-FFT. See sphereboundary.
1007 : !! ug(npw_k*ndat)=wavefunctions in reciprocal space
1008 : !!
1009 : !! OUTPUT
1010 : !! ur(ldx*ldy*ldz*ndat)=wavefunctions in real space.
1011 : !!
1012 : !! SOURCE
1013 :
1014 214988 : subroutine dfti_fftug_dpc(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
1015 214988 : istwf_k, mgfft, kg_k, gbound, ug, ur, &
1016 : isign, iscale) ! optional
1017 :
1018 : !Arguments ------------------------------------
1019 : !scalars
1020 : integer,intent(in) :: fftalg,fftcache
1021 : integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
1022 : !arrays
1023 : integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
1024 : complex(dp),target,intent(in) :: ug(npw_k*ndat)
1025 : complex(dp),target,intent(inout) :: ur(ldx*ldy*ldz*ndat) !vz_i
1026 : integer,optional,intent(in) :: isign, iscale
1027 :
1028 : #ifdef HAVE_DFTI
1029 : !Local variables-------------------------------
1030 : !scalars
1031 : integer,parameter :: dist=1
1032 : integer :: iscale__, isign__
1033 : !arrays
1034 : real(dp) :: fofgout(2,0)
1035 214988 : real(dp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
1036 : ! *************************************************************************
1037 :
1038 214988 : iscale__ = 0; if (present(iscale)) iscale__ = iscale
1039 214988 : isign__ = +1; if (present(isign)) isign__ = isign
1040 :
1041 : #undef TK_PREF
1042 : #define TK_PREF(name) CONCAT(cplx_,name)
1043 : #undef TK_PREF_box2gsph
1044 : #define TK_PREF_box2gsph cplx_box2gsph
1045 : #undef TK_PREF_gsph2box
1046 : #define TK_PREF_gsph2box cplx_gsph2box
1047 :
1048 : #undef FFT_PRECISION
1049 : #define FFT_PRECISION FFT_DOUBLE
1050 :
1051 : #include "fftug.finc"
1052 :
1053 : #undef FFT_PRECISION
1054 :
1055 : #else
1056 : ! Silence compiler warning
1057 : ABI_ERROR("FFT_DFTI support not activated")
1058 : ABI_UNUSED((/fftalg,fftcache,npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1),isign,iscale/))
1059 : ABI_UNUSED((/ug(1),ur(1)/))
1060 : #endif
1061 :
1062 214988 : end subroutine dfti_fftug_dpc
1063 : !!***
1064 :
1065 : !----------------------------------------------------------------------
1066 :
1067 : !!****f* m_dfti/dfti_fftur_dp
1068 : !! NAME
1069 : !! dfti_fftur_dp
1070 : !!
1071 : !! FUNCTION
1072 : !! Compute ndat zero-padded FFTs from R- to G-space .
1073 : !! Mainly used for the transform of wavefunctions.
1074 : !! TARGET: dp arrays with real and imaginary part.
1075 : !!
1076 : !! INPUTS
1077 : !! fftalg=FFT algorithm (see input variable)
1078 : !! fftcache=size of the cache (kB)
1079 : !! npw_k=number of plane waves for this k-point.
1080 : !! nx,ny,nz=Number of point along the three directions.
1081 : !! ldx,ldy,ldz=Leading dimensions of the array.
1082 : !! ndat=Number of transforms
1083 : !! istwf_k=Option describing the storage of the wavefunction.
1084 : !! mgfft=Max number of FFT divisions (used to dimension gbound)
1085 : !! kg_k(3,npw_k)=G-vectors in reduced coordinates
1086 : !! gbound(2*mgfft+8,2)=Table for padded-FFT. See sphereboundary.
1087 : !!
1088 : !! SIDE EFFECT
1089 : !! ur(2,ldx*ldy*ldz*ndat)= In input: wavefunctions in real space.
1090 : !! Destroyed in output. Do not use ur anymore!
1091 : !! OUTPUT
1092 : !! ug(2,npw_k*ndat)=wavefunctions in reciprocal space.
1093 : !!
1094 : !! SOURCE
1095 :
1096 0 : subroutine dfti_fftur_dp(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
1097 0 : istwf_k, mgfft, kg_k, gbound, ur, ug, &
1098 : isign, iscale) ! optional
1099 :
1100 : !Arguments ------------------------------------
1101 : !scalars
1102 : integer,intent(in) :: fftalg,fftcache
1103 : integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
1104 : integer,optional,intent(in) :: isign, iscale
1105 : !arrays
1106 : integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
1107 : real(dp),target,intent(inout) :: ur(2*ldx*ldy*ldz*ndat)
1108 : real(dp),target,intent(inout) :: ug(2*npw_k*ndat) !vz_i
1109 :
1110 : #ifdef HAVE_DFTI
1111 : !Local variables-------------------------------
1112 : !scalars
1113 : integer,parameter :: dist=2
1114 : integer :: iscale__, isign__
1115 : !arrays
1116 : real(dp) :: dum_ugin(2,0)
1117 0 : real(dp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
1118 : ! *************************************************************************
1119 :
1120 0 : iscale__ = 1; if (present(iscale)) iscale__ = iscale
1121 0 : isign__ = -1; if (present(isign)) isign__ = isign
1122 :
1123 : #undef TK_PREF
1124 : #define TK_PREF(name) CONCAT(cg_,name)
1125 : #undef TK_PREF_box2gsph
1126 : #define TK_PREF_box2gsph cg_box2gsph
1127 : #undef TK_PREF_gsph2box
1128 : #define TK_PREF_gsph2box cg_gsph2box
1129 :
1130 : #undef FFT_PRECISION
1131 : #define FFT_PRECISION FFT_DOUBLE
1132 :
1133 : #include "fftur.finc"
1134 :
1135 : #undef FFT_PRECISION
1136 :
1137 : #else
1138 : ! Silence compiler warning
1139 : ABI_ERROR("FFT_DFTI support not activated")
1140 : ABI_UNUSED((/fftalg,fftcache/))
1141 : ABI_UNUSED((/npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1),iscale,isign/))
1142 : ABI_UNUSED((/ug(1),ur(1)/))
1143 : #endif
1144 :
1145 0 : end subroutine dfti_fftur_dp
1146 : !!***
1147 :
1148 : !----------------------------------------------------------------------
1149 :
1150 : !!****f* m_dfti/dfti_fftur_spc
1151 : !! NAME
1152 : !! dfti_fftur_spc
1153 : !!
1154 : !! FUNCTION
1155 : !! Compute ndat zero-padded FFTs from R- to G-space .
1156 : !! Mainly used for the transform of wavefunctions.
1157 : !! TARGET: spc arrays
1158 : !!
1159 : !! INPUTS
1160 : !! fftalg=FFT algorithm (see input variable)
1161 : !! fftcache=size of the cache (kB)
1162 : !! npw_k=number of plane waves for this k-point.
1163 : !! nx,ny,nz=Number of point along the three directions.
1164 : !! ldx,ldy,ldz=Leading dimensions of the array.
1165 : !! ndat=Number of transforms
1166 : !! istwf_k=Option describing the storage of the wavefunction.
1167 : !! mgfft=Max number of FFT divisions (used to dimension gbound)
1168 : !! kg_k(3,npw_k)=G-vectors in reduced coordinates
1169 : !! gbound(2*mgfft+8,2)=Table for padded-FFT. See sphereboundary.
1170 : !!
1171 : !! SIDE EFFECT
1172 : !! ur(ldx*ldy*ldz*ndat)= In input: wavefunctions in real space.
1173 : !! Destroyed in output. Do not use ur anymore!
1174 : !!
1175 : !! OUTPUT
1176 : !! ug(npw_k*ndat)=wavefunctions in reciprocal space.
1177 : !!
1178 : !! SOURCE
1179 :
1180 18 : subroutine dfti_fftur_spc(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
1181 18 : istwf_k, mgfft, kg_k, gbound, ur, ug, &
1182 : isign, iscale) ! optional
1183 :
1184 : !Arguments ------------------------------------
1185 : !scalars
1186 : integer,intent(in) :: fftalg,fftcache
1187 : integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
1188 : !arrays
1189 : integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
1190 : complex(sp),target,intent(inout) :: ur(ldx*ldy*ldz*ndat)
1191 : complex(sp),target,intent(inout) :: ug(npw_k*ndat) !vz_i
1192 : integer,optional,intent(in) :: isign, iscale
1193 :
1194 : #ifdef HAVE_DFTI
1195 : !Local variables-------------------------------
1196 : !scalars
1197 : integer,parameter :: dist=1
1198 : integer :: iscale__, isign__
1199 : !arrays
1200 : real(sp) :: dum_ugin(2,0)
1201 18 : real(sp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
1202 : ! *************************************************************************
1203 :
1204 18 : iscale__ = 1; if (present(iscale)) iscale__ = iscale
1205 18 : isign__ = -1; if (present(isign)) isign__ = isign
1206 :
1207 : #undef TK_PREF
1208 : #define TK_PREF(name) CONCAT(cplx_,name)
1209 : #undef TK_PREF_box2gsph
1210 : #define TK_PREF_box2gsph cplx_box2gsph
1211 : #undef TK_PREF_gsph2box
1212 : #define TK_PREF_gsph2box cplx_gsph2box
1213 :
1214 : #undef FFT_PRECISION
1215 : #define FFT_PRECISION FFT_SINGLE
1216 :
1217 : #include "fftur.finc"
1218 :
1219 : #undef FFT_PRECISION
1220 :
1221 : #else
1222 : ! Silence compiler warning
1223 : ABI_ERROR("FFT_DFTI support not activated")
1224 : ABI_UNUSED((/fftalg,fftcache/))
1225 : ABI_UNUSED((/npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1),isign,iscale/))
1226 : ABI_UNUSED((/ug(1),ur(1)/))
1227 : #endif
1228 :
1229 18 : end subroutine dfti_fftur_spc
1230 : !!***
1231 :
1232 : !----------------------------------------------------------------------
1233 :
1234 : !!****f* m_dfti/dfti_fftur_dpc
1235 : !! NAME
1236 : !! dfti_fftur_dpc
1237 : !!
1238 : !! FUNCTION
1239 : !! Compute ndat zero-padded FFTs from R ro G.
1240 : !! Mainly used for the transform of wavefunctions.
1241 : !! TARGET: DP arrays
1242 : !!
1243 : !! INPUTS
1244 : !! fftalg=FFT algorithm (see input variable)
1245 : !! fftcache=size of the cache (kB)
1246 : !! npw_k=number of plane waves for this k-point.
1247 : !! nx,ny,nz=Number of point along the three directions.
1248 : !! ldx,ldy,ldz=Leading dimensions of the array.
1249 : !! ndat=Number of transforms
1250 : !! istwf_k=Option describing the storage of the wavefunction.
1251 : !! mgfft=Max number of FFT divisions (used to dimension gbound)
1252 : !! kg_k(3,npw_k)=G-vectors in reduced coordinates
1253 : !! gbound(2*mgfft+8,2)=Table for padded-FFT. See sphereboundary.
1254 : !!
1255 : !! SIDE EFFECT
1256 : !! ur(ldx*ldy*ldz*ndat)= In input: wavefunctions in real space.
1257 : !! Destroyed in output. Do not use ur anymore!
1258 : !! OUTPUT
1259 : !! ug(npw_k*ndat)=wavefunctions in reciprocal space
1260 : !!
1261 : !! SOURCE
1262 :
1263 779986 : subroutine dfti_fftur_dpc(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
1264 779986 : istwf_k, mgfft, kg_k, gbound, ur, ug, &
1265 : isign, iscale) ! optional
1266 :
1267 : !Arguments ------------------------------------
1268 : !scalars
1269 : integer,intent(in) :: fftalg,fftcache
1270 : integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
1271 : integer,optional,intent(in) :: isign, iscale
1272 : !arrays
1273 : integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
1274 : complex(dp),target,intent(inout) :: ur(ldx*ldy*ldz*ndat)
1275 : complex(dp),target,intent(inout) :: ug(npw_k*ndat) !vz_i
1276 :
1277 : #ifdef HAVE_DFTI
1278 : !Local variables-------------------------------
1279 : !scalars
1280 : integer,parameter :: dist=1
1281 : integer :: iscale__, isign__
1282 : !arrays
1283 : real(dp) :: dum_ugin(2,0)
1284 779986 : real(dp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
1285 : ! *************************************************************************
1286 :
1287 779986 : iscale__ = 1; if (present(iscale)) iscale__ = iscale
1288 779986 : isign__ = -1; if (present(isign)) isign__ = isign
1289 :
1290 : #undef TK_PREF
1291 : #define TK_PREF(name) CONCAT(cplx_,name)
1292 : #undef TK_PREF_box2gsph
1293 : #define TK_PREF_box2gsph cplx_box2gsph
1294 : #undef TK_PREF_gsph2box
1295 : #define TK_PREF_gsph2box cplx_gsph2box
1296 :
1297 : #undef FFT_PRECISION
1298 : #define FFT_PRECISION FFT_DOUBLE
1299 :
1300 : #include "fftur.finc"
1301 :
1302 : #undef FFT_PRECISION
1303 :
1304 : #else
1305 : ! Silence compiler warning
1306 : ABI_ERROR("FFT_DFTI support not activated")
1307 : ABI_UNUSED((/fftalg,fftcache/))
1308 : ABI_UNUSED((/npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1),iscale,isign/))
1309 : ABI_UNUSED((/ug(1),ur(1)/))
1310 : #endif
1311 :
1312 779986 : end subroutine dfti_fftur_dpc
1313 : !!***
1314 :
1315 : !----------------------------------------------------------------------
1316 :
1317 : !!****f* m_dfti/dfti_c2c_ip_spc
1318 : !! NAME
1319 : !! dfti_c2c_ip_spc
1320 : !!
1321 : !! FUNCTION
1322 : !! Driver routine for in-place 3D complex-complex FFT. TARGET: SPC arrays
1323 : !!
1324 : !! INPUTS
1325 : !! nx,ny,nz=Number of points along the three directions.
1326 : !! ldx,ldy,ldz=Physical dimensions of the array.
1327 : !! ndat=Number of FFTs to be done.
1328 : !! isign= +1 : ff(G) => ff(R); -1 : ff(R) => ff(G)
1329 : !!
1330 : !! SIDE EFFECTS
1331 : !! ff(ldx*ldy*ldz*ndat)=
1332 : !! In input: the complex array to be transformed.
1333 : !! In output: the Fourier transform in the space specified by isign.
1334 : !!
1335 : !! SOURCE
1336 :
1337 33608 : subroutine dfti_c2c_ip_spc(nx, ny, nz, ldx, ldy, ldz, ndat, iscale, isign, ff)
1338 :
1339 : !Arguments ------------------------------------
1340 : !scalars
1341 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,iscale,isign
1342 : !arrays
1343 : complex(sp),intent(inout) :: ff(ldx*ldy*ldz*ndat)
1344 : ! *************************************************************************
1345 :
1346 : ! Include Fortran template
1347 : #undef DEV_DFTI_PRECISION
1348 : #define DEV_DFTI_PRECISION DFTI_SINGLE
1349 :
1350 : #include "dfti_c2c_ip.finc"
1351 :
1352 33608 : end subroutine dfti_c2c_ip_spc
1353 : !!***
1354 :
1355 : !----------------------------------------------------------------------
1356 :
1357 : !!****f* m_dfti/dfti_c2c_ip_dpc
1358 : !! NAME
1359 : !! dfti_c2c_ip_dpc
1360 : !!
1361 : !! FUNCTION
1362 : !! Driver routine for in-place 3D complex-complex FFT. TARGET: DP arrays
1363 : !!
1364 : !! INPUTS
1365 : !! nx,ny,nz=Number of points along the three directions.
1366 : !! ldx,ldy,ldz=Physical dimensions of the array.
1367 : !! ndat=Number of FFTs to be done.
1368 : !! iscale=0 if G --> R FFT should not be scaled.
1369 : !! isign= +1 : ff(G) => ff(R); -1 : ff(R) => ff(G)
1370 : !!
1371 : !! SIDE EFFECTS
1372 : !! ff(ldx*ldy*ldz*ndat)=
1373 : !! In input: the complex array to be transformed.
1374 : !! In output: the Fourier transformed in the space specified by isign.
1375 : !!
1376 : !! SOURCE
1377 :
1378 12121 : subroutine dfti_c2c_ip_dpc(nx, ny, nz, ldx, ldy, ldz, ndat, iscale, isign, ff)
1379 :
1380 : !Arguments ------------------------------------
1381 : !scalars
1382 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,iscale,isign
1383 : !arrays
1384 : complex(dp),intent(inout) :: ff(ldx*ldy*ldz*ndat)
1385 : ! *************************************************************************
1386 :
1387 : ! Include Fortran template
1388 : #undef DEV_DFTI_PRECISION
1389 : #define DEV_DFTI_PRECISION DFTI_DOUBLE
1390 :
1391 : #include "dfti_c2c_ip.finc"
1392 :
1393 12121 : end subroutine dfti_c2c_ip_dpc
1394 : !!***
1395 :
1396 : !----------------------------------------------------------------------
1397 :
1398 : !!****f* m_dfti/dfti_c2c_op_spc
1399 : !! NAME
1400 : !! dfti_c2c_op_spc
1401 : !!
1402 : !! FUNCTION
1403 : !! Driver routine for out-of-place 3D complex-complex FFT of lengths nx, ny, nz.
1404 : !! TARGET: spc arrays
1405 : !!
1406 : !! INPUTS
1407 : !! nx,ny,nz=Number of points along the three directions.
1408 : !! ldx,ldy,ldz=Physical dimensions of the array.
1409 : !! ndat=Number of FFTs to be done.
1410 : !! iscale=0 if G --> R FFT should not be scaled.
1411 : !! isign= +1 : ff(G) => gg(R); -1 : ff(R) => gg(G)
1412 : !! ff(ldx*ldy*ldz*ndat)=The array to be transformed.
1413 : !!
1414 : !! OUTPUT
1415 : !! gg(ldx*ldy*ldz*ndat)=The FFT of ff.
1416 : !!
1417 : !! SOURCE
1418 :
1419 24 : subroutine dfti_c2c_op_spc(nx, ny, nz, ldx, ldy, ldz, ndat, iscale, isign, ff, gg)
1420 :
1421 : !Arguments ------------------------------------
1422 : !scalars
1423 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,isign,ndat, iscale
1424 : !arrays
1425 : complex(sp),intent(in) :: ff(ldx*ldy*ldz*ndat)
1426 : complex(sp),intent(out) :: gg(ldx*ldy*ldz*ndat)
1427 : ! *************************************************************************
1428 :
1429 : ! Include Fortran template
1430 : #undef DEV_DFTI_PRECISION
1431 : #define DEV_DFTI_PRECISION DFTI_SINGLE
1432 :
1433 : #include "dfti_c2c_op.finc"
1434 :
1435 24 : end subroutine dfti_c2c_op_spc
1436 : !!***
1437 :
1438 : !----------------------------------------------------------------------
1439 :
1440 : !!****f* m_dfti/dfti_c2c_op_dpc
1441 : !! NAME
1442 : !! dfti_c2c_op_dpc
1443 : !!
1444 : !! FUNCTION
1445 : !! Driver routine for out-of-place 3D complex-complex FFT of lengths nx, ny, nz.
1446 : !! TARGET: DP arrays
1447 : !!
1448 : !! INPUTS
1449 : !! nx,ny,nz=Number of points along the three directions.
1450 : !! ldx,ldy,ldz=Physical dimensions of the array.
1451 : !! ndat=Number of FFTs to be done.
1452 : !! iscale=0 if G --> R FFT should not be scaled.
1453 : !! isign= +1 : ff(G) => gg(R); -1 : ff(R) => gg(G)
1454 : !! ff(ldx*ldy*ldz*ndat)=The array to be transformed.
1455 : !!
1456 : !! OUTPUT
1457 : !! gg(ldx*ldy*ldz*ndat)=The FFT of ff.
1458 : !!
1459 : !! SOURCE
1460 :
1461 467313 : subroutine dfti_c2c_op_dpc(nx, ny, nz, ldx, ldy, ldz, ndat, iscale, isign, ff, gg)
1462 :
1463 : !Arguments ------------------------------------
1464 : !scalars
1465 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,isign,ndat,iscale
1466 : !arrays
1467 : complex(dp),intent(in) :: ff(ldx*ldy*ldz*ndat)
1468 : complex(dp),intent(out) :: gg(ldx*ldy*ldz*ndat)
1469 : ! *************************************************************************
1470 :
1471 : ! Include Fortran template
1472 : #undef DEV_DFTI_PRECISION
1473 : #define DEV_DFTI_PRECISION DFTI_DOUBLE
1474 :
1475 : #include "dfti_c2c_op.finc"
1476 :
1477 467313 : end subroutine dfti_c2c_op_dpc
1478 : !!***
1479 :
1480 : !----------------------------------------------------------------------
1481 :
1482 : !!****f* m_dfti/dfti_many_dft_op
1483 : !! NAME
1484 : !! dfti_many_dft_op
1485 : !!
1486 : !! FUNCTION
1487 : !! Driver routine for many out-of-place 3D complex-to-complex FFTs of lengths nx, ny, nz.
1488 : !!
1489 : !! INPUTS
1490 : !! nx,ny,nz=Number of points along the three directions.
1491 : !! ldx,ldy,ldz=Physical dimension of the fin and fout arrays (to avoid cache conflicts).
1492 : !! ndat=Number of FFTs to be done.
1493 : !! fin(2*ldx*ldy*ldz*ndat)=The complex array to be transformed.
1494 : !! isign=sign of Fourier transform exponent: current convention uses
1495 : !! +1 for transforming from G to r,
1496 : !! -1 for transforming from r to G.
1497 : !!
1498 : !! OUTPUT
1499 : !! fout(2,ldx*ldy*ldz*ndat)=The Fourier transform of fin.
1500 : !!
1501 : !! SOURCE
1502 :
1503 464447 : subroutine dfti_many_dft_op(nx,ny,nz,ldx,ldy,ldz,ndat,isign,fin,fout)
1504 :
1505 : !Arguments ------------------------------------
1506 : !scalars
1507 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,isign
1508 : !arrays
1509 : real(dp),target,intent(in) :: fin(2*ldx*ldy*ldz*ndat)
1510 : real(dp),target,intent(out) :: fout(2*ldx*ldy*ldz*ndat)
1511 :
1512 : #ifdef HAVE_DFTI
1513 : !Local variables-------------------------------
1514 : !scalars
1515 : integer,parameter :: iscale1 = 1
1516 : type(C_ptr) :: fin_cptr, fout_cptr
1517 :
1518 : !arrays
1519 464447 : complex(dp),contiguous, pointer :: fin_fptr(:),fout_fptr(:)
1520 : ! *************************************************************************
1521 :
1522 : ! Associate complex pointers with real inputs via the C pointers
1523 464447 : fin_cptr = C_loc(fin)
1524 464447 : call C_F_pointer(fin_cptr,fin_fptr, shape=[ldx*ldy*ldz*ndat])
1525 :
1526 464447 : fout_cptr = C_loc(fout)
1527 464447 : call C_F_pointer(fout_cptr,fout_fptr, shape=[ldx*ldy*ldz*ndat])
1528 :
1529 : ! Call complex version --> a lot of boilerplate code avoided
1530 464447 : call dfti_c2c_op(nx, ny, nz, ldx, ldy, ldz, ndat, iscale1, isign, fin_fptr, fout_fptr)
1531 :
1532 : #else
1533 : ABI_ERROR("FFT_DFTI support not activated")
1534 : ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,ndat,isign/))
1535 : ABI_UNUSED(fin(1))
1536 : ABI_UNUSED(fout(1))
1537 : #endif
1538 :
1539 464447 : end subroutine dfti_many_dft_op
1540 : !!***
1541 :
1542 : !----------------------------------------------------------------------
1543 :
1544 : !!****f* m_dfti/dfti_many_dft_ip
1545 : !! NAME
1546 : !! dfti_many_dft_ip
1547 : !!
1548 : !! FUNCTION
1549 : !! Driver routine for many in-place 3D complex-to-complex FFTs of lengths nx, ny, nz.
1550 : !!
1551 : !! INPUTS
1552 : !! nx,ny,nz=Number of points along the three directions.
1553 : !! ldx,ldy,ldz=Physical dimension of the finout array (to avoid cache conflicts).
1554 : !! ndat=Number of FFTs to be done.
1555 : !! isign=sign of Fourier transform exponent: current convention uses
1556 : !! +1 for transforming from G to r,
1557 : !! -1 for transforming from r to G.
1558 : !!
1559 : !! OUTPUT
1560 : !! finout(2,ldx*ldy*ldz*ndat)=
1561 : !! In input: The complex array to be transformed.
1562 : !! In output: The FFT results.
1563 : !!
1564 : !! SOURCE
1565 :
1566 0 : subroutine dfti_many_dft_ip(nx,ny,nz,ldx,ldy,ldz,ndat,isign,finout)
1567 :
1568 : !Arguments ------------------------------------
1569 : !scalars
1570 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,isign
1571 : !arrays
1572 : real(dp),target,intent(inout) :: finout(2*ldx*ldy*ldz*ndat)
1573 :
1574 : #ifdef HAVE_DFTI
1575 : !Local variables-------------------------------
1576 : !scalars
1577 : integer,parameter :: iscale1 = 1
1578 : type(C_ptr) :: finout_cptr
1579 : !arrays
1580 : complex(dp),contiguous, pointer :: finout_fptr(:)
1581 : ! *************************************************************************
1582 :
1583 : ! Associate complex finout_fptr with real ffinout via the C pointer
1584 0 : finout_cptr = C_loc(finout)
1585 0 : call C_F_pointer(finout_cptr,finout_fptr, shape=(/ldx*ldy*ldz*ndat/))
1586 :
1587 : ! Call complex version --> a lot of boilerplate code avoided
1588 0 : call dfti_c2c_ip(nx, ny, nz, ldx, ldy, ldz, ndat, iscale1, isign, finout_fptr)
1589 :
1590 : #else
1591 : ABI_ERROR("FFT_DFTI support not activated")
1592 : ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,ndat,isign/))
1593 : ABI_UNUSED(finout(1))
1594 : #endif
1595 :
1596 0 : end subroutine dfti_many_dft_ip
1597 : !!***
1598 :
1599 : !----------------------------------------------------------------------
1600 :
1601 : !!****f* m_dfti/dfti_fftpad_dp
1602 : !! NAME
1603 : !! dfti_fftpad_dp
1604 : !!
1605 : !! FUNCTION
1606 : !! This routine transforms wavefunctions using 3D zero-padded FFTs with DFTI.
1607 : !! The 3D ffts are computed only on lines and planes which have non zero elements (see zpad_init)
1608 : !! FFT transform is in-place.
1609 : !!
1610 : !! INPUTS
1611 : !! nx,ny,nz=Logical dimensions of the FFT mesh.
1612 : !! ldx,ldy,ldz=Physical dimension of the f array (to avoid cache conflicts).
1613 : !! ndat=Number of FFTs
1614 : !! mgfft=MAX(nx,ny,nz), only used to dimension gbound
1615 : !! isign=The sign of the transform.
1616 : !! gbound(2*mgfft+8,2)= The boundaries of the basis sphere of G vectors at a given k-point.
1617 : !! See sphereboundary for more info.
1618 : !!
1619 : !! SIDE EFFECTS
1620 : !! ff(2*ldx*ldy*ldz*ndat)=
1621 : !! input: The array with the data to be transformed.
1622 : !! output: The results of the FFT.
1623 : !!
1624 : !! SOURCE
1625 :
1626 51 : subroutine dfti_fftpad_dp(ff, nx, ny, nz, ldx, ldy, ldz, ndat, mgfft, isign, gbound, iscale)
1627 :
1628 : !Arguments ------------------------------------
1629 : !scalars
1630 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign
1631 : !arrays
1632 : integer,intent(in) :: gbound(2*mgfft+8,2)
1633 : real(dp),target,intent(inout) :: ff(2*ldx*ldy*ldz*ndat)
1634 : integer,optional,intent(in) :: iscale
1635 :
1636 : !Local variables-------------------------------
1637 : #ifdef HAVE_DFTI
1638 : !scalars
1639 : type(C_ptr) :: cptr
1640 : integer :: iscale__
1641 : !arrays
1642 : complex(dp),contiguous, pointer :: fptr(:)
1643 : ! *************************************************************************
1644 :
1645 51 : iscale__ = merge(1, 0, isign == -1); if (present(iscale)) iscale__ = iscale
1646 :
1647 : ! Associate complex fptr with real ff via the C pointer
1648 51 : cptr = C_loc(ff)
1649 51 : call C_F_pointer(cptr, fptr, SHAPE=[ldx*ldy*ldz*ndat])
1650 :
1651 : ! Call complex version --> a lot of boilerplate code avoided
1652 51 : call dfti_fftpad_dpc(fptr, nx, ny, nz, ldx, ldy, ldz, ndat, mgfft, isign, gbound)
1653 :
1654 : #else
1655 : ABI_ERROR("FFT_DFTI support not activated")
1656 : ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign,iscale/))
1657 : ABI_UNUSED(gbound(1,1))
1658 : ABI_UNUSED(ff(1))
1659 : #endif
1660 :
1661 51 : end subroutine dfti_fftpad_dp
1662 : !!***
1663 :
1664 : !----------------------------------------------------------------------
1665 :
1666 : !!****f* m_dfti/dfti_fftpad_dpc
1667 : !! NAME
1668 : !! dfti_fftpad_dpc
1669 : !!
1670 : !! FUNCTION
1671 : !! This routine transforms wavefunctions using 3D zero-padded FFTs with DFTI.
1672 : !! The 3D ffts are computed only on lines and planes which have non zero elements (see zpad_init)
1673 : !! FFT transform is in-place. Target: complex double-precision arrays.
1674 : !!
1675 : !! INPUTS
1676 : !! nx,ny,nz=Logical dimensions of the FFT mesh.
1677 : !! ldx,ldy,ldz=Physical dimension of the f array (to avoid cache conflicts).
1678 : !! ndat=Number of FFTs.
1679 : !! mgfft=MAX(nx,ny,nz), only used to dimension gbound
1680 : !! isign=The sign of the transform.
1681 : !! gbound(2*mgfft+8,2)= The boundaries of the basis sphere of G vectors at a given k-point.
1682 : !! See sphereboundary for more info.
1683 : !!
1684 : !! SIDE EFFECTS
1685 : !! ff(ldx*ldy*ldz*ndat)=
1686 : !! input: The array with the data to be transformed.
1687 : !! output: The results of the FFT.
1688 : !!
1689 : !! SOURCE
1690 :
1691 5735994 : subroutine dfti_fftpad_dpc(ff, nx, ny, nz, ldx, ldy, ldz, ndat, mgfft, isign, gbound, iscale)
1692 :
1693 : !Arguments ------------------------------------
1694 : !scalars
1695 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign
1696 : integer,optional,intent(in) :: iscale
1697 : !arrays
1698 : integer,intent(in) :: gbound(2*mgfft+8,2)
1699 : complex(dp),intent(inout) :: ff(ldx*ldy*ldz*ndat)
1700 :
1701 : !Local variables-------------------------------
1702 : #ifdef HAVE_DFTI
1703 : ! *************************************************************************
1704 :
1705 : ! Include Fortran template
1706 : #undef DEV_DFTI_PRECISION
1707 : #define DEV_DFTI_PRECISION DFTI_DOUBLE
1708 :
1709 : #include "dfti_fftpad.finc"
1710 :
1711 : #else
1712 : ABI_ERROR("FFT_DFTI support not activated")
1713 : ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign,iscale/))
1714 : ABI_UNUSED(gbound(1,1))
1715 : ABI_UNUSED(ff(1))
1716 : #endif
1717 :
1718 5735994 : end subroutine dfti_fftpad_dpc
1719 : !!***
1720 :
1721 : !----------------------------------------------------------------------
1722 :
1723 : !!****f* m_dfti/dfti_fftpad_spc
1724 : !! NAME
1725 : !! dfti_fftpad_spc
1726 : !!
1727 : !! FUNCTION
1728 : !! This routine transforms wavefunctions using 3D zero-padded FFTs with DFTI.
1729 : !! The 3D ffts are computed only on lines and planes which have non zero elements (see zpad_init)
1730 : !! FFT transform is in-place. Target: complex SPC arrays.
1731 : !!
1732 : !! INPUTS
1733 : !! nx,ny,nz=Logical dimensions of the FFT mesh.
1734 : !! ldx,ldy,ldz=Physical dimension of the f array (to avoid cache conflicts).
1735 : !! ndat=Number of FFTs.
1736 : !! mgfft=MAX(nx,ny,nz), only used to dimension gbound
1737 : !! isign=The sign of the transform.
1738 : !! gbound(2*mgfft+8,2)= The boundaries of the basis sphere of G vectors at a given k-point.
1739 : !! See sphereboundary for more info.
1740 : !!
1741 : !! SIDE EFFECTS
1742 : !! ff(ldx*ldy*ldz*ndat)=
1743 : !! input: The array with the data to be transformed.
1744 : !! output: The results of the FFT.
1745 : !!
1746 : !! SOURCE
1747 :
1748 30 : subroutine dfti_fftpad_spc(ff, nx, ny, nz, ldx, ldy, ldz, ndat, mgfft, isign, gbound, iscale)
1749 :
1750 : !Arguments ------------------------------------
1751 : !scalars
1752 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign
1753 : integer,optional,intent(in) :: iscale
1754 : !arrays
1755 : integer,intent(in) :: gbound(2*mgfft+8,2)
1756 : complex(sp),intent(inout) :: ff(ldx*ldy*ldz*ndat)
1757 :
1758 : #ifdef HAVE_DFTI
1759 :
1760 : ! Include Fortran template
1761 : #undef DEV_DFTI_PRECISION
1762 : #define DEV_DFTI_PRECISION DFTI_SINGLE
1763 :
1764 : #include "dfti_fftpad.finc"
1765 :
1766 : #else
1767 : ABI_ERROR("FFT_DFTI support not activated")
1768 : ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign,iscale/))
1769 : ABI_UNUSED(gbound(1,1))
1770 : ABI_UNUSED(ff(1))
1771 : #endif
1772 :
1773 30 : end subroutine dfti_fftpad_spc
1774 : !!***
1775 :
1776 : !----------------------------------------------------------------------
1777 :
1778 : !!****f* m_dfti/dfti_r2c_op_dpc
1779 : !! NAME
1780 : !! dfti_r2c_op_dpc
1781 : !!
1782 : !! FUNCTION
1783 : !! Driver routine for out-of-place 3D real-to-complex FFT of lengths nx, ny, nz.
1784 : !!
1785 : !! INPUTS
1786 : !! nx,ny,nz=Number of points along the three directions.
1787 : !! ldx,ldy,ldz=Physical dimensions of the f array (to avoid cache conflicts).
1788 : !! ff(ldx*ldy*ldz*ndat)=The real array to be transformed.
1789 : !! ndat=Number of FFTs to be done.
1790 : !!
1791 : !! OUTPUT
1792 : !! gg(ldx*ldy*ldz*ndat)=The forward FFT of ff (complex valued)
1793 : !!
1794 : !! SOURCE
1795 :
1796 360550 : subroutine dfti_r2c_op_dpc(nx, ny, nz, ldx, ldy, ldz, ndat, ff, gg)
1797 :
1798 : !Arguments ------------------------------------
1799 : !scalars
1800 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat
1801 : !arrays
1802 : real(dp),intent(in) :: ff(ldx*ldy*ldz*ndat)
1803 : complex(dp),intent(out) :: gg(ldx*ldy*ldz*ndat)
1804 :
1805 : #ifdef HAVE_DFTI
1806 : !Local variables-------------------------------
1807 : !scalars
1808 : integer :: status,nhp,padx,i1,i2,i3,igp,igf,imgf,ii,arr3(3)
1809 : integer :: i1inv,i2inv,i3inv,idat,padatf,arr(4)
1810 : type(DFTI_DESCRIPTOR),pointer :: Desc
1811 : type(C_PTR) :: cptr
1812 : !arrays
1813 360550 : integer,allocatable :: i1inver(:),i2inver(:),i3inver(:)
1814 : complex(dp),contiguous, pointer :: gg_hp(:)
1815 : ! *************************************************************************
1816 :
1817 360550 : padx = (nx/2+1)
1818 360550 : nhp = (nx/2+1)*ny*nz
1819 :
1820 360550 : call dfti_alloc_complex(nhp*ndat,cptr,gg_hp)
1821 :
1822 360550 : arr3(1) = nx
1823 360550 : arr3(2) = ny
1824 360550 : arr3(3) = nz
1825 360550 : status = DftiCreateDescriptor(Desc, DFTI_DOUBLE, DFTI_REAL, 3, arr3 )
1826 360550 : DFTI_CHECK(status)
1827 :
1828 360550 : status = DftiSetValue(Desc, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX)
1829 360550 : status = DftiSetValue(Desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE )
1830 360550 : arr(1) = 0
1831 360550 : arr(2) = 1
1832 360550 : arr(3) = ldx
1833 360550 : arr(4) = ldx*ldy
1834 360550 : status = DftiSetValue(Desc, DFTI_INPUT_STRIDES, arr)
1835 360550 : status = DftiSetValue(Desc, DFTI_INPUT_DISTANCE, ldx*ldy*ldz)
1836 : arr(1) = 0
1837 : arr(2) = 1
1838 360550 : arr(3) = padx
1839 360550 : arr(4) = padx*ny
1840 360550 : status = DftiSetValue(Desc, DFTI_OUTPUT_STRIDES, arr)
1841 360550 : status = DftiSetValue(Desc, DFTI_OUTPUT_DISTANCE, nhp)
1842 360550 : status = DftiSetValue(Desc, DFTI_NUMBER_OF_TRANSFORMS, ndat)
1843 360550 : status = DftiSetValue(Desc, DFTI_FORWARD_SCALE, one / DBLE(nx*ny*nz) )
1844 360550 : DFTI_CHECK(status)
1845 :
1846 360550 : DFTI_CHECK( DftiCommitDescriptor(Desc) )
1847 :
1848 360550 : DFTI_CHECK( DftiComputeForward(Desc, ff, gg_hp) )
1849 :
1850 360550 : DFTI_CHECK( DftiFreeDescriptor(Desc) )
1851 :
1852 : ! Reconstruct full FFT: Hermitian redundancy: out[i] is the conjugate of out[n-i]
1853 1081650 : ABI_MALLOC(i1inver,(padx))
1854 1081650 : ABI_MALLOC(i2inver,(ny))
1855 1081650 : ABI_MALLOC(i3inver,(nz))
1856 :
1857 360550 : i1inver(1)=1
1858 4407639 : do i1=2,padx
1859 4407639 : i1inver(i1)=nx+2-i1
1860 : end do
1861 :
1862 360550 : i2inver(1)=1
1863 7777186 : do i2=2,ny
1864 7777186 : i2inver(i2)=ny+2-i2
1865 : end do
1866 :
1867 360550 : i3inver(1)=1
1868 8925704 : do i3=2,nz
1869 8925704 : i3inver(i3)=nz+2-i3
1870 : end do
1871 :
1872 : igp=0
1873 721118 : do idat=1,ndat
1874 360568 : padatf=(idat-1)*ldx*ldy*ldz
1875 9647092 : do i3=1,nz
1876 8925974 : i3inv = i3inver(i3)
1877 233635581 : do i2=1,ny
1878 224349039 : i2inv = i2inver(i2)
1879 4486547570 : do i1=1,padx
1880 4253272557 : igp=igp+1
1881 4253272557 : igf = i1 + (i3-1)*ldx*ldy + (i2-1)*ldx + padatf
1882 4253272557 : gg(igf) = gg_hp(igp)
1883 4253272557 : i1inv = i1inver(i1)
1884 4477621596 : if (i1inv/=i1) then
1885 3828821252 : imgf = i1inv + (i3inv-1)*ldx*ldy + (i2inv-1)*ldx + padatf
1886 3828821252 : gg(imgf) = DCONJG(gg_hp(igp))
1887 : end if
1888 : end do
1889 : end do
1890 : end do
1891 : end do
1892 :
1893 360550 : ABI_FREE(i1inver)
1894 360550 : ABI_FREE(i2inver)
1895 360550 : ABI_FREE(i3inver)
1896 :
1897 360550 : call dfti_free(cptr)
1898 :
1899 : #else
1900 : ABI_ERROR("FFT_DFTI support not activated")
1901 : ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz/))
1902 : ABI_UNUSED(ff)
1903 : ABI_UNUSED(gg(1))
1904 : #endif
1905 :
1906 360550 : end subroutine dfti_r2c_op_dpc
1907 : !!***
1908 :
1909 : !----------------------------------------------------------------------
1910 :
1911 : !!****f* m_dfti/dfti_r2c_op_dp
1912 : !! NAME
1913 : !! dfti_r2c_op_dp
1914 : !!
1915 : !! FUNCTION
1916 : !! Driver routine for out-of-place 3D real-to-complex FFT of lengths nx, ny, nz.
1917 : !!
1918 : !! INPUTS
1919 : !! nx,ny,nz=Number of points along the three directions.
1920 : !! ldx,ldy,ldz=Physical dimensions of the f array (to avoid cache conflicts).
1921 : !! ndat=Number of FFTs to be done.
1922 : !! ff(ldx*ldy*ldz*ndat)=The real array to be transformed.
1923 : !!
1924 : !! OUTPUT
1925 : !! gg(2*ldx*ldy*ldz*ndat)=The forward FFT of ff (real valued)
1926 : !!
1927 : !! SOURCE
1928 :
1929 360550 : subroutine dfti_r2c_op_dp(nx, ny, nz, ldx, ldy, ldz, ndat, ff, gg)
1930 :
1931 : !Arguments ------------------------------------
1932 : !scalars
1933 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat
1934 : !arrays
1935 : real(dp),intent(in) :: ff(ldx*ldy*ldz*ndat)
1936 : real(dp),target,intent(out) :: gg(2*ldx*ldy*ldz*ndat)
1937 :
1938 : #ifdef HAVE_DFTI
1939 : !Local variables-------------------------------
1940 : !scalars
1941 : type(C_ptr) :: gg_cptr
1942 : !arrays
1943 : complex(dp),contiguous, pointer :: gg_fptr(:)
1944 : ! *************************************************************************
1945 :
1946 360550 : gg_cptr = C_loc(gg)
1947 360550 : call C_F_pointer(gg_cptr,gg_fptr, shape=(/ldx*ldy*ldz*ndat/))
1948 :
1949 360550 : call dfti_r2c_op_dpc(nx,ny,nz,ldx,ldy,ldz,ndat,ff,gg_fptr)
1950 :
1951 : #else
1952 : ABI_ERROR("FFT_DFTI support not activated")
1953 : ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz/))
1954 : ABI_UNUSED(ff)
1955 : ABI_UNUSED(gg(1))
1956 : #endif
1957 :
1958 360550 : end subroutine dfti_r2c_op_dp
1959 : !!***
1960 :
1961 : !----------------------------------------------------------------------
1962 :
1963 : !!****f* m_dfti/dfti_c2r_op_dpc
1964 : !! NAME
1965 : !! dfti_c2r_op_dpc
1966 : !!
1967 : !! FUNCTION
1968 : !! Driver routine for out-of-place 3D complex-to-real FFT of lengths nx, ny, nz.
1969 : !!
1970 : !! INPUTS
1971 : !! nx,ny,nz=Number of point along the three directions.
1972 : !! ldx,ldy,ldz=Physical dimension of the f array (to avoid cache conflicts).
1973 : !! ndat=Number of FFTs to be done.
1974 : !! ff(2,ldx*ldy*ldz*ndat)=The complex array to be transformed.
1975 : !!
1976 : !! OUTPUT
1977 : !! gg(2,ldx*ldy*ldz*ndat)=The backwards real FFT of ff.
1978 : !!
1979 : !! SOURCE
1980 :
1981 389721 : subroutine dfti_c2r_op_dpc(nx, ny, nz, ldx, ldy, ldz, ndat, ff, gg)
1982 :
1983 : !Arguments ------------------------------------
1984 : !scalars
1985 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat
1986 : !arrays
1987 : complex(dp),intent(in) :: ff(ldx*ldy*ldz*ndat)
1988 : real(dp),intent(out) :: gg(ldx*ldy*ldz*ndat)
1989 :
1990 : #ifdef HAVE_DFTI
1991 : !Local variables-------------------------------
1992 : !scalars
1993 : integer :: status,nhp,padx,i2,i3,igp,igf,idat,padatf,padatp,ii,arr(4),arr3(3)
1994 : type(DFTI_DESCRIPTOR),pointer :: Desc
1995 : type(C_PTR) :: cptr
1996 : !arrays
1997 : complex(dp),contiguous, pointer :: ff_hp(:)
1998 : ! *************************************************************************
1999 :
2000 : !stride = 1
2001 : !idist = nhp
2002 : !odist = nx*ny*nz
2003 : !n = (/nx,ny,nz/)
2004 : !inembed = (/(nx/2+1),ny,nz/)
2005 : !onembed = (/nx,ny,nz/) ! check this
2006 : !my_plan = retrieve_plan3(n,ndat,inembed,stride,idist,onembed,stride,odist,FFTW_BACKWARD,my_flags,Saved_plans)
2007 :
2008 : ! Fill the Hermitian part: Hermitian redundancy: out[i] is the conjugate of out[n-i]
2009 389721 : padx = (nx/2+1)
2010 389721 : nhp = padx*ny*nz
2011 :
2012 389721 : call dfti_alloc_complex(nhp*ndat,cptr,ff_hp)
2013 :
2014 : !!$OMP PARALLEL DO PRIVATE(padatf,padatp,igf,igp)
2015 779460 : do idat=1,ndat
2016 389739 : padatf=(idat-1)*ldx*ldy*ldz
2017 389739 : padatp=(idat-1)*padx*ny*nz
2018 10328073 : do i3=1,nz
2019 247273504 : do i2=1,ny
2020 237335152 : igf = (i3-1)*ldx*ldy + (i2-1)*ldx + padatf
2021 237335152 : igp = (i3-1)*padx*ny + (i2-1)*padx + padatp
2022 4628680725 : ff_hp(igp+1:igp+padx) = ff(igf+1:igf+padx)
2023 : end do
2024 : end do
2025 : end do
2026 :
2027 389721 : arr3(1) = nx
2028 389721 : arr3(2) = ny
2029 389721 : arr3(3) = nz
2030 389721 : status = DftiCreateDescriptor(Desc, DFTI_DOUBLE, DFTI_REAL, 3, arr3 )
2031 389721 : DFTI_CHECK(status)
2032 :
2033 389721 : status = DftiSetValue(Desc, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX)
2034 389721 : status = DftiSetValue(Desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE )
2035 389721 : arr(1) = 0
2036 389721 : arr(2) = 1
2037 389721 : arr(3) = padx
2038 389721 : arr(4) = padx*ny
2039 389721 : status = DftiSetValue(Desc, DFTI_INPUT_STRIDES, arr)
2040 389721 : status = DftiSetValue(Desc, DFTI_INPUT_DISTANCE, nhp)
2041 : arr(1) = 0
2042 : arr(2) = 1
2043 389721 : arr(3) = ldx
2044 389721 : arr(4) = ldx*ldy
2045 389721 : status = DftiSetValue(Desc, DFTI_OUTPUT_STRIDES, arr)
2046 389721 : status = DftiSetValue(Desc, DFTI_OUTPUT_DISTANCE, ldx*ldy*ldz)
2047 389721 : status = DftiSetValue(Desc, DFTI_NUMBER_OF_TRANSFORMS, ndat)
2048 389721 : DFTI_CHECK(status)
2049 :
2050 389721 : DFTI_CHECK( DftiCommitDescriptor(Desc) )
2051 :
2052 389721 : DFTI_CHECK( DftiComputeBackward(Desc, ff_hp, gg) )
2053 :
2054 389721 : DFTI_CHECK( DftiFreeDescriptor(Desc) )
2055 :
2056 389721 : call dfti_free(cptr)
2057 :
2058 : #else
2059 : ABI_ERROR("FFT_DFTI support not activated")
2060 : ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz/))
2061 : ABI_UNUSED(ff(1))
2062 : ABI_UNUSED(gg(1))
2063 : #endif
2064 :
2065 389721 : end subroutine dfti_c2r_op_dpc
2066 : !!***
2067 :
2068 : !----------------------------------------------------------------------
2069 :
2070 : !!****f* m_dfti/dfti_c2r_op_dp
2071 : !! NAME
2072 : !! dfti_c2r_op_dp
2073 : !!
2074 : !! FUNCTION
2075 : !! Driver routine for out-of-place 3D complex-to-real FFT of lengths nx, ny, nz.
2076 : !!
2077 : !! INPUTS
2078 : !! nx,ny,nz=Number of point along the three directions.
2079 : !! ldx,ldy,ldz=Physical dimension of the f array (to avoid cache conflicts).
2080 : !! ndat=Number of FFTs to be done.
2081 : !! ff(2,ldx*ldy*ldz*ndat)=The complex array to be transformed.
2082 : !!
2083 : !! OUTPUT
2084 : !! gg(ldx*ldy*ldz*ndat)=The backwards real FFT of ff.
2085 : !!
2086 : !! SOURCE
2087 :
2088 389721 : subroutine dfti_c2r_op_dp(nx, ny, nz, ldx, ldy, ldz, ndat, ff, gg)
2089 :
2090 : !Arguments ------------------------------------
2091 : !scalars
2092 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat
2093 : !arrays
2094 : real(dp),target,intent(in) :: ff(2*ldx*ldy*ldz*ndat)
2095 : real(dp),intent(inout) :: gg(ldx*ldy*ldz*ndat) !vz_i
2096 :
2097 : #ifdef HAVE_DFTI
2098 : !Local variables-------------------------------
2099 : !scalars
2100 : type(C_ptr) :: ff_cptr
2101 : !arrays
2102 : complex(dp),contiguous, pointer :: ff_fptr(:)
2103 : ! *************************************************************************
2104 :
2105 389721 : ff_cptr = C_loc(ff)
2106 389721 : call C_F_pointer(ff_cptr,ff_fptr, shape=(/ldx*ldy*ldz*ndat/))
2107 :
2108 389721 : call dfti_c2r_op_dpc(nx,ny,nz,ldx,ldy,ldz,ndat,ff_fptr,gg)
2109 :
2110 : #else
2111 : ABI_ERROR("FFT_DFTI support not activated")
2112 : ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz/))
2113 : ABI_UNUSED((/ff(1),gg(1)/))
2114 : #endif
2115 :
2116 389721 : end subroutine dfti_c2r_op_dp
2117 : !!***
2118 :
2119 : !----------------------------------------------------------------------
2120 :
2121 : !!****f* m_dfti/dfti_check_status
2122 : !! NAME
2123 : !! dfti_check_status
2124 : !!
2125 : !! FUNCTION
2126 : !! Error handler for DFTI wrappers. Print error message and abort.
2127 : !!
2128 : !! INPUTS
2129 : !! status = status error reported by dfti.
2130 : !! [file] = file name
2131 : !! [line] = line number
2132 : !!
2133 : !! SOURCE
2134 :
2135 : #ifdef HAVE_DFTI
2136 :
2137 0 : subroutine dfti_check_status(status, file, line)
2138 :
2139 : !Arguments ------------------------------------
2140 : !scalars
2141 : integer,intent(in) :: status
2142 : integer,optional,intent(in) :: line
2143 : character(len=*),optional,intent(in) :: file
2144 :
2145 : !Local variables-------------------------------
2146 : integer :: f90line
2147 : character(len=10) :: lnum
2148 : character(len=500) :: f90name
2149 : character(len=500) :: my_msg
2150 : character(len=DFTI_MAX_MESSAGE_LENGTH+500) :: err_msg
2151 : ! *************************************************************************
2152 :
2153 0 : if (PRESENT(line)) then
2154 0 : f90line=line
2155 : else
2156 0 : f90line=0
2157 : end if
2158 0 : call int2char10(f90line,lnum)
2159 :
2160 0 : if (PRESENT(file)) then
2161 0 : f90name = basename(file)
2162 : else
2163 0 : f90name='Subroutine Unknown'
2164 : end if
2165 :
2166 0 : my_msg=strcat(f90name,":",lnum,":")
2167 :
2168 0 : if (status /= 0) then
2169 0 : if (.not. DftiErrorClass(status, DFTI_NO_ERROR)) then
2170 0 : err_msg = strcat(my_msg," Error: ",DftiErrorMessage(status))
2171 0 : ABI_ERROR(err_msg)
2172 : end if
2173 : end if
2174 :
2175 0 : end subroutine dfti_check_status
2176 : !!***
2177 :
2178 : #endif
2179 :
2180 : !----------------------------------------------------------------------
2181 :
2182 : !!****f* m_dfti/dfti_spawn_threads_here
2183 : !! NAME
2184 : !! dfti_spawn_threads_here
2185 : !!
2186 : !! FUNCTION
2187 : !! Helper function that returns true if FFT calls should be OMP
2188 : !! parallelized in the client code.
2189 : !!
2190 : !! INPUTS
2191 : !! ndat=Number of FFT transforms to do
2192 : !! nthreads = Number of threads available
2193 : !!
2194 : !! SOURCE
2195 :
2196 : function dfti_spawn_threads_here(ndat, nthreads) result(ans)
2197 :
2198 : !Arguments ------------------------------------
2199 : !scalars
2200 : integer,intent(in) :: ndat,nthreads
2201 : logical :: ans
2202 : ! *************************************************************************
2203 :
2204 2113 : ans = .FALSE.
2205 : #ifdef HAVE_OPENMP
2206 : ans = (nthreads > 1 .and. MOD(ndat,nthreads) == 0 .and. .not. USE_LIB_THREADS)
2207 : #else
2208 : ABI_UNUSED((/ndat,nthreads/))
2209 : #endif
2210 :
2211 : end function dfti_spawn_threads_here
2212 : !!***
2213 :
2214 : !----------------------------------------------------------------------
2215 :
2216 : !!****f* m_dfti/dfti_use_lib_threads
2217 : !! NAME
2218 : !! dfti_use_lib_threads
2219 : !!
2220 : !! FUNCTION
2221 : !!
2222 : !! INPUTS
2223 : !!
2224 : !! SOURCE
2225 :
2226 19 : subroutine dfti_use_lib_threads(logvar)
2227 :
2228 : !Arguments ------------------------------------
2229 : logical,intent(in) :: logvar
2230 : ! *************************************************************************
2231 :
2232 19 : USE_LIB_THREADS = logvar
2233 :
2234 19 : end subroutine dfti_use_lib_threads
2235 : !!***
2236 :
2237 : !----------------------------------------------------------------------
2238 :
2239 : !!****f* m_dfti/dfti_alloc_real_dp
2240 : !! NAME
2241 : !! dfti_alloc_real_dp
2242 : !!
2243 : !! FUNCTION
2244 : !!
2245 : !! INPUTS
2246 : !!
2247 : !! OUTPUT
2248 : !!
2249 : !! SOURCE
2250 :
2251 : #ifdef HAVE_DFTI
2252 :
2253 : subroutine dfti_alloc_real_dp(size, cptr, fptr)
2254 :
2255 : !Arguments ------------------------------------
2256 : !scalars
2257 : integer,intent(in) :: size
2258 : real(dp),contiguous, pointer :: fptr(:)
2259 : type(C_PTR),intent(out) :: cptr
2260 : ! *************************************************************************
2261 :
2262 : cptr = mkl_malloc( INT(size*C_DOUBLE, KIND=C_SIZE_T), DFTI_DEFAULT_ALIGNMENT_DP)
2263 : if (.not. C_ASSOCIATED(cptr)) then
2264 : ABI_ERROR("mkl_malloc returned NULL!")
2265 : end if
2266 :
2267 : call c_f_pointer(cptr, fptr, [size])
2268 :
2269 : end subroutine dfti_alloc_real_dp
2270 : !!***
2271 :
2272 : #endif
2273 :
2274 : !----------------------------------------------------------------------
2275 :
2276 : !!****f* m_dfti/dfti_alloc_complex_spc
2277 : !! NAME
2278 : !! dfti_alloc_complex_spc
2279 : !!
2280 : !! FUNCTION
2281 : !!
2282 : !! INPUTS
2283 : !!
2284 : !! OUTPUT
2285 : !!
2286 : !! SOURCE
2287 :
2288 : #ifdef HAVE_DFTI
2289 :
2290 577567 : subroutine dfti_alloc_complex_spc(size, cptr, fptr)
2291 :
2292 : !Arguments ------------------------------------
2293 : !scalars
2294 : integer,intent(in) :: size
2295 : complex(sp),contiguous, pointer :: fptr(:)
2296 : type(C_PTR),intent(out) :: cptr
2297 : ! *************************************************************************
2298 :
2299 577567 : cptr = mkl_malloc( INT(2*size*C_FLOAT, KIND=C_SIZE_T), DFTI_DEFAULT_ALIGNMENT_SP)
2300 577567 : if (.not. C_ASSOCIATED(cptr)) then
2301 0 : ABI_ERROR("mkl_malloc returned NULL!")
2302 : end if
2303 :
2304 1155134 : call c_f_pointer(cptr, fptr, [size])
2305 :
2306 577567 : end subroutine dfti_alloc_complex_spc
2307 : !!***
2308 :
2309 : #endif
2310 :
2311 : !----------------------------------------------------------------------
2312 :
2313 : !!****f* m_dfti/dfti_alloc_complex_dpc
2314 : !! NAME
2315 : !! dfti_alloc_complex_dpc
2316 : !!
2317 : !! FUNCTION
2318 : !!
2319 : !! INPUTS
2320 : !!
2321 : !! OUTPUT
2322 : !!
2323 : !! SOURCE
2324 :
2325 : #ifdef HAVE_DFTI
2326 :
2327 192320084 : subroutine dfti_alloc_complex_dpc(size, cptr, fptr)
2328 :
2329 : !Arguments ------------------------------------
2330 : !scalars
2331 : integer,intent(in) :: size
2332 : complex(dp),contiguous, pointer :: fptr(:)
2333 : type(C_PTR),intent(out) :: cptr
2334 : ! *************************************************************************
2335 :
2336 192320084 : cptr = mkl_malloc( INT(2*size*C_DOUBLE, KIND=C_SIZE_T), DFTI_DEFAULT_ALIGNMENT_DP)
2337 192320084 : if (.not. C_ASSOCIATED(cptr)) then
2338 0 : ABI_ERROR("mkl_malloc returned NULL!")
2339 : end if
2340 :
2341 384640168 : call c_f_pointer(cptr, fptr, [size])
2342 :
2343 192320084 : end subroutine dfti_alloc_complex_dpc
2344 : !!***
2345 :
2346 : #endif
2347 :
2348 : !----------------------------------------------------------------------
2349 :
2350 : END MODULE m_dfti
2351 : !!***
|