Line data Source code
1 : !!****m* ABINIT/m_fftcore
2 : !! NAME
3 : !! m_fftcore
4 : !!
5 : !! FUNCTION
6 : !! Low-level tools for FFT (sequential and MPI parallel version)
7 : !! It also provides helper functions to set up the list of G vectors
8 : !! inside a sphere or to count them.
9 : !!
10 : !! COPYRIGHT
11 : !! Copyright (C) 2014-2026 ABINIT group (SG, XG, AR, MG, MT)
12 : !! This file is distributed under the terms of the
13 : !! GNU General Public License, see ~abinit/COPYING
14 : !! or http://www.gnu.org/copyleft/gpl.txt .
15 : !!
16 : !! TODO
17 : !! 1) Pass distribfft instead of MPI_enreg to simplify the API and facilitate code-reuse.
18 : !!
19 : !! 2) Merge this module with m_distribfft
20 : !!
21 : !! 3) Get rid of paral_kgb and MPI_type! This is a low-level module that may be called by other
22 : !! code in which paral_kgb is meaningless! FFT tables and a MPI communicator are sufficient.
23 : !!
24 : !! SOURCE
25 :
26 : #if defined HAVE_CONFIG_H
27 : #include "config.h"
28 : #endif
29 :
30 : #include "abi_common.h"
31 :
32 : module m_fftcore
33 :
34 : use defs_basis
35 : use m_abicore
36 : use m_errors
37 : use m_xmpi
38 : use m_sort
39 :
40 : use m_time, only : timab
41 : use m_fstrings, only : itoa, sjoin
42 : use m_geometry, only : normv
43 : use defs_abitypes, only : MPI_type
44 : use m_mpinfo, only : destroy_mpi_enreg, initmpi_seq
45 :
46 : implicit none
47 :
48 : private
49 :
50 : public :: fftalg_isavailable ! True if the FFT library specified by fftalg is available.
51 : public :: fftalg_has_mpi ! True if fftalg provides MPI-FFTs.
52 : public :: fftalg_for_npfft ! Returns the default value for fftalg given the number of processors for the FFT.
53 : public :: fftalg_info ! Returns strings with info on the FFT library specified by fftalg.
54 : public :: get_cache_kb ! Returns the cache size in Kbs (based on CPP variables).
55 : public :: ngfft_seq ! initialize ngfft(18) from the FFT divisions (assume sequential FFT)
56 : public :: print_ngfft ! Print the content of ngfft(18) in explicative format.
57 : public :: bound ! Find distance**2 to boundary point of fft box nearest to kpt
58 : public :: getng ! From ecut and metric tensor in reciprocal space, computes recommended ngfft(1:3)
59 : public :: sphereboundary ! Finds the boundary of the basis sphere of G vectors
60 : public :: sphere
61 : public :: sphere_fft ! Insert cg inside box.
62 : public :: sphere_fft1 ! TODO: This one should be replaced by sphere_fft.
63 : public :: change_istwfk ! Change the istwfk mode of a set of wavefunctions (sequential version, same k-point)
64 : public :: kpgsph ! Set up the G vector list
65 : public :: kpgcount ! Give the number of G vector in each direction
66 : public :: get_kg ! Helper function to calculate the set of G-vectors at a given kpoint (no MPI FFT)
67 : public :: kgindex ! Compute the index of each plane wave on a FFT grid.
68 :
69 : ! Low-level tools for MPI FFT
70 : public :: switch
71 : public :: switch_cent
72 : public :: switchreal
73 : public :: switchreal_cent
74 : public :: scramble
75 : public :: fill
76 : public :: fill_cent
77 : public :: unfill
78 : public :: unfill_cent
79 : public :: unmpiswitch
80 : public :: unswitch
81 : public :: unswitchreal_cent
82 : public :: unmpiswitch_cent
83 : public :: unscramble
84 : public :: unswitch_cent
85 : public :: unswitchreal
86 : public :: mpiswitch
87 : public :: mpiswitch_cent
88 :
89 : public :: mpifft_fg2dbox
90 : public :: mpifft_fg2dbox_dpc
91 : public :: mpifft_dbox2fg
92 : public :: mpifft_dbox2fg_dpc
93 : public :: mpifft_dbox2fr
94 : public :: mpifft_dbox2fr_dpc
95 : public :: mpifft_fr2dbox
96 : public :: mpifft_fr2dbox_dpc
97 : public :: mpifft_collect_datar ! Collect a real-space MPI-FFT distributed array on each proc.
98 :
99 : public :: indfftrisc
100 : public :: addrho
101 : public :: multpot
102 :
103 : ! 0 for double precision version (default), 1 for mixed precision FFTs
104 : integer, public, save, protected :: fftcore_mixprec = 0
105 : public :: fftcore_set_mixprec
106 : ! *************************************************************************
107 :
108 : !----------------------------------------------------------------------
109 : ! Private variables
110 :
111 : #define FFTALGA_SIZE 5
112 : character(len=*),private,parameter :: fftalga2name(1:FFTALGA_SIZE)= &
113 : (/"Goedecker ", &
114 : "Vendor FFT ", &
115 : "FFTW3 ", &
116 : "Goedecker2002 ", &
117 : "DFTI " /)
118 :
119 : #define FFTALGB_SIZE 1
120 : character(len=*),private,parameter :: fftalgb2name(0:FFTALGB_SIZE)= &
121 : (/"C2C",&
122 : "R2C"/)
123 :
124 : #define FFTALGC_SIZE 2
125 : character(len=*),private,parameter :: fftalgc2name(0:FFTALGC_SIZE)= &
126 : (/"No pad ",&
127 : "zero-pad ",&
128 : "zero-pad+cache "/)
129 :
130 : contains
131 : !!***
132 :
133 : !----------------------------------------------------------------------
134 :
135 : !!****f* m_fftcore/fftcore_set_mixprec
136 : !! NAME
137 : !! fftalg_set_precision
138 : !!
139 : !! FUNCTION
140 : !! Set the precision to be used in the FFT routines: 0 for standard double precision,
141 : !! 1 for mixed precision (dp input, sp for intermediate arrays passed to FFT libs)
142 : !! Return old value.
143 : !!
144 : !! INPUTS
145 : !!
146 : !! SOURCE
147 :
148 57242 : integer function fftcore_set_mixprec(wp) result(old_wp)
149 :
150 : !Arguments ------------------------------------
151 : !scalars
152 : integer,intent(in) :: wp
153 : ! *************************************************************************
154 :
155 57242 : old_wp = fftcore_mixprec
156 57242 : fftcore_mixprec = abs(wp)
157 :
158 57194 : select case (fftcore_mixprec)
159 : case (0)
160 57194 : if (old_wp /= fftcore_mixprec) call wrtout(std_out, " fftcore_mixprec 0 --> Using double-precision FFT", newlines=1)
161 : case (1)
162 48 : if (old_wp /= fftcore_mixprec) call wrtout(std_out, " fftcore_mixprec 1 --> Using mixed precision FFT", newlines=1)
163 : case default
164 57242 : ABI_ERROR(sjoin("Wrong value for input wp:", itoa(fftcore_mixprec)))
165 : end select
166 :
167 57242 : end function fftcore_set_mixprec
168 : !!***
169 :
170 : !----------------------------------------------------------------------
171 :
172 : !!****f* m_fftcore/fftalg_isavailable
173 : !! NAME
174 : !! fftalg_isavailable
175 : !!
176 : !! FUNCTION
177 : !! Returns TRUE if the FFT library specified by fftalg (ngfft(7)) is available
178 : !!
179 : !! INPUTS
180 : !! fftalg=Input variable.
181 : !!
182 : !! SOURCE
183 :
184 98 : logical pure function fftalg_isavailable(fftalg) result(ans)
185 :
186 : !Arguments ------------------------------------
187 : integer,intent(in) :: fftalg
188 :
189 : !Local variables-------------------------------
190 : integer :: fftalga,fftalgb,fftalgc
191 : ! *************************************************************************
192 :
193 98 : ans = .TRUE.
194 98 : fftalga = fftalg/100
195 98 : fftalgb = mod(fftalg,100)/10
196 98 : fftalgc = mod(fftalg,10)
197 :
198 : ! Optional FFT libraries.
199 : #ifndef HAVE_FFTW3
200 98 : if (fftalga == FFT_FFTW3) ans = .FALSE.
201 : #endif
202 :
203 : #ifndef HAVE_DFTI
204 : if (fftalga == FFT_DFTI) ans = .FALSE.
205 : #endif
206 :
207 98 : end function fftalg_isavailable
208 : !!***
209 :
210 : !----------------------------------------------------------------------
211 :
212 : !!****f* m_fftcore/fftalg_has_mpi
213 : !! NAME
214 : !! fftalg_has_mpi
215 : !!
216 : !! FUNCTION
217 : !! True if the FFT library specified by fftalg is available.
218 : !!
219 : !! INPUTS
220 : !! fftalg=Input variable.
221 : !!
222 : !! SOURCE
223 :
224 256 : pure function fftalg_has_mpi(fftalg) result(ans)
225 :
226 : !Arguments ------------------------------------
227 : !scalars
228 : integer,intent(in) :: fftalg
229 : logical :: ans
230 :
231 : !Local variables-------------------------------
232 : !scalars
233 : integer :: fftalga,fftalgb,fftalgc
234 : ! *************************************************************************
235 :
236 256 : ans = .False.
237 256 : fftalga = fftalg/100; fftalgb = mod(fftalg,100)/10; fftalgc = mod(fftalg,10)
238 :
239 256 : if (fftalga == FFT_FFTW3) ans = .True.
240 : !if (fftalga == FFT_DFTI) ans = .True.
241 256 : if (fftalga == FFT_SG2002) ans = .True.
242 :
243 256 : end function fftalg_has_mpi
244 : !!***
245 :
246 : !----------------------------------------------------------------------
247 :
248 : !!****f* m_fftcore/fftalg_for_npfft
249 : !! NAME
250 : !! fftalg_for_npfft
251 : !!
252 : !! FUNCTION
253 : !! Returns the default value of fftalg given the number of MPI nodes
254 : !! to be used in the FFTs.
255 : !!
256 : !! INPUTS
257 : !! nproc_fft=Number of processors used for MPI FFT
258 : !! nthreads =Number of openMP threads
259 : !!
260 : !! OUTPUT
261 : !! fftalg=Integer used to select the FFT library.
262 : !!
263 : !! SOURCE
264 :
265 22303 : pure function fftalg_for_npfft(nproc_fft, forbid_threads) result(fftalg)
266 :
267 : !Arguments ------------------------------------
268 : !scalars
269 : integer,intent(in) :: nproc_fft
270 : logical,intent(in),optional :: forbid_threads
271 : integer :: fftalg
272 : ! *************************************************************************
273 :
274 : ! Default for the sequential case.
275 : fftalg = 112
276 :
277 : ! Use Goedecker2002 if fftalg does not support MPI or threads (e.g 112)
278 22303 : if (nproc_fft > 1) fftalg = 401
279 : if (present(forbid_threads)) then
280 : if (forbid_threads) fftalg = 401
281 : endif
282 :
283 : #ifdef HAVE_FFTW3
284 : fftalg = 312
285 : #elif defined HAVE_DFTI
286 22303 : fftalg = 512
287 22303 : if (nproc_fft > 1) fftalg = 401 ! MPI-FFT with DFTI is not implemented yet
288 : #endif
289 :
290 : !if (nproc_fft > 1) fftalg = 401 ! This is to revert to the old behavior.
291 :
292 22303 : end function fftalg_for_npfft
293 : !!***
294 :
295 : !----------------------------------------------------------------------
296 :
297 : !!****f* m_fftcore/fftalg_info
298 : !! NAME
299 : !! fftalg_info
300 : !!
301 : !! FUNCTION
302 : !! Returns info on the FFT library specified by fftalg (ngfft(7))
303 : !!
304 : !! INPUTS
305 : !! fftalg=Input variable.
306 : !!
307 : !! OUTPUT
308 : !! library=String with the name of FFT library
309 : !! cplex_mode= String defining whether the FFT library supports real<-->complex transforms.
310 : !! padding_mode=Padding mode.
311 : !!
312 : !! SOURCE
313 :
314 423 : subroutine fftalg_info(fftalg,library,cplex_mode,padding_mode)
315 :
316 : !Arguments ------------------------------------
317 : !scalars
318 : integer,intent(in) :: fftalg
319 : character(len=*),intent(out) :: library,cplex_mode,padding_mode
320 :
321 : !Local variables-------------------------------
322 : !scalars
323 : integer :: fftalga,fftalgb,fftalgc
324 : ! *************************************************************************
325 :
326 423 : library = "Unknown"; cplex_mode = "Unknown"; padding_mode = "Unknown"
327 :
328 423 : fftalga=fftalg/100
329 423 : if (fftalga>0 .and. fftalga<=FFTALGA_SIZE) library = fftalga2name(fftalga)
330 :
331 423 : fftalgb=mod(fftalg,100)/10
332 423 : if (fftalgb>=0 .and. fftalgb<=FFTALGB_SIZE) cplex_mode = fftalgb2name(fftalgb)
333 :
334 423 : fftalgc=mod(fftalg,10)
335 423 : if (fftalgc>=0 .and. fftalgc<=FFTALGC_SIZE) padding_mode = fftalgc2name(fftalgc)
336 :
337 423 : end subroutine fftalg_info
338 : !!***
339 :
340 : !----------------------------------------------------------------------
341 :
342 : !!****f* m_fftcore/get_cache_kb
343 : !! NAME
344 : !! get_cache_kb
345 : !!
346 : !! FUNCTION
347 : !! Returns the cache size in KB to be used for cache blocking algorithms in the FFT routines.
348 : !! The value is derived from the values of the CPP options defined in config.h
349 : !!
350 : !! TODO
351 : !! Use C to get the real cache size.
352 : !! See http://stackoverflow.com/questions/12594208/c-program-to-determine-levels-size-of-cache
353 : !!
354 : !! SOURCE
355 :
356 8501 : pure function get_cache_kb()
357 :
358 : !Local variables-------------------------------
359 : !scalars
360 : integer :: get_cache_kb
361 : ! *************************************************************************
362 :
363 : ! Default value
364 154715 : get_cache_kb = 16
365 : !get_cache_kb = 32
366 : !get_cache_kb = 256
367 :
368 8501 : end function get_cache_kb
369 : !!***
370 :
371 : !----------------------------------------------------------------------
372 :
373 : !!****f* m_fftcore/ngfft_seq
374 : !! NAME
375 : !! ngfft_seq
376 : !!
377 : !! FUNCTION
378 : !! Helper function used to initialize ngfft(18) from the FFT divisions
379 : !! in the case of sequential execution.
380 : !!
381 : !! INPUTS
382 : !! n123(3)=FFT divisions.
383 : !!
384 : !! OUTPUT
385 : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft.
386 : !!
387 : !! SOURCE
388 :
389 146214 : pure subroutine ngfft_seq(ngfft, n123)
390 :
391 : !Arguments ------------------------------------
392 : integer,intent(in) :: n123(3)
393 : integer,intent(out) :: ngfft(18)
394 :
395 : !Local variables-------------------------------
396 : integer :: fftalg
397 : ! *************************************************************************
398 :
399 : ! Default for sequential case.
400 : fftalg = 112
401 : #ifdef HAVE_FFTW3
402 : fftalg = 312
403 : #elif defined HAVE_DFTI
404 146214 : fftalg = 512
405 : #endif
406 :
407 584856 : ngfft(1:3) = n123
408 146214 : ngfft(4) = 2*(ngfft(1)/2)+1
409 146214 : ngfft(5) = 2*(ngfft(2)/2)+1
410 146214 : ngfft(6) = ngfft(3)
411 146214 : ngfft(7)= fftalg ! fftalg
412 146214 : ngfft(8)= get_cache_kb() ! cache_kb
413 146214 : ngfft(9)= 0 ! paral_fft_
414 146214 : ngfft(10)=1 ! nproc_fft
415 146214 : ngfft(11)=0 ! me_fft
416 146214 : ngfft(12)=0 ! n2proc
417 146214 : ngfft(13)=0 ! n3proc
418 877284 : ngfft(14:18)=0 ! not used
419 :
420 146214 : end subroutine ngfft_seq
421 : !!***
422 :
423 : !----------------------------------------------------------------------
424 :
425 : !!****f* m_fftcore/print_ngfft
426 : !! NAME
427 : !! print_ngfft
428 : !!
429 : !! FUNCTION
430 : !! Print the content of ngfft(18) in explicative format.
431 : !!
432 : !! INPUTS
433 : !! units: Unit numbers
434 : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft.
435 : !! [unit]=unit number for output (defaults to std_out).
436 : !! [prtvol]=verbosity level (defaults to 0).
437 : !!
438 : !! OUTPUT
439 : !! Only writing
440 : !!
441 : !! SOURCE
442 :
443 20396 : subroutine print_ngfft(units, ngfft, header, prtvol)
444 :
445 : !Arguments ------------------------------------
446 : !scalars
447 : integer,intent(in) :: units(:)
448 : integer,intent(in),optional :: prtvol
449 : character(len=*),intent(in),optional :: header
450 : !arrays
451 : integer,intent(in) :: ngfft(18)
452 :
453 : !Local variables-------------------------------
454 : integer :: my_prtvol
455 : character(len=500) :: msg
456 : ! *************************************************************************
457 :
458 10198 : my_prtvol=0; if (PRESENT(prtvol)) my_prtvol=prtvol
459 :
460 10198 : msg = ch10//' ==== FFT mesh description (ngfft) ==== '
461 10198 : if (PRESENT(header)) msg=ch10//' ==== '//TRIM(ADJUSTL(header))//' ==== '
462 10198 : call wrtout(units, msg)
463 :
464 : write(msg,'(2(a,3i5,a),a,i5,2a,i5)')&
465 10198 : '- FFT mesh divisions ........................ ',ngfft(1),ngfft(2),ngfft(3),ch10,&
466 10198 : '- Augmented FFT divisions ................... ',ngfft(4),ngfft(5),ngfft(6),ch10,&
467 10198 : '- FFT algorithm ............................. ',ngfft(7),ch10,&
468 20396 : '- FFT cache size ............................ ',ngfft(8)
469 10198 : call wrtout(units, msg)
470 :
471 10198 : if (my_prtvol > 0) then
472 : write(msg,'(6(a,i5,a),a,4i5)')&
473 0 : '- FFT parallelization level ................. ',ngfft(9),ch10,&
474 0 : '- Number of processors in my FFT group ...... ',ngfft(10),ch10,&
475 0 : '- Index of me in my FFT group ............... ',ngfft(11),ch10,&
476 0 : '- No of xy planes in R space treated by me .. ',ngfft(12),ch10,&
477 0 : '- No of xy planes in G space treated by me .. ',ngfft(13),ch10,&
478 0 : '- MPI communicator for FFT .................. ',ngfft(14),ch10,&
479 0 : '- Value of ngfft(15:18) ..................... ',ngfft(15:18)
480 0 : call wrtout(units, msg)
481 : end if
482 :
483 10198 : end subroutine print_ngfft
484 : !!***
485 :
486 : !!****f* m_fftcore/bound
487 : !! NAME
488 : !! bound
489 : !!
490 : !! FUNCTION
491 : !! For given kpt, ngfft, and gmet,
492 : !! Find distance**2 to boundary point of fft box nearest to kpt
493 : !! Find distance**2 to boundary point of fft box farthest to kpt
494 : !!
495 : !! INPUTS
496 : !! kpt(3)=real input k vector (reduced coordinates)
497 : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
498 : !! gmet(3,3)=reciprocal space metric (currently in Bohr**-2)
499 : !!
500 : !! OUTPUT
501 : !! dsqmax=maximum distance**2 from k to boundary in Bohr**-2.
502 : !! dsqmin=minimum distance**2 from k to boundary in Bohr**-2.
503 : !! gbound(3)=coords of G on boundary (corresponding to gsqmin)
504 : !! plane=which plane min occurs in (1,2, or 3 for G1,etc).
505 : !!
506 : !! NOTES
507 : !! Potential trouble: this routine was written assuming kpt lies inside
508 : !! first Brillouin zone. No measure is taken to fold input kpt back
509 : !! into first zone. Given arbitrary kpt, this will cause trouble.
510 : !!
511 : !! SOURCE
512 :
513 260098 : subroutine bound(dsqmax,dsqmin,gbound,gmet,kpt,ngfft,plane)
514 :
515 : !Arguments ------------------------------------
516 : !scalars
517 : integer,intent(out) :: plane
518 : real(dp),intent(out) :: dsqmax,dsqmin
519 : !arrays
520 : integer,intent(in) :: ngfft(18)
521 : integer,intent(out) :: gbound(3)
522 : real(dp),intent(in) :: gmet(3,3),kpt(3)
523 :
524 : !Local variables-------------------------------
525 : !scalars
526 : integer :: i1,i1min,i2,i2min,i3,i3min
527 : real(dp) :: dsm,dsp
528 : character(len=500) :: msg
529 : ! *************************************************************************
530 :
531 : !Set plane to impossible value
532 260098 : plane=0
533 :
534 : !look at +/- g1 planes:
535 260098 : dsqmax=zero
536 260098 : dsqmin=dsq(ngfft(1)/2,-ngfft(2)/2,-ngfft(3)/2,gmet,kpt)+0.01_dp
537 3602984 : do i2=-ngfft(2)/2,ngfft(2)/2
538 81043142 : do i3=-ngfft(3)/2,ngfft(3)/2
539 77440158 : dsp = dsq(ngfft(1)/2, i2, i3,gmet,kpt)
540 77440158 : dsm = dsq( - ngfft(1)/2, i2, i3,gmet,kpt)
541 77440158 : if (dsp>dsqmax) dsqmax = dsp
542 77440158 : if (dsm>dsqmax) dsqmax = dsm
543 77440158 : if (dsp<dsqmin) then
544 4290521 : dsqmin = dsp
545 4290521 : i1min = ngfft(1)/2
546 4290521 : i2min = i2
547 4290521 : i3min = i3
548 4290521 : plane=1
549 : end if
550 80783044 : if (dsm<dsqmin) then
551 1177269 : dsqmin = dsm
552 1177269 : i1min = - ngfft(1)/2
553 1177269 : i2min = i2
554 1177269 : i3min = i3
555 1177269 : plane=1
556 : end if
557 : end do
558 : end do
559 : !
560 : !+/- g2 planes:
561 3851272 : do i1=-ngfft(1)/2,ngfft(1)/2
562 85565238 : do i3=-ngfft(3)/2,ngfft(3)/2
563 81713966 : dsp = dsq(i1,ngfft(2)/2,i3,gmet,kpt)
564 81713966 : dsm = dsq(i1,-ngfft(2)/2,i3,gmet,kpt)
565 81713966 : if (dsp>dsqmax) dsqmax = dsp
566 81713966 : if (dsm>dsqmax) dsqmax = dsm
567 81713966 : if (dsp<dsqmin) then
568 375291 : dsqmin = dsp
569 375291 : i1min = i1
570 375291 : i2min = ngfft(2)/2
571 375291 : i3min = i3
572 375291 : plane=2
573 : end if
574 85305140 : if (dsm<dsqmin) then
575 208842 : dsqmin = dsm
576 208842 : i1min = i1
577 208842 : i2min = - ngfft(2)/2
578 208842 : i3min = i3
579 208842 : plane=2
580 : end if
581 : end do
582 : end do
583 : !
584 : !+/- g3 planes:
585 3851272 : do i1=-ngfft(1)/2,ngfft(1)/2
586 83399162 : do i2=-ngfft(2)/2,ngfft(2)/2
587 79547890 : dsp = dsq(i1,i2,ngfft(3)/2,gmet,kpt)
588 79547890 : dsm = dsq(i1,i2,-ngfft(3)/2,gmet,kpt)
589 79547890 : if (dsp>dsqmax) dsqmax = dsp
590 79547890 : if (dsm>dsqmax) dsqmax = dsm
591 79547890 : if (dsp<dsqmin) then
592 294650 : dsqmin = dsp
593 294650 : i1min = i1
594 294650 : i2min = i2
595 294650 : i3min = ngfft(3)/2
596 294650 : plane=3
597 : end if
598 83139064 : if (dsm<dsqmin) then
599 141909 : dsqmin = dsm
600 141909 : i1min = i1
601 141909 : i2min = i2
602 141909 : i3min = - ngfft(3)/2
603 141909 : plane=3
604 : end if
605 : end do
606 : end do
607 :
608 260098 : if (plane==0) then
609 : ! Trouble: missed boundary somehow
610 : write(msg, '(a,a,a,3f9.4,a,3(i0,1x),a,a,a,a,a)' )&
611 0 : 'Trouble finding boundary of G sphere for',ch10,&
612 0 : 'kpt=',kpt(:),' and ng=',ngfft(1:3),ch10,&
613 0 : 'Action : check that kpt lies',&
614 0 : 'reasonably within first Brillouin zone; ',ch10,&
615 0 : 'else code bug, contact ABINIT group.'
616 0 : ABI_BUG(msg)
617 : end if
618 :
619 260098 : gbound(1)=i1min
620 260098 : gbound(2)=i2min
621 260098 : gbound(3)=i3min
622 :
623 : contains
624 :
625 477664126 : function dsq(i1,i2,i3,gmet,kpt)
626 :
627 : integer :: i1,i2,i3
628 : real(dp) :: dsq
629 : real(dp) :: kpt(3),gmet(3,3)
630 :
631 : dsq=gmet(1,1)*(kpt(1)+dble(i1))**2&
632 : & +gmet(2,2)*(kpt(2)+dble(i2))**2&
633 : & +gmet(3,3)*(kpt(3)+dble(i3))**2&
634 : & +2._dp*(gmet(1,2)*(kpt(1)+dble(i1))*(kpt(2)+dble(i2))&
635 : & +gmet(2,3)*(kpt(2)+dble(i2))*(kpt(3)+dble(i3))&
636 477664126 : & +gmet(3,1)*(kpt(3)+dble(i3))*(kpt(1)+dble(i1)))
637 477664126 : end function dsq
638 :
639 : end subroutine bound
640 : !!***
641 :
642 : !!****f* m_fftcore/getng
643 : !! NAME
644 : !! getng
645 : !!
646 : !! FUNCTION
647 : !! From ecut and metric tensor in reciprocal space, computes recommended ngfft(1:3)
648 : !! Also computes the recommended value of nfft and mgfft
649 : !! Pay attention that the FFT grid must be compatible with the symmetry operations (see irrzg.f).
650 : !!
651 : !! INPUTS
652 : !! boxcutmin=minimum value of boxcut admitted (boxcut is the ratio
653 : !! between the radius of the sphere contained in the FFT box, and the
654 : !! radius of the planewave sphere): usually 2.0.
655 : !! chksymtnons= if==3, will impose the FFT grid to be invariant under the spatial symmetries.
656 : !! ecut=energy cutoff in Hartrees
657 : !! gmet(3,3)=reciprocal space metric (bohr**-2).
658 : !! kpt(3)=input k vector in terms of reciprocal lattice primitive translations
659 : !! me_fft=index of the processor in the FFT set (use 0 if sequential)
660 : !! nproc_fft=number of processors in the FFT set (use 1 if sequential)
661 : !! nsym=number of symmetry elements in group
662 : !! paral_fft=0 if no FFT parallelisation; 1 if FFT parallelisation
663 : !! symrel(3,3,nsym)=symmetry matrices in real space (integers)
664 : !! tnons(3,nsym)=nonsymmorphic translations associated to symrel
665 : !!
666 : !! OUTPUT
667 : !! mgfft= max(ngfft(1),ngfft(2),ngfft(3))
668 : !! nfft=number of points in the FFT box=ngfft(1)*ngfft(2)*ngfft(3)/nproc_fft
669 : !!
670 : !! SIDE EFFECTS
671 : !! Input/Output
672 : !! ngfft(1:18)=integer array with FFT box dimensions and other information on FFTs.
673 : !! On input ngfft(1:3) contains optional trial values. If ngfft(1:3)/minbox is greater than value
674 : !! calculated to avoid wrap-around error and ngfft obeys constraint placed by the FFT routine that is used
675 : !! then ngfft(1:3) is left unchanged. Otherwise set to value computed in now.
676 : !!
677 : !! Note that there is the possibility of an undetected error if we
678 : !! are dealing with a cubic unit cell and ngfft(1), ngfft(2) and ngfft(3)
679 : !! are different. In the future we should handle this case.
680 : !!
681 : !! ngfft(4),ngfft(5),ngfft(6)= modified values to avoid cache trashing,
682 : !! presently: ngfft(4)=ngfft(1)+1 if ngfft(1) is even;
683 : !! ngfft(5)=ngfft(2)+1 if ngfft(2) is even.
684 : !! in the other cases, ngfft(4:6)=ngfft(1:3).
685 : !! Other choices may better, but this is left for the future.
686 : !! ngfft(7)=choice for FFT algorithm, see the input variable fftalg
687 : !! ngfft(8)=size of the cache, in bytes (not used here presently).!!
688 : !! other ngfft slots are used for parallelism see ~abinit/doc/variables/vargs.htm#ngfft
689 : !! [ngfftc(1:18)]= -optional- value of ngfft for the "coarse" grid
690 : !! [unit] = -optional- output unit number (DEFAULT std_out)
691 : !! [gpu_option] = GPU implementation to use, i.e. cuda, openMP, ... (0=not using GPU)
692 : !!
693 : !! SOURCE
694 :
695 8392 : subroutine getng(boxcutmin, chksymtnons, ecut, gmet, kpt, me_fft, mgfft, nfft, ngfft, &
696 8392 : nproc_fft, nsym, paral_fft, symrel, tnons, &
697 : ngfftc, unit, gpu_option) ! optional
698 :
699 : use defs_fftdata, only : mg
700 :
701 : !Arguments ------------------------------------
702 : !scalars
703 : integer,intent(in) :: chksymtnons,me_fft,nproc_fft,nsym,paral_fft
704 : integer,intent(out) :: mgfft,nfft
705 : integer,optional,intent(in) :: unit,gpu_option
706 : real(dp),intent(in) :: boxcutmin,ecut
707 : !arrays
708 : integer,intent(in) :: symrel(3,3,nsym)
709 : integer,intent(in),optional :: ngfftc(3)
710 : integer,intent(inout) :: ngfft(18)
711 : real(dp),intent(in) :: gmet(3,3),kpt(3)
712 : real(dp),intent(in) :: tnons(3,nsym)
713 :
714 : !Local variables-------------------------------
715 : !scalars
716 : integer,save :: first=1,msrch(3),previous_paral_mode=0
717 : integer :: element,ifactor,ii,index,ipower,isrch,isrch1,isrch2,isrch3,isym,jj,mu,paral_fft_
718 : integer :: plane,testok,tobechecked,ount,fftalga,nn,ngdiv,valpow
719 : real(dp),parameter :: minbox=0.75_dp
720 : real(dp) :: dsqmax,dsqmin,ecutmx,prodcurrent,prodtrial,tnscaled,xx,yy
721 : logical :: testdiv
722 : character(len=500) :: msg
723 : integer,parameter :: largest_ngfft=mg ! Goedecker FFT: any powers of 2, 3, and 5 - must be coherent with defs_fftdata.F90
724 : integer,parameter :: maxpow2 =16 ! int(log(largest_ngfft+half)/log(two))
725 : integer,parameter :: maxpow3 =6 ! int(log(largest_ngfft+half)/log(three))
726 : integer,parameter :: maxpow5 =6 ! int(log(largest_ngfft+half)/log(five))
727 : !#if defined HAVE_FFTW3 || defined HAVE_DFTI
728 : !#ifdef _GMATTEO_WHISH_LIST
729 : #if 0
730 : integer,parameter :: maxpow7 =5 ! FFTW3 and DFTI support powers of 7 and 11
731 : integer,parameter :: maxpow11=4
732 : #else
733 : integer,parameter :: maxpow7 =0
734 : integer,parameter :: maxpow11=0
735 : #endif
736 : integer,parameter :: mmsrch=(maxpow2+1)*(maxpow3+1)*(maxpow5+1)*(maxpow7+1)*(maxpow11+1)
737 : integer,parameter :: nfactor=10, mpower=5
738 : !Arrays
739 : integer,save :: iperm(mmsrch),srch(mmsrch,3)
740 : integer(i8b) :: li_srch(mmsrch)
741 : integer :: divisor(3,3),gbound(3),imax(3),imin(3),ngcurrent(3)
742 : integer :: ngmax(3),ngsav(3),ngtrial(3)
743 : integer :: npower(3,mpower)
744 : integer,parameter :: factor(10) = (/1,2,3,4,5,6,8,9,10,12/)
745 : integer,parameter :: power(5) = (/2,3,5,7,11/)
746 : ! *************************************************************************
747 :
748 8392 : ount = std_out; if (present(unit)) ount = unit
749 :
750 : !write(std_out,*)' m_fftcore/getng : enter'
751 :
752 8392 : fftalga = ngfft(7)/100
753 :
754 : !If not yet done, compute recommended (boxcut>=2) fft grid dimensions
755 : !In case we switch for paral to sequential mode, recompute srch.
756 : !This is the case e.g. when computing ngfftdiel in sequential mode
757 : !after an initial computation of ngfft in parallel
758 :
759 8392 : paral_fft_=paral_fft;if (nproc_fft==0) paral_fft_=0
760 :
761 8392 : if(first==1.or.paral_fft_ /= previous_paral_mode) then
762 2114 : first=0; previous_paral_mode=paral_fft_
763 2114 : srch(:,:)=0
764 :
765 : ! Factors of 2
766 2114 : srch(1,1)=1
767 35938 : do ii=1,maxpow2
768 35938 : srch(ii+1,1)=srch(ii,1)*2
769 : end do
770 :
771 : ! Factors of 3
772 14798 : index=maxpow2+1
773 : if(maxpow3>0)then
774 14798 : do ii=1,max(1,maxpow3)
775 446054 : srch(1+ii*index:(ii+1)*index,1)=3*srch(1+(ii-1)*index:ii*index,1)
776 : end do
777 : end if
778 :
779 : ! Factors of 5
780 14798 : index=(maxpow3+1)*index
781 : if(maxpow5>0)then
782 14798 : do ii=1,max(1,maxpow5)
783 12684 : li_srch = 0
784 1522080 : li_srch(1+ii*index:(ii+1)*index)=5_i8b*srch(1+(ii-1)*index:ii*index,1)
785 10578456 : where (li_srch > huge(maxpow3)) li_srch = huge(maxpow3)
786 1524194 : srch(1+ii*index:(ii+1)*index,1)=li_srch(1+ii*index:(ii+1)*index)
787 : end do
788 : end if
789 :
790 : ! Factors of 7
791 : index=(maxpow5+1)*index
792 : if(maxpow7>0)then
793 : do ii=1,max(1,maxpow7)
794 : srch(1+ii*index:(ii+1)*index,1)=7*srch(1+(ii-1)*index:ii*index,1)
795 : end do
796 : end if
797 :
798 : ! Factors of 11
799 2114 : index=(maxpow7+1)*index
800 : if(maxpow11>0)then
801 : do ii=1,max(1,maxpow11)
802 : srch(1+ii*index:(ii+1)*index,1)=11*srch(1+(ii-1)*index:ii*index,1)
803 : end do
804 : end if
805 :
806 2114 : call sort_int(mmsrch,srch(:,1),iperm)
807 :
808 566552 : do ii=1,mmsrch
809 566552 : if(srch(ii,1)>largest_ngfft)exit
810 : end do
811 2114 : msrch(1)=ii-1
812 :
813 : ! In case of FFT parallelism, one need ngfft(2) and ngfft(3) to be multiple of nproc_fft
814 2114 : if(paral_fft_==1)then
815 1447 : msrch(2)=0
816 387796 : do ii=1,msrch(1)
817 387796 : if(modulo(srch(ii,1),nproc_fft)==0) then
818 384129 : msrch(2)=msrch(2)+1
819 384129 : srch(msrch(2),2)=srch(ii,1)
820 : end if
821 : end do
822 : !write(msg,'(a,i0,a,i0,2a,i0)')&
823 : ! 'The second and third dimension of the FFT grid: ',ngfft(2),", ",ngfft(3),ch10,&
824 : ! 'were imposed to be multiple of the number of processors for the FFT: ', nproc_fft
825 : !if (ount /= dev_null) ABI_COMMENT(msg)
826 : else
827 667 : msrch(2)=msrch(1)
828 556278 : srch(:,2)=srch(:,1)
829 : end if
830 :
831 : ! The second and third search list have the same constraint
832 2114 : msrch(3)=msrch(2)
833 1769354 : srch(:,3)=srch(:,2)
834 :
835 : ! The set of allowed ngfft values has been found
836 : end if ! first==1
837 :
838 : !=============================================================================================
839 : !
840 : ! Determination of sufficient values of ngfft with ngfft(2) and ngfft(3) taken inside
841 : ! sets of values that take into account the constraint on nproc_fft
842 :
843 : !Save input values of ngfft
844 33568 : ngsav(1:3) = ngfft(1:3)
845 :
846 : !As an initial guess for ngfft, use the provided coarse mesh grid
847 8392 : if (PRESENT(ngfftc)) then
848 4720 : ngfft(1:3)=ngfftc(1:3)
849 1180 : call wrtout(ount,' Using supplied coarse mesh as initial guess.')
850 : else
851 28848 : ngfft(1:3)=2
852 : end if
853 :
854 : !Enlarge the initial guess until the set of ngfft entirely comprises the sphere
855 240728 : do
856 :
857 240728 : call bound(dsqmax,dsqmin,gbound,gmet,kpt,ngfft,plane)
858 :
859 : ! Exit the infinite do-loop if the sphere is inside the FFT box
860 240728 : if (dsqmin>=(half*boxcutmin**2*ecut/pi**2)) exit
861 :
862 : ! Fix nearest boundary
863 1902558 : do ii=1,msrch(plane)-1
864 1894166 : if (srch(ii,plane)>=ngfft(plane)) then
865 : ! redefine ngfft(plane) to next higher choice
866 232336 : ngfft(plane)=srch(ii+1,plane)
867 232336 : exit ! Exit the loop over ii
868 : end if
869 :
870 1661830 : if (ii==msrch(plane)-1)then
871 : ! Here, we are in trouble
872 : write(msg, '(a,i12,5a)' ) &
873 0 : 'ngfft is bigger than allowed value =',ngfft(plane),'.',ch10,&
874 0 : 'This indicates that desired ngfft is larger than getng',ch10,&
875 0 : 'can handle. The code has to be changed and compiled.'
876 0 : ABI_BUG(msg)
877 : end if
878 : end do
879 :
880 : end do ! End of the infinite do-loop : will either "exit", or abort
881 :
882 : !ecutmx=maximum ecut consistent with chosen ngfft
883 8392 : ecutmx=0.5_dp*pi**2*dsqmin
884 :
885 : !Print results
886 : write(msg, '(a,1p,e14.6,a,3i8,a,a,e14.6)' ) &
887 8392 : ' For input ecut=',ecut,' best grid ngfft=',ngfft(1:3),ch10,&
888 16784 : ' max ecut=',ecutmx
889 8392 : call wrtout(ount,msg)
890 :
891 : ! The FFT grid is compatible with the symmetries if for each
892 : ! symmetry isym, each ii and each jj, the quantity
893 : ! (ngfft(jj)*symrel(jj,ii,isym))/ngfft(ii) is an integer.
894 : ! This relation is immediately verified for diagonal elements, since
895 : ! symrel is an integer. It is also verified if symrel(ii,jj,isym) is zero.
896 : ! Moreover, to cope with the non-symmorphic translation vectors, at least the
897 : ! origin must be sent to a point of the FFT grid. Hence, the non-symmorphic
898 : ! translations tnons(i) multiplied by ngfft(i) must be an integer.
899 : ! The latter condition is however imposed only when chksymtnons=3.
900 : ! Indeed, ABINIT will be able to reimpose the symmetry at the level of the density and potential.
901 : ! This might be a problem for GW calculations, though ...
902 :
903 : !Compute the biggest (positive) common divisor of each off-diagonal element of the symmetry matrices
904 8392 : divisor(:,:)=0; tobechecked=0
905 :
906 33568 : do ii=1,3
907 109096 : do jj=1,3
908 75528 : if(jj==ii)cycle
909 1249710 : do isym=1,nsym
910 1174182 : if(symrel(jj,ii,isym)==0 .or. divisor(jj,ii)==1 )cycle
911 30701 : tobechecked=1
912 30701 : element=abs(symrel(jj,ii,isym))
913 30701 : testdiv= ( divisor(jj,ii)==0 .or. divisor(jj,ii)==element .or. element==1)
914 75528 : if(testdiv)then
915 30701 : divisor(jj,ii)=element
916 : else
917 : ! Must evaluate common divisor between non-trivial numbers
918 : do
919 0 : if(divisor(jj,ii)<element)element=element-divisor(jj,ii)
920 0 : if(divisor(jj,ii)>element)divisor(jj,ii)=divisor(jj,ii)-element
921 1143481 : if(divisor(jj,ii)==element)exit
922 : end do
923 : end if
924 : end do
925 : end do
926 : end do
927 :
928 : !Check whether there is a problem: the grid must be invariant
929 : !with respect to point symmetry operations, and spatial symmetry operations if chksymtnons==3
930 8392 : testok=1
931 8392 : if(tobechecked==1)then
932 24512 : do ii=1,3
933 73536 : do jj=1,3
934 55152 : xx=divisor(jj,ii)*ngfft(jj)
935 55152 : yy=xx/ngfft(ii)
936 73536 : if(abs(yy-nint(yy))>tol8)testok=0
937 : end do
938 24512 : if(chksymtnons==3)then
939 5877 : do isym=1,nsym
940 5682 : tnscaled=tnons(ii,isym)*ngfft(ii)
941 5877 : if(abs(tnscaled-nint(tnscaled))>tol8)testok=0
942 : enddo
943 : endif
944 : end do
945 : end if
946 :
947 : !DEBUG
948 : !write(std_out,*)' m_fftcore/getng : chksymtnons,testok,nproc_fft=',chksymtnons,testok,nproc_fft
949 : !ENDDEBUG
950 :
951 : !If there is a problem
952 6128 : if(testok==0)then
953 : ! Find the powers of 2, 3, 5 (possibly 7 and 11) that are needed or will be enough in ngfft,
954 : ! taking both the constraint on nproc_nfft and the constraint on tnons.
955 : ! First decompose nproc_fft, providing divisors of ngfft(2:3)
956 88 : nn=nproc_fft
957 88 : npower(:,:)=0
958 528 : do ipower=1,mpower
959 440 : valpow=power(ipower)
960 528 : do while (mod(nn,valpow)==0)
961 0 : nn=nn/valpow
962 0 : npower(3,ipower)=npower(3,ipower)+1
963 : end do
964 : enddo
965 88 : if(nn/=1)then
966 0 : ABI_ERROR(sjoin("nproc_fft: ", itoa(nproc_fft), "is not a multiple of 2, 3, 5, 7 or 11"))
967 : endif
968 528 : npower(2,:)=npower(3,:)
969 :
970 : ! Then examine tnons
971 88 : if(chksymtnons==3)then
972 56 : do ii=1,3
973 90 : do ifactor=1,nfactor
974 90 : testok=1
975 2322 : do isym=1,nsym
976 2232 : tnscaled=factor(ifactor)*tnons(ii,isym)
977 2322 : if(abs(tnscaled-nint(tnscaled))>tol8)testok=0
978 : enddo
979 90 : if(testok==1)exit
980 : enddo
981 56 : if(testok==1)then
982 42 : if(ifactor/=1)then
983 36 : if(ifactor==2)npower(ii,1)=max(npower(ii,1),1) ! At least one power of 2
984 36 : if(ifactor==3)npower(ii,2)=max(npower(ii,2),1) ! At least one power of 3
985 36 : if(ifactor==4)npower(ii,1)=max(npower(ii,1),2) ! At least two powers of 2
986 36 : if(ifactor==5)npower(ii,3)=max(npower(ii,3),1) ! At least one power of 5
987 36 : if(ifactor==6)then
988 2 : npower(ii,1)=max(npower(ii,1),1) ! At least one power of 2
989 2 : npower(ii,2)=max(npower(ii,2),1) ! At least one power of 3
990 : endif
991 36 : if(ifactor==7)npower(ii,1)=max(npower(ii,1),3) ! At least three powers of 2
992 36 : if(ifactor==8)npower(ii,2)=max(npower(ii,2),2) ! At least two powers of 3
993 36 : if(ifactor==9)then
994 0 : npower(ii,1)=max(npower(ii,1),1) ! At least one power of 2
995 0 : npower(ii,3)=max(npower(ii,3),1) ! At least one power of 5
996 : end if
997 36 : if(ifactor==10)then
998 0 : npower(ii,1)=max(npower(ii,1),2) ! At least two powers of 2
999 0 : npower(ii,2)=max(npower(ii,2),1) ! At least one power of 3
1000 : end if
1001 : endif
1002 : else
1003 : write(msg, '(5a,i12,2a,9i12,2a,3f10.7,2a)' ) &
1004 0 : 'Chksymtnons=1 . Found potentially symmetry-breaking value of tnons, ', ch10,&
1005 0 : ' which is neither a rational fraction in 1/8th nor in 1/12th (1/9th and 1/10th are tolerated also) :', ch10,&
1006 0 : ' for the symmetry number ',isym,ch10,&
1007 0 : ' symrel is ',symrel(1:3,1:3,isym),ch10,&
1008 0 : ' tnons is ',tnons(1:3,isym),ch10,&
1009 0 : 'This problem should have been caught earlier.'
1010 0 : ABI_BUG(msg)
1011 : endif
1012 : enddo ! ii
1013 : endif ! chksymtnons
1014 :
1015 : ! Get minimal search indices, simply those of the current ngfft
1016 352 : do ii=1,3
1017 70840 : do isrch=1,msrch(ii)
1018 70488 : index=srch(isrch,ii)
1019 70752 : if(index==ngfft(ii))imin(ii)=isrch
1020 : end do
1021 : end do
1022 :
1023 : ! Get maximal search indices : the ngtrial values must be identical (to fulfill the constraint induced by the
1024 : ! off diagonal elements of symrel), but also must contain sufficient powers of basic primes (2, 3, 5, 7, 11),
1025 : ! and be bigger than all current ngfft components. This should guarantee that such a triplet fulfills all constraints.
1026 : ! Determine the divisor of allowed ngmax
1027 : ngdiv=1
1028 528 : do ipower=1,mpower
1029 1848 : ngdiv=ngdiv*power(ipower)**(maxval(npower(:,ipower)))
1030 : enddo
1031 352 : ngmax(1)=ngdiv*(maxval(ngfft(1:3)-1)/ngdiv+1)
1032 352 : ngmax(1:3)=ngmax(1)
1033 352 : do ii=1,3
1034 3847 : do isrch=1,msrch(ii)
1035 3759 : index=srch(isrch,ii)
1036 3759 : if(mod(index,ngdiv)==0 .and. index>=ngmax(ii))then
1037 264 : imax(ii)=isrch
1038 264 : ngmax(ii)=index
1039 264 : exit
1040 : endif
1041 : end do
1042 : end do
1043 : ! This gives a tentative symmetric triplet
1044 : ngcurrent(1:3)=ngmax(1:3)
1045 88 : prodcurrent=ngmax(1)*ngmax(2)*ngmax(3)+1.0d-3
1046 : ! However, it is perhaps possible to do better, by asymmetric triplets, still giving lower prodcurrent !
1047 88 : ngmax(1)=min(int(prodcurrent/(ngfft(2)*ngfft(3))),srch(msrch(1),1))
1048 88 : ngmax(2)=min(int(prodcurrent/(ngfft(1)*ngfft(3))),srch(msrch(2),2))
1049 88 : ngmax(3)=min(int(prodcurrent/(ngfft(1)*ngfft(2))),srch(msrch(3),3))
1050 352 : do ii=1,3
1051 70840 : do isrch=1,msrch(ii)
1052 70488 : index=srch(isrch,ii)
1053 : ! One cannot suppose that ngmax belongs to the allowed list,
1054 : ! so must use <= instead of == , to determine largest index
1055 70752 : if(index<=ngmax(ii))imax(ii)=isrch
1056 : end do
1057 : end do
1058 :
1059 : !write(std_out,*)' ngmin(1:3)=',srch(imin(1),1),srch(imin(2),2),srch(imin(3),3)
1060 : !write(std_out,*)' ngmax(1:3)=',ngmax(1:3)
1061 :
1062 88 : ngcurrent(1:3)=ngmax(1:3)
1063 88 : prodcurrent=ngmax(1)*ngmax(2)*ngmax(3)+1.0d-3
1064 :
1065 : ! Now, start brute force search
1066 968 : do isrch1=imin(1),imax(1)
1067 880 : ngtrial(1)=srch(isrch1,1)
1068 16009 : do isrch2=imin(2),imax(2)
1069 15041 : ngtrial(2)=srch(isrch2,2)
1070 130881 : do isrch3=imin(3),imax(3)
1071 128354 : ngtrial(3)=srch(isrch3,3)
1072 128354 : prodtrial=real(ngtrial(1))*real(ngtrial(2))*real(ngtrial(3))+1.0d-3
1073 128354 : if(prodtrial>prodcurrent-1.0d-4)exit
1074 : ! The trial product is lower or equal to the current product,
1075 : ! so now, checks whether the symmetry constraints are OK
1076 : testok=1
1077 459840 : do ii=1,3
1078 1379520 : do jj=1,3
1079 1034640 : xx=divisor(jj,ii)*ngtrial(jj)
1080 1034640 : yy=xx/ngtrial(ii)
1081 1379520 : if(abs(yy-nint(yy))>tol8)testok=0
1082 : end do
1083 459840 : if(chksymtnons==3)then
1084 12828 : do isym=1,nsym
1085 12240 : tnscaled=tnons(ii,isym)*ngtrial(ii)
1086 12828 : if(abs(tnscaled-nint(tnscaled))>tol8)testok=0
1087 : enddo
1088 : endif
1089 : end do
1090 : ! DEBUG
1091 : ! write(ount,'(a,3i6,a,i3,a,es16.6)' )' getng : current trial triplet',ngtrial(1:3),&
1092 : ! & ' testok=',testok,' prodtrial=',prodtrial
1093 : ! ENDDEBUG
1094 114960 : if(testok==0)cycle
1095 : ! When one arrives here, the symmetry constraints are fulfilled, so update current values
1096 : ! Then continues the search, in hope of a better value.
1097 92 : ngcurrent(1:3)=ngtrial(1:3)
1098 130001 : prodcurrent=prodtrial
1099 : end do
1100 : end do
1101 : end do
1102 :
1103 352 : ngfft(1:3)=ngcurrent(1:3)
1104 88 : call bound(dsqmax,dsqmin,gbound,gmet,kpt,ngfft,plane)
1105 : ! ecutmx=maximum ecut consistent with chosen ngfft
1106 88 : ecutmx=0.5_dp*pi**2*dsqmin
1107 : ! Give results
1108 : write(msg, '(a,3i8,a,a,e14.6)' ) &
1109 88 : ' However, must be changed due to symmetry =>',ngfft(1:3),ch10,&
1110 176 : ' with max ecut=',ecutmx
1111 88 : call wrtout(ount,msg)
1112 :
1113 88 : if (prodcurrent>huge(ii)) then
1114 : write(msg, '(5a)' )&
1115 0 : 'The best FFT grid will lead to indices larger',ch10,&
1116 0 : 'than the largest representable integer on this machine.',ch10,&
1117 0 : 'Action: try to deal with smaller problems. Also contact ABINIT group.'
1118 0 : ABI_ERROR(msg)
1119 : end if
1120 :
1121 : end if ! testok==0
1122 :
1123 : !Possibly use the input values of ngfft
1124 : if (int( dble(ngsav(1)) / minbox ) >= ngfft(1) .and.&
1125 8392 : int( dble(ngsav(2)) / minbox ) >= ngfft(2) .and.&
1126 : int( dble(ngsav(3)) / minbox ) >= ngfft(3) ) then
1127 :
1128 : ! Must check whether the values are in the allowed list
1129 586 : testok=0
1130 2344 : do mu=1,3
1131 23339 : do ii=1,msrch(mu)
1132 22753 : if(srch(ii,mu)==ngsav(mu))then
1133 1758 : testok=testok+1
1134 1758 : exit
1135 : end if
1136 : end do
1137 : end do
1138 586 : if(testok==3)then
1139 586 : write(msg,'(a,3(a,i1,a,i3),a)') ' input values of',&
1140 2930 : (' ngfft(',mu,') =',ngsav(mu),mu=1,3),' are alright and will be used'
1141 586 : call wrtout(ount,msg)
1142 2344 : do mu = 1,3
1143 2344 : ngfft(mu) = ngsav(mu)
1144 : end do
1145 : end if
1146 :
1147 : end if
1148 :
1149 : !mgfft needs to be set to the maximum of ngfft(1),ngfft(2),ngfft(3)
1150 33568 : mgfft = maxval(ngfft(1:3))
1151 :
1152 8392 : if (paral_fft_==1) then
1153 : ! For the time being, one need ngfft(2) and ngfft(3) to be multiple of nproc_fft
1154 6677 : if(modulo(ngfft(2),nproc_fft)/=0)then
1155 : write(msg,'(4a,i5,a,i5)')&
1156 0 : 'The second dimension of the FFT grid, ngfft(2), should be ',&
1157 0 : 'a multiple of the number of processors for the FFT, nproc_fft.',ch10,&
1158 0 : 'However, ngfft(2)=',ngfft(2),' and nproc_fft=',nproc_fft
1159 0 : ABI_BUG(msg)
1160 : end if
1161 6677 : if(modulo(ngfft(3),nproc_fft)/=0)then
1162 : write(msg,'(4a,i5,a,i5)')&
1163 0 : 'The third dimension of the FFT grid, ngfft(3), should be ',&
1164 0 : 'a multiple of the number of processors for the FFT, nproc_fft.',ch10,&
1165 0 : 'However, ngfft(3)=',ngfft(3),' and nproc_fft=',nproc_fft
1166 0 : ABI_BUG(msg)
1167 : end if
1168 :
1169 1715 : else if (paral_fft_/=0) then
1170 0 : write(msg,'(a,i0)')'paral_fft_ should be 0 or 1, but its value is ',paral_fft_
1171 0 : ABI_BUG(msg)
1172 : end if
1173 :
1174 : ! Compute effective number of FFT points (for this MPI node if parall FFT)
1175 33568 : nfft=product(ngfft(1:3))/max(1,nproc_fft)
1176 :
1177 : !Set up fft array dimensions ngfft(4,5,6) to avoid cache conflicts
1178 8392 : ngfft(4)=2*(ngfft(1)/2)+1
1179 8392 : ngfft(5)=2*(ngfft(2)/2)+1
1180 8392 : ngfft(6)=ngfft(3)
1181 8392 : if (any(fftalga == [FFT_FFTW3, FFT_DFTI])) then
1182 : ! FFTW3 supports leading dimensions but at the price of a larger number of FFTs
1183 : ! to be executed along z when the zero-padded version is used.
1184 : ! One should check whether the augmentation is beneficial for FFTW3.
1185 : ngfft(4)=2*(ngfft(1)/2)+1
1186 : ngfft(5)=2*(ngfft(2)/2)+1
1187 : !ngfft(4)=ngfft(1)
1188 : !ngfft(5)=ngfft(2)
1189 : ngfft(6)=ngfft(3)
1190 : end if
1191 :
1192 8392 : if (present(gpu_option)) then
1193 8384 : if (gpu_option/=ABI_GPU_DISABLED) then
1194 0 : ngfft(4)=ngfft(1)
1195 0 : ngfft(5)=ngfft(2)
1196 0 : ngfft(6)=ngfft(3)
1197 : end if
1198 : end if
1199 :
1200 50352 : ngfft(14:18)=0 ! ngfft(14) to be filled outside of getng
1201 :
1202 8392 : if (paral_fft_==0) then
1203 1715 : ngfft(9)=0 ! paral_fft_
1204 1715 : ngfft(10)=1 ! nproc_fft
1205 1715 : ngfft(11)=0 ! me_fft
1206 1715 : ngfft(12)=0 ! n2proc
1207 1715 : ngfft(13)=0 ! n3proc
1208 : else
1209 6677 : ngfft(9)=1 ! paral_fft_
1210 6677 : ngfft(10)=nproc_fft
1211 6677 : ngfft(11)=me_fft
1212 6677 : ngfft(12)=ngfft(2)/nproc_fft
1213 6677 : ngfft(13)=ngfft(3)/nproc_fft
1214 : end if
1215 :
1216 16784 : call print_ngfft([ount], ngfft, header="FFT mesh")
1217 :
1218 8392 : end subroutine getng
1219 : !!***
1220 :
1221 : !!****f* m_fftcore/sphereboundary
1222 : !! NAME
1223 : !! sphereboundary
1224 : !!
1225 : !! FUNCTION
1226 : !! Finds the boundary of the basis sphere of G vectors (at a given
1227 : !! k point) for use in improved zero padding of ffts in 3 dimensions.
1228 : !! Provides data to be used by subroutine fourwf, in the form of
1229 : !! an array gbound(2*mgfft+8,2).
1230 : !!
1231 : !! The first component (for use when mod(fftalg,10)==2))
1232 : !! provides integer values g1min,g1max,g2min,g2max
1233 : !! and then for g2 in the
1234 : !! sequence g2=0,1,2,...,g2max,g2min,g2min+1,...,-1, provides g1min, g1max.
1235 : !!
1236 : !! The second component (for use when mod(fftalg,10)==1))
1237 : !! provides integer values g1min,g1max,g3min,g3max,
1238 : !! where g3min and g3max have been corrected in case of time-reversal
1239 : !! and then for g3 in the sequence
1240 : !! g3=0,1,2,...,g3max,g3min,g3min+1,...,-1, provides g2min, g2max.
1241 : !! (also corrected in case of time-reversal)
1242 : !!
1243 : !! These values are stored in the above order in array gbound.
1244 : !! Debug mode, if fftalg is between 000 and 099
1245 : !!
1246 : !! INPUTS
1247 : !! istwf_k=option parameter that describes the storage of wfs
1248 : !! kg_k(3,npw)=integer coordinates of G vectors in basis sphere
1249 : !! mgfft=maximum size of 1D FFTs (only for dimensioning purposes)
1250 : !! npw=number of G vectors in basis at this k point
1251 : !!
1252 : !! OUTPUT
1253 : !! gbound(2*mgfft+8,2)=defined above
1254 : !!
1255 : !! SOURCE
1256 :
1257 3264335 : subroutine sphereboundary(gbound, istwf_k, kg_k, mgfft, npw)
1258 :
1259 : !Arguments ------------------------------------
1260 : !scalars
1261 : integer,intent(in) :: istwf_k,mgfft,npw
1262 : !arrays
1263 : integer,intent(in) :: kg_k(3,npw)
1264 : integer,intent(out) :: gbound(2*mgfft+8,2)
1265 :
1266 : !Local variables-------------------------------
1267 : !scalars
1268 : integer :: dim_a,dim_b,fftalgc,g_a,gmax_a,gmax_b,gmax_b1,gmax_b2,gmin_a,gmin_b
1269 : integer :: gmin_b1,gmin_b2,igb,ii,iloop,ipw,testm,testp,kgk
1270 : character(len=500) :: msg
1271 : !arrays
1272 : integer :: gmax(2),gmin(2)
1273 : ! *************************************************************************
1274 : !
1275 : !DEBUG
1276 : !write(std_out,*)' sphereboundary : enter'
1277 : !write(std_out, '(a)' )' sphereboundary : list of plane waves coordinates for k point '
1278 : !write(std_out, '(a)' )' ipw kg_k(1:3,ipw) '
1279 : !do ipw=1,npw
1280 : !write(std_out, '(i10,a,3i6)' )ipw,' ',kg_k(1:3,ipw)
1281 : !end do
1282 : !gbound=-999
1283 : !ENDDEBUG
1284 :
1285 : !Determine cube boundaries
1286 609460001 : gbound(1,1)=minval(kg_k(1,:))
1287 609460001 : gbound(2,1)=maxval(kg_k(1,:))
1288 9793005 : gbound(1:2,2)=gbound(1:2,1)
1289 :
1290 : !Treat differently the fftalgc cases
1291 9793005 : do ii=1,2
1292 :
1293 6528670 : fftalgc=3-ii
1294 :
1295 6528670 : if(fftalgc/=2)then
1296 : dim_a=3
1297 : dim_b=2
1298 : else
1299 3264335 : dim_a=2
1300 3264335 : dim_b=1
1301 : end if
1302 :
1303 : ! Relevant boundaries
1304 1218920002 : gbound(3,ii)=minval(kg_k(dim_a,:))
1305 1218920002 : gbound(4,ii)=maxval(kg_k(dim_a,:))
1306 6528670 : gmin_a=gbound(3,ii)
1307 6528670 : gmax_a=gbound(4,ii)
1308 :
1309 : ! Must complete the sphere for fftalgc==1 and special storage modes.
1310 : ! Explanation : sg_fftpad is not able to take into account
1311 : ! the time-reversal symmetry, so that the boundaries will not be delimited
1312 : ! by the kg_k set, but by their symmetric also.
1313 6528670 : if(istwf_k>=2 .and. fftalgc==1)then
1314 30755 : if( istwf_k==2 .or. istwf_k==3 .or. istwf_k==6 .or. istwf_k==7 )then
1315 24884 : gbound(4,2)=max(gmax_a,-gmin_a)
1316 24884 : gbound(3,2)=-gbound(4,2)
1317 5871 : else if( istwf_k==4 .or. istwf_k==5 .or. istwf_k==8 .or. istwf_k==9 )then
1318 5871 : gbound(4,2)=max(gmax_a,-gmin_a-1)
1319 5871 : gbound(3,2)=-gbound(4,2)-1
1320 : end if
1321 30755 : gmax_a=gbound(4,2) ; gmin_a=gbound(3,2)
1322 : end if
1323 :
1324 6528670 : igb=5
1325 :
1326 : ! Consider first every g_a in range 0 ... gmax_a, then gmin_a ... -1
1327 6528670 : gmin(1)=0 ; gmax(1)=gmax_a
1328 6528670 : gmin(2)=gmin_a ; gmax(2)=-1
1329 :
1330 22850345 : do iloop=1,2
1331 :
1332 19586010 : if( gmin(iloop) <= gmax(iloop) )then
1333 :
1334 58322884 : do g_a=gmin(iloop),gmax(iloop)
1335 :
1336 45306510 : if(istwf_k==1 .or. fftalgc/=1)then
1337 : ! Select the minimal and maximal values, in the selected plane
1338 44950196 : gmin_b=mgfft+1 ! Initialized with a value larger than all possible ones
1339 44950196 : gmax_b=-mgfft-1 ! Initialized with a value smaller than all possible ones
1340 13419018168 : do ipw=1,npw
1341 13419018168 : if(kg_k(dim_a,ipw)==g_a)then
1342 1189933933 : kgk=kg_k(dim_b,ipw)
1343 1189933933 : if(kgk<=gmin_b)gmin_b=kgk
1344 1189933933 : if(kgk>=gmax_b)gmax_b=kgk
1345 : end if
1346 : end do
1347 :
1348 356314 : else if(istwf_k>=2 .and. fftalgc==1)then
1349 :
1350 : ! Here, must take into account time-reversal symmetry explicitly
1351 :
1352 : ! Determine the boundaries for the plane g_a
1353 356314 : testp=0
1354 356314 : if(g_a<=gmax_a)then
1355 : ! Select the minimal and maximal values, in the selected plane
1356 356314 : gmin_b1=mgfft+1 ! Initialized with a value larger than all possible ones
1357 356314 : gmax_b1=-mgfft-1 ! Initialized with a value smaller than all possible ones
1358 642690710 : do ipw=1,npw
1359 642690710 : if(kg_k(dim_a,ipw)==g_a)then
1360 22457399 : kgk=kg_k(dim_b,ipw)
1361 22457399 : if(kgk<=gmin_b1)gmin_b1=kgk
1362 22457399 : if(kgk>=gmax_b1)gmax_b1=kgk
1363 : end if
1364 : end do
1365 :
1366 :
1367 : testp=1
1368 : end if
1369 :
1370 : ! Determine the boundaries for the plane -g_a or -g_a-1
1371 356314 : testm=0
1372 356314 : if( istwf_k==2 .or. istwf_k==3 .or. istwf_k==6 .or. istwf_k==7 )then
1373 :
1374 288530 : if(-g_a>=gmin_a)then
1375 : ! Select the minimal and maximal values, in the selected plane
1376 : ! Warning : there is an inversion of search (might be confusing)
1377 288530 : gmax_b2=mgfft+1 ! Initialized with a value larger than all possible ones
1378 288530 : gmin_b2=-mgfft-1 ! Initialized with a value smaller than all possible ones
1379 505047560 : do ipw=1,npw
1380 505047560 : if(kg_k(dim_a,ipw)==-g_a)then
1381 18377624 : kgk=kg_k(dim_b,ipw)
1382 18377624 : if(kgk<=gmax_b2)gmax_b2=kgk
1383 18377624 : if(kgk>=gmin_b2)gmin_b2=kgk
1384 : end if
1385 : end do
1386 : testm=1
1387 : end if
1388 :
1389 67784 : else if( istwf_k==4 .or. istwf_k==5 .or. istwf_k==8 .or. istwf_k==9 )then
1390 :
1391 67784 : if(-g_a-1>=gmin_a)then
1392 : ! Select the minimal and maximal values, in the selected plane
1393 : ! Warning : there is an inversion of search (might be confusing)
1394 67784 : gmax_b2=mgfft+1 ! Initialized with a value larger than all possible ones
1395 67784 : gmin_b2=-mgfft-1 ! Initialized with a value smaller than all possible ones
1396 137643150 : do ipw=1,npw
1397 137643150 : if(kg_k(dim_a,ipw)==-g_a-1)then
1398 4079775 : kgk=kg_k(dim_b,ipw)
1399 4079775 : if(kgk<=gmax_b2)gmax_b2=kgk
1400 4079775 : if(kgk>=gmin_b2)gmin_b2=kgk
1401 : end if
1402 : end do
1403 : testm=1
1404 : end if
1405 :
1406 : end if
1407 :
1408 : ! Must invert the boundaries, to use them for plane g_a
1409 : if(testm==1)then
1410 : ! This is needed to avoid border effect
1411 : ! if the search did not lead to any element
1412 356314 : gmin_b2=max(gmin_b2,-mgfft) ; gmax_b2=min(gmax_b2,mgfft)
1413 356314 : if(istwf_k<=5)then
1414 279544 : gmax_b2=-gmax_b2 ; gmin_b2=-gmin_b2
1415 : else
1416 76770 : gmax_b2=-gmax_b2-1 ; gmin_b2=-gmin_b2-1
1417 : end if
1418 : end if
1419 :
1420 356314 : if( testp==1 .and. testm==1)then
1421 356314 : gmin_b=min(gmin_b1,gmin_b2) ; gmax_b=max(gmax_b1,gmax_b2)
1422 0 : else if( testp==1 )then
1423 : gmin_b=gmin_b1 ; gmax_b=gmax_b1
1424 0 : else if( testm==1 )then
1425 0 : gmin_b=gmin_b2 ; gmax_b=gmax_b2
1426 : end if
1427 :
1428 : end if ! Endif take into account time-reversal symmetry
1429 :
1430 45306510 : if (igb+1>2*mgfft+4) then
1431 : write(msg, '(2a, 4(a,3(i0,1x),a))' )&
1432 0 : "About to overwrite gbound array (FFT mesh too small) ",ch10, &
1433 0 : " iloop, igb, mgb = ",iloop,igb,2*mgfft+4, ch10, &
1434 0 : " istwfk, mgfft, npw = ",istwf_k, mgfft, npw, ch10, &
1435 0 : " minval(kg_k) = ",minval(kg_k, dim=2), ch10, &
1436 0 : " maxval(kg_k) = ",maxval(kg_k, dim=2), ch10
1437 0 : ABI_BUG(msg)
1438 : end if
1439 :
1440 45306510 : gbound(igb,ii)=gmin_b
1441 45306510 : gbound(igb+1,ii)=gmax_b
1442 :
1443 45306510 : if( iloop==1 .and. istwf_k>=2 .and. istwf_k<=5 .and. fftalgc==2 .and. g_a==0)then
1444 : ! If k_y=0 , for fftalgc==2, the g_a==0 plane must be completed
1445 23717 : if(istwf_k==2 .or. istwf_k==4)then
1446 18779 : gbound(igb+1,ii)=max(gmax_b,-gmin_b)
1447 18779 : gbound(igb,ii)=-gbound(igb+1,ii)
1448 4938 : else if(istwf_k==3 .or. istwf_k==5)then
1449 4938 : gbound(igb+1,ii)=max(gmax_b,-gmin_b-1)
1450 4938 : gbound(igb,ii)=-gbound(igb+1,ii)-1
1451 : end if
1452 :
1453 : end if
1454 :
1455 58322884 : igb=igb+2
1456 :
1457 : end do ! g_a
1458 : end if
1459 : end do ! iloop
1460 : end do ! ii (fftalgc)
1461 :
1462 : !DEBUG
1463 : !write(std_out,'(a)')' sphereoundary : list of plane waves coordinates for 1st k point '
1464 : !write(std_out,'(a)')' ipw kg_k(1:3,ipw) '
1465 : !do ipw=1,npw
1466 : !write(std_out, '(i10,a,3i6)' )ipw,' ',kg_k(1:3,ipw)
1467 : !end do
1468 : !write(std_out, '(a)' )' sphereboundary : list of boundaries '
1469 : !do igb=1,2*mgfft+8
1470 : !write(std_out, '(i10,a,2i6)' )igb,' ',gbound(igb,1),gbound(igb,2)
1471 : !end do
1472 : !write(std_out,*)' sphereboundary : exit '
1473 : !ENDDEBUG
1474 :
1475 3264335 : end subroutine sphereboundary
1476 : !!***
1477 :
1478 : !----------------------------------------------------------------------
1479 :
1480 : !!****f* m_fftcore/sphere
1481 : !! NAME
1482 : !! sphere
1483 : !!
1484 : !! FUNCTION
1485 : !! Array cg is defined in sphere with npw g-vectors.
1486 : !! Insert cg inside FFT box of n1*n2*n3 points to define array cfft for
1487 : !! rest of cfft is filled with 0 s.
1488 : !!
1489 : !! iflag=1 ==> insert cg into cfft.
1490 : !! iflag=2 ==> insert cg into cfft, where the second and third dimension
1491 : !! have been switched (needed for new 2002 SGoedecker FFT)
1492 : !! iflag=-1==> extract cg from cfft.
1493 : !! iflag=-2==> extract cg from cfft, where the second and third dimension
1494 : !! have been switched (needed for new 2002 SGoedecker FFT)
1495 : !! WARNING: iflag=-2 cannot use symmetry operations.
1496 : !!
1497 : !! There is also the possibility to apply a symmetry operation,
1498 : !! as well as to make a shift in reciprocal space, or to multiply
1499 : !! by a constant factor, in the case iflag=-1.
1500 : !! Multiplication by a constant factor is also possible in the case iflag=-2.
1501 : !!
1502 : !! INPUTS
1503 : !! cg(2,npw*ndat)= contains values for npw G vectors in basis sphere
1504 : !! ndat=number of wavefunctions
1505 : !! npw=number of G vectors in basis at this k point
1506 : !! cfft(2,n4,n5,n6*ndat) = array in FFT box
1507 : !! n1,n2,n3=physical dimension of the box (cfft)
1508 : !! n4,n5,n6=memory dimension of cfft
1509 : !! kg_k(3,npw)=integer coordinates of G vectors in basis sphere
1510 : !! istwf_k=option parameter that describes the storage of wfs
1511 : !! iflag=option parameter. Possible values: -1, -2, 1, 2
1512 : !! me_g0=1 if this node has G=0.
1513 : !! shiftg(3)=The shift in reciprocal space.
1514 : !! symrec(3,3)=symmetry operation in reciprocal space to be applied (symrec)
1515 : !! xnorm=Normalization factor.
1516 : !!
1517 : !! SIDE EFFECTS
1518 : !! Input/Output
1519 : !! iflag=1 and 2, insert cg(input) into cfft(output)
1520 : !! iflag=-1 and -2, extract cg(output) from cfft(input)
1521 : !!
1522 : !! NOTES
1523 : !! cg and cfft are assumed to be of type COMPLEX, although this routine treats
1524 : !! them as real of twice the length to avoid nonstandard complex*16.
1525 : !! If istwf_k differs from 1, then special storage modes must be taken
1526 : !! into account, for symmetric wavefunctions coming from k=(0 0 0) or other special k points.
1527 : !!
1528 : !! TODO
1529 : !! 1) Order arguments
1530 : !! 2) Split the two cases to avoid breaking intent: from and to sphere (merge with cg_box2gpsh and cg_gsph2box?)
1531 : !! 3) If symmetries are used with or without shiftg, it might happen that the FFT mesh
1532 : !! is not large enough to accommodate the rotated G, in this case one should return ierr /= 0
1533 : !!
1534 : !! SOURCE
1535 :
1536 2549427 : subroutine sphere(cg, ndat, npw, cfft, n1, n2, n3, n4, n5, n6, kg_k, istwf_k, iflag, me_g0, shiftg, symrec, xnorm)
1537 :
1538 : !Arguments ------------------------------------
1539 : !scalars
1540 : integer,intent(in) :: iflag,istwf_k,n1,n2,n3,n4,n5,n6,ndat,npw,me_g0
1541 : real(dp),intent(in) :: xnorm
1542 : !arrays
1543 : integer,intent(in) :: kg_k(3,npw),shiftg(3),symrec(3,3)
1544 : real(dp),intent(inout) :: cfft(2,n4,n5,n6*ndat),cg(2,npw*ndat)
1545 :
1546 : !Local variables-------------------------------
1547 : !scalars
1548 : integer :: i1,i1inv,i2,i2inv,i3,i3inv,id1,id2,id3,idat,ipw
1549 : integer :: j1,j2,j3,l1,l2,l3,npwmin,use_symmetry,i3dat,i3invdat,i2invdat,ipwdat,i2dat
1550 : !character(len=500) :: msg
1551 : !arrays
1552 : integer :: identity(3,3)
1553 5098854 : integer :: i1inver(n1),i2inver(n2),i3inver(n3)
1554 : ! *************************************************************************
1555 :
1556 : DBG_ENTER("COLL")
1557 :
1558 : ! In the case of special k-points, invariant under time-reversal,
1559 : ! but not Gamma, initialize the inverse coordinates.
1560 : ! Remember that:
1561 : !
1562 : ! u_k(G) = u_{k+G0}(G-G0); u_{-k}(G) = u_k(G)^* and therefore:
1563 : ! u_{G0/2}(G) = u_{G0/2}(-G-G0)^*.
1564 :
1565 2549427 : if (istwf_k>=2) then
1566 54202 : if(istwf_k==2 .or. istwf_k==4 .or. istwf_k==6 .or. istwf_k==8)then
1567 21567 : i1inver(1)=1
1568 207639 : do i1=2,n1
1569 207639 : i1inver(i1)=n1+2-i1
1570 : end do
1571 : else
1572 344318 : do i1=1,n1
1573 344318 : i1inver(i1)=n1+1-i1
1574 : end do
1575 : end if
1576 54202 : if(istwf_k>=2 .and. istwf_k<=5)then
1577 34537 : i2inver(1)=1
1578 309049 : do i2=2,n2
1579 309049 : i2inver(i2)=n2+2-i2
1580 : end do
1581 : else
1582 216898 : do i2=1,n2
1583 216898 : i2inver(i2)=n2+1-i2
1584 : end do
1585 : end if
1586 54202 : if(istwf_k==2 .or. istwf_k==3 .or. istwf_k==6 .or. istwf_k==7)then
1587 35558 : i3inver(1)=1
1588 380351 : do i3=2,n3
1589 380351 : i3inver(i3)=n3+2-i3
1590 : end do
1591 : else
1592 236819 : do i3=1,n3
1593 236819 : i3inver(i3)=n3+1-i3
1594 : end do
1595 : end if
1596 : end if
1597 :
1598 2549427 : if (iflag==1 .or. iflag==2) then
1599 : ! Insert cg into cfft with extra 0 s around outside:
1600 19199044578 : cfft = zero
1601 :
1602 : ! Take care of each plane wave, and complete cfft if needed
1603 1286749 : if (istwf_k==1) then
1604 :
1605 1233290 : if (iflag==1) then
1606 : !$OMP PARALLEL DO PRIVATE(i1,i2,i3) IF (ndat>1)
1607 2259584 : do idat=1,ndat
1608 492645561 : do ipw=1,npw
1609 490385977 : i1=kg_k(1,ipw); if(i1<0) i1=i1+n1; i1=i1+1
1610 490385977 : i2=kg_k(2,ipw); if(i2<0) i2=i2+n2; i2=i2+1
1611 490385977 : i3=kg_k(3,ipw); if(i3<0) i3=i3+n3; i3=i3+1
1612 :
1613 490385977 : cfft(1,i1,i2,i3+n6*(idat-1))=cg(1,ipw+npw*(idat-1))
1614 491515793 : cfft(2,i1,i2,i3+n6*(idat-1))=cg(2,ipw+npw*(idat-1))
1615 : end do
1616 : end do
1617 : end if
1618 :
1619 1233290 : if (iflag==2) then
1620 : !$OMP PARALLEL DO PRIVATE(i1,i2,i3) IF (ndat>1)
1621 239643 : do idat=1,ndat
1622 48993833 : do ipw=1,npw
1623 48754190 : i1=kg_k(1,ipw); if(i1<0) i1=i1+n1; i1=i1+1
1624 48754190 : i2=kg_k(2,ipw); if(i2<0) i2=i2+n2; i2=i2+1
1625 48754190 : i3=kg_k(3,ipw); if(i3<0) i3=i3+n3; i3=i3+1
1626 :
1627 48754190 : cfft(1,i1,i3,i2+n6*(idat-1))=cg(1,ipw+npw*(idat-1))
1628 48890311 : cfft(2,i1,i3,i2+n6*(idat-1))=cg(2,ipw+npw*(idat-1))
1629 : end do
1630 : end do
1631 : end if
1632 :
1633 53459 : else if (istwf_k>=2) then
1634 :
1635 53459 : npwmin=1
1636 53459 : if (istwf_k==2 .and. me_g0==1) then
1637 : ! If gamma point, then cfft must be completed
1638 19960 : do idat=1,ndat
1639 9982 : cfft(1,1,1,1+n6*(idat-1))=cg(1,1+npw*(idat-1))
1640 19960 : cfft(2,1,1,1+n6*(idat-1))=zero
1641 : end do
1642 : npwmin=2
1643 : end if
1644 :
1645 53459 : if (iflag==1) then
1646 : !$OMP PARALLEL DO PRIVATE(i1,i1inv,i2,i2inv,i3,i3inv) IF (ndat>1)
1647 103546 : do idat=1,ndat
1648 15752734 : do ipw=npwmin,npw
1649 15649188 : i1=kg_k(1,ipw); if(i1<0) i1=i1+n1; i1=i1+1
1650 15649188 : i2=kg_k(2,ipw); if(i2<0) i2=i2+n2; i2=i2+1
1651 15649188 : i3=kg_k(3,ipw); if(i3<0) i3=i3+n3; i3=i3+1
1652 : ! Construct the coordinates of -k-G
1653 15649188 : i1inv=i1inver(i1) ; i2inv=i2inver(i2) ; i3inv=i3inver(i3)
1654 :
1655 15649188 : cfft(1,i1,i2,i3+n6*(idat-1))=cg(1,ipw+npw*(idat-1))
1656 15649188 : cfft(2,i1,i2,i3+n6*(idat-1))=cg(2,ipw+npw*(idat-1))
1657 15649188 : cfft(1,i1inv,i2inv,i3inv+n6*(idat-1))= cg(1,ipw+npw*(idat-1))
1658 15700963 : cfft(2,i1inv,i2inv,i3inv+n6*(idat-1))=-cg(2,ipw+npw*(idat-1))
1659 : end do
1660 : end do
1661 : end if
1662 :
1663 53459 : if (iflag==2) then
1664 : !$OMP PARALLEL DO PRIVATE(i1,i1inv,i2,i2inv,i3,i3inv) IF (ndat>1)
1665 3376 : do idat=1,ndat
1666 5483232 : do ipw=npwmin,npw
1667 5479856 : i1=kg_k(1,ipw); if(i1<0) i1=i1+n1; i1=i1+1
1668 5479856 : i2=kg_k(2,ipw); if(i2<0) i2=i2+n2; i2=i2+1
1669 5479856 : i3=kg_k(3,ipw); if(i3<0) i3=i3+n3; i3=i3+1
1670 :
1671 : ! Construct the coordinates of -k-G
1672 5479856 : i1inv=i1inver(i1) ; i2inv=i2inver(i2) ; i3inv=i3inver(i3)
1673 :
1674 5479856 : cfft(1,i1,i3,i2+n6*(idat-1))=cg(1,ipw+npw*(idat-1))
1675 5479856 : cfft(2,i1,i3,i2+n6*(idat-1))=cg(2,ipw+npw*(idat-1))
1676 5479856 : cfft(1,i1inv,i3inv,i2inv+n6*(idat-1))= cg(1,ipw+npw*(idat-1))
1677 5481544 : cfft(2,i1inv,i3inv,i2inv+n6*(idat-1))=-cg(2,ipw+npw*(idat-1))
1678 : end do
1679 : end do
1680 : end if
1681 :
1682 : end if
1683 :
1684 1262678 : else if (iflag==-1 .or. iflag==-2) then
1685 : ! extract cg(output) from cfft(input)
1686 :
1687 1262678 : use_symmetry=0
1688 1262678 : identity(:,:)=0; identity(1,1)=1 ; identity(2,2)=1 ; identity(3,3)=1
1689 16414814 : if(sum((symrec(:,:)-identity(:,:))**2)/=0)use_symmetry=1
1690 5050712 : if(sum(shiftg(:)**2)/=0)use_symmetry=1
1691 :
1692 : ! Extract cg from cfft, ignoring components outside range of cg:
1693 1262678 : if (istwf_k==1) then
1694 :
1695 1261935 : if (use_symmetry==0) then
1696 158524 : if (iflag==-1) then
1697 : !$OMP PARALLEL DO PRIVATE(i1,i2,i3,ipwdat,i3dat) IF (ndat>1)
1698 143122 : do idat=1,ndat
1699 38434135 : do ipw=1,npw
1700 38291013 : i1=kg_k(1,ipw); if(i1<0) i1=i1+n1; i1=i1+1
1701 38291013 : i2=kg_k(2,ipw); if(i2<0) i2=i2+n2; i2=i2+1
1702 38291013 : i3=kg_k(3,ipw); if(i3<0) i3=i3+n3; i3=i3+1
1703 38291013 : ipwdat = ipw + (idat-1) * npw
1704 38291013 : i3dat = i3 + (idat-1) * n6
1705 :
1706 38291013 : cg(1,ipwdat)=cfft(1,i1,i2,i3dat)*xnorm
1707 38362576 : cg(2,ipwdat)=cfft(2,i1,i2,i3dat)*xnorm
1708 : end do
1709 : end do
1710 : else
1711 : ! iflag==-2
1712 : !$OMP PARALLEL DO PRIVATE(i1,i2,i3,ipwdat,i2dat) IF (ndat>1)
1713 206509 : do idat=1,ndat
1714 40573243 : do ipw=1,npw
1715 40366734 : i1=kg_k(1,ipw); if(i1<0) i1=i1+n1; i1=i1+1
1716 40366734 : i2=kg_k(2,ipw); if(i2<0) i2=i2+n2; i2=i2+1
1717 40366734 : i3=kg_k(3,ipw); if(i3<0) i3=i3+n3; i3=i3+1
1718 :
1719 40366734 : ipwdat = ipw + (idat-1) * npw
1720 40366734 : i2dat = i2 + (idat-1) * n6
1721 :
1722 40366734 : cg(1,ipwdat)=cfft(1,i1,i3,i2dat)*xnorm
1723 40486278 : cg(2,ipwdat)=cfft(2,i1,i3,i2dat)*xnorm
1724 : end do
1725 : end do
1726 : end if
1727 : else
1728 : ! use_symmetry == 1
1729 : !$OMP PARALLEL DO PRIVATE(i1,i2,i3,j1,j2,j3,l1,l2,l3,ipwdat,i3dat) IF (ndat>1)
1730 2206822 : do idat=1,ndat
1731 464252121 : do ipw=1,npw
1732 462045299 : l1=kg_k(1,ipw)+shiftg(1)
1733 462045299 : l2=kg_k(2,ipw)+shiftg(2)
1734 462045299 : l3=kg_k(3,ipw)+shiftg(3)
1735 462045299 : j1=symrec(1,1)*l1+symrec(1,2)*l2+symrec(1,3)*l3
1736 462045299 : j2=symrec(2,1)*l1+symrec(2,2)*l2+symrec(2,3)*l3
1737 462045299 : j3=symrec(3,1)*l1+symrec(3,2)*l2+symrec(3,3)*l3
1738 462045299 : if(j1<0) j1=j1+n1; i1=j1+1
1739 462045299 : if(j2<0) j2=j2+n2; i2=j2+1
1740 462045299 : if(j3<0) j3=j3+n3; i3=j3+1
1741 : ! [i1, i2, i3] are the indices of S(g + g0) in the FFT box.
1742 : ! while ipw is the index of g in kg_k
1743 :
1744 462045299 : ipwdat = ipw + (idat-1) * npw
1745 462045299 : i3dat = i3 + (idat-1)*n6
1746 :
1747 : ! c(g) = cfft(S(g + shiftg))
1748 462045299 : cg(1,ipwdat)=cfft(1,i1,i2,i3dat)*xnorm
1749 463148710 : cg(2,ipwdat)=cfft(2,i1,i2,i3dat)*xnorm
1750 : end do
1751 : end do
1752 : end if
1753 :
1754 743 : else if (istwf_k>=2) then
1755 :
1756 743 : npwmin=1
1757 743 : if (istwf_k==2 .and. me_g0==1) then
1758 : ! Extract cg from cfft, in a way that projects on a
1759 : ! wavefunction with time-reversal symmetry
1760 274 : do idat=1,ndat
1761 137 : ipwdat = 1 + (idat-1) * npw
1762 137 : i3dat = 1 + (idat-1)*n6
1763 137 : cg(1,ipwdat)=cfft(1,1,1,i3dat)*xnorm
1764 274 : cg(2,ipwdat)=zero
1765 : end do
1766 : npwmin=2
1767 : end if
1768 :
1769 743 : if (use_symmetry==0) then
1770 :
1771 367 : if (iflag==-1) then
1772 : !$OMP PARALLEL DO PRIVATE(i1,i1inv,i2,i2inv,i3,i3inv,ipwdat,i3dat,i3invdat) IF (ndat>1)
1773 434 : do idat=1,ndat
1774 42206 : do ipw=npwmin,npw
1775 41772 : i1=kg_k(1,ipw); if(i1<0) i1=i1+n1; i1=i1+1
1776 41772 : i2=kg_k(2,ipw); if(i2<0) i2=i2+n2; i2=i2+1
1777 41772 : i3=kg_k(3,ipw); if(i3<0) i3=i3+n3; i3=i3+1
1778 :
1779 : ! Construct the coordinates of -k-G
1780 41772 : i1inv=i1inver(i1); i2inv=i2inver(i2); i3inv=i3inver(i3)
1781 :
1782 41772 : ipwdat = ipw + (idat-1) * npw
1783 41772 : i3dat = i3 + (idat-1) * n6
1784 41772 : i3invdat = i3inv + (idat-1) * n6
1785 :
1786 : ! Here the time-reversal symmetry is used to project from cfft
1787 41772 : cg(1,ipwdat)=(cfft(1,i1,i2,i3dat) + cfft(1,i1inv,i2inv,i3invdat))*0.5d0*xnorm
1788 41989 : cg(2,ipwdat)=(cfft(2,i1,i2,i3dat) - cfft(2,i1inv,i2inv,i3invdat))*0.5d0*xnorm
1789 : end do
1790 : end do
1791 :
1792 : else
1793 : !$OMP PARALLEL DO PRIVATE(i1,i1inv,i2,i2inv,i3,i3inv,ipwdat,i2dat,i2invdat) IF (ndat>1)
1794 300 : do idat=1,ndat
1795 1745174 : do ipw=npwmin,npw
1796 1744874 : i1=kg_k(1,ipw); if(i1<0) i1=i1+n1; i1=i1+1
1797 1744874 : i2=kg_k(2,ipw); if(i2<0) i2=i2+n2; i2=i2+1
1798 1744874 : i3=kg_k(3,ipw); if(i3<0) i3=i3+n3; i3=i3+1
1799 :
1800 : ! Construct the coordinates of -k-G
1801 1744874 : i1inv=i1inver(i1) ; i2inv=i2inver(i2) ; i3inv=i3inver(i3)
1802 :
1803 1744874 : ipwdat = ipw + (idat-1) * npw
1804 1744874 : i2dat = i2 + (idat-1) * n6
1805 1744874 : i2invdat = i2inv + (idat-1) * n6
1806 :
1807 : ! Here the time-reversal symmetry is used to project from cfft
1808 1744874 : cg(1,ipwdat)=(cfft(1,i1,i3,i2dat) + cfft(1,i1inv,i3inv,i2invdat))*0.5d0*xnorm
1809 1745024 : cg(2,ipwdat)=(cfft(2,i1,i3,i2dat) - cfft(2,i1inv,i3inv,i2invdat))*0.5d0*xnorm
1810 : end do
1811 : end do
1812 : end if
1813 :
1814 : else
1815 : ! Use symmetry
1816 376 : id1=n1/2+2
1817 376 : id2=n2/2+2
1818 376 : id3=n3/2+2
1819 :
1820 : !$OMP PARALLEL DO PRIVATE(i1,i1inv,i2,i2inv,i3,i3inv,j1,j2,j3,l1,l2,l3,ipwdat,i3dat,i3invdat) IF (ndat>1)
1821 752 : do idat=1,ndat
1822 45834 : do ipw=npwmin,npw
1823 :
1824 45082 : i1=kg_k(1,ipw); if(i1<0) i1=i1+n1; i1=i1+1
1825 45082 : i2=kg_k(2,ipw); if(i2<0) i2=i2+n2; i2=i2+1
1826 45082 : i3=kg_k(3,ipw); if(i3<0) i3=i3+n3; i3=i3+1
1827 :
1828 45082 : i1inv=i1inver(i1) ; i2inv=i2inver(i2) ; i3inv=i3inver(i3)
1829 :
1830 45082 : l1=kg_k(1,ipw)+shiftg(1)
1831 45082 : l2=kg_k(2,ipw)+shiftg(2)
1832 45082 : l3=kg_k(3,ipw)+shiftg(3)
1833 45082 : j1=symrec(1,1)*l1+symrec(1,2)*l2+symrec(1,3)*l3
1834 45082 : j2=symrec(2,1)*l1+symrec(2,2)*l2+symrec(2,3)*l3
1835 45082 : j3=symrec(3,1)*l1+symrec(3,2)*l2+symrec(3,3)*l3
1836 45082 : if(j1<0)j1=j1+n1 ; i1=j1+1
1837 45082 : if(j2<0)j2=j2+n2 ; i2=j2+1
1838 45082 : if(j3<0)j3=j3+n3 ; i3=j3+1
1839 :
1840 : ! Construct the coordinates of -k-G
1841 45082 : l1=i1inv-(i1inv/id1)*n1-1+shiftg(1)
1842 45082 : l2=i2inv-(i2inv/id2)*n2-1+shiftg(2)
1843 45082 : l3=i3inv-(i3inv/id3)*n3-1+shiftg(3)
1844 45082 : j1=symrec(1,1)*l1+symrec(1,2)*l2+symrec(1,3)*l3
1845 45082 : j2=symrec(2,1)*l1+symrec(2,2)*l2+symrec(2,3)*l3
1846 45082 : j3=symrec(3,1)*l1+symrec(3,2)*l2+symrec(3,3)*l3
1847 45082 : if(j1<0)j1=j1+n1 ; i1inv=j1+1
1848 45082 : if(j2<0)j2=j2+n2 ; i2inv=j2+1
1849 45082 : if(j3<0)j3=j3+n3 ; i3inv=j3+1
1850 :
1851 45082 : ipwdat = ipw + (idat-1) * npw
1852 45082 : i3dat = i3 + (idat-1) * n6
1853 45082 : i3invdat = i3inv + (idat-1) * n6
1854 :
1855 : ! Here the time-reversal symmetry is used to project from cfft
1856 45082 : cg(1,ipwdat)=(cfft(1,i1,i2,i3dat) + cfft(1,i1inv,i2inv,i3invdat))*0.5d0*xnorm
1857 45458 : cg(2,ipwdat)=(cfft(2,i1,i2,i3dat) - cfft(2,i1inv,i2inv,i3invdat))*0.5d0*xnorm
1858 : end do
1859 : end do
1860 : end if
1861 :
1862 : end if
1863 :
1864 : else
1865 0 : ABI_BUG(sjoin('iflag: ', itoa(iflag),' not acceptable.'))
1866 : end if
1867 :
1868 : DBG_EXIT("COLL")
1869 :
1870 2549427 : end subroutine sphere
1871 : !!***
1872 :
1873 : !----------------------------------------------------------------------
1874 :
1875 : !!****f* m_fftcore/sphere_fft
1876 : !! NAME
1877 : !! sphere_fft
1878 : !!
1879 : !! FUNCTION
1880 : !! Array cg is defined in sphere with npw points. Insert cg inside box
1881 : !! of n1*n2*n3 points to define array cfft for fft box.
1882 : !! corresponds to given element in cg. rest of cfft is filled with 0 s.
1883 : !!
1884 : !! iflag=1==>insert cg into cfft.
1885 : !! iflag=2==>insert cg into cfft, where the second and third dimension
1886 : !! have been switched (needed for new 2002 SGoedecker FFT)
1887 : !! iflag=-1==> extract cg from cfft.
1888 : !! iflag=-2==> extract cg from cfft, where the second and third dimension
1889 : !! have been switched (needed for new 2002 SGoedecker FFT)
1890 : !! (WARNING : iflag=-2 cannot use symmetry operations)
1891 : !!
1892 : !! There is also the possibility to apply a symmetry operation,
1893 : !! as well as to make a shift in reciprocal space, or to multiply
1894 : !! by a constant factor, in the case iflag=-1.
1895 : !! Multiplication by a constant factor is also possible in the case iflag=-2.
1896 : !!
1897 : !! INPUTS
1898 : !! cg(2,npw)= contains values for npw G vectors in basis sphere
1899 : !! ndat=number of FFT to do in //
1900 : !! npw=number of G vectors in basis at this k point
1901 : !! cfft(2,n4,n5,n6) = fft box
1902 : !! n1,n2,n3=physical dimension of the box (cfft)
1903 : !! n4,n5,n6=memory dimension of cfft
1904 : !! kg_k(3,npw)=integer coordinates of G vectors in basis sphere
1905 : !! mpi_enreg=information about MPI parallelization
1906 : !! tab_fftwf2_local(n2)=local i2 indices in fourwf
1907 : !! nd2proc TO BE DESCRIBED SB 090831
1908 : !! iflag=option parameter. Possible values: -1, -2, 1, 2 ; this is used only in debug option
1909 : !!
1910 : !! OUTPUT
1911 : !! (see side effects)
1912 : !!
1913 : !! SIDE EFFECTS
1914 : !! Input/Output
1915 : !! iflag=1 and 2, insert cg(input) into cfft(output)
1916 : !! iflag=-1 and -2, extract cg(output) from cfft(input)
1917 : !!
1918 : !! NOTES
1919 : !! cg and cfft are assumed to be of type COMPLEX, although this routine treats
1920 : !! them as real of twice the length to avoid nonstandard complex*16.
1921 : !!
1922 : !! WARNING
1923 : !! NO CHECK is DONE over iflag.
1924 : !!
1925 : !! TODO
1926 : !! Order arguments
1927 : !!
1928 : !! SOURCE
1929 :
1930 0 : subroutine sphere_fft(cg,ndat,npw,cfft,n1,n2,n3,n4,n5,kg_k,tab_fftwf2_local,nd2proc)
1931 :
1932 : !Arguments ------------------------------------
1933 : !scalars
1934 : integer,intent(in) :: n1,n2,n3,n4,n5,nd2proc,ndat,npw
1935 : integer,intent(in) :: tab_fftwf2_local(n2)
1936 : !arrays
1937 : integer,intent(in) :: kg_k(3,npw)
1938 : real(dp),intent(in) :: cg(2,npw*ndat)
1939 : real(dp),intent(out) :: cfft(2,n4,n5,nd2proc*ndat)
1940 :
1941 : !Local variables-------------------------------
1942 : !scalars
1943 : integer :: i1,i2,i2_local,i3,idat,ipw
1944 : ! *************************************************************************
1945 :
1946 : !Insert cg into cfft with extra 0 s around outside:
1947 0 : cfft = zero
1948 :
1949 : !$OMP PARALLEL DO PRIVATE(i1,i2,i2_local,i3)
1950 0 : do ipw=1,npw
1951 0 : i1=kg_k(1,ipw); if(i1<0)i1=i1+n1; i1=i1+1
1952 0 : i2=kg_k(2,ipw); if(i2<0)i2=i2+n2; i2=i2+1
1953 0 : i3=kg_k(3,ipw); if(i3<0)i3=i3+n3; i3=i3+1
1954 0 : i2_local = tab_fftwf2_local(i2)
1955 0 : do idat=1,ndat
1956 0 : cfft(1,i1,i3,i2_local + nd2proc*(idat-1))=cg(1,ipw+npw*(idat-1))
1957 0 : cfft(2,i1,i3,i2_local + nd2proc*(idat-1))=cg(2,ipw+npw*(idat-1))
1958 : end do
1959 : end do
1960 :
1961 0 : end subroutine sphere_fft
1962 : !!***
1963 :
1964 : !----------------------------------------------------------------------
1965 :
1966 : !!****f* m_fftcore/sphere_fft1
1967 : !! NAME
1968 : !! sphere_fft1
1969 : !!
1970 : !! FUNCTION
1971 : !! Array cg is defined in sphere with npw points. Insert cg inside box
1972 : !! of n1*n2*n3 points to define array cfft for fft box.
1973 : !! corresponds to given element in cg. rest of cfft is filled with 0 s.
1974 : !!
1975 : !! iflag=1==>insert cg into cfft.
1976 : !! iflag=2==>insert cg into cfft, where the second and third dimension
1977 : !! have been switched (needed for new 2002 SGoedecker FFT)
1978 : !! iflag=-1==> extract cg from cfft.
1979 : !! iflag=-2==> extract cg from cfft, where the second and third dimension
1980 : !! have been switched (needed for new 2002 SGoedecker FFT)
1981 : !! (WARNING : iflag=-2 cannot use symmetry operations)
1982 : !!
1983 : !! There is also the possibility to apply a symmetry operation,
1984 : !! as well as to make a shift in reciprocal space, or to multiply
1985 : !! by a constant factor, in the case iflag=-1.
1986 : !! Multiplication by a constant factor is also possible in the case iflag=-2.
1987 : !!
1988 : !! INPUTS
1989 : !! cg(2,npw)= contains values for npw G vectors in basis sphere
1990 : !! ndat=number of FFT to do in //
1991 : !! npw=number of G vectors in basis at this k point
1992 : !! cfft(2,n4,n5,n6) = fft box
1993 : !! n1,n2,n3=physical dimension of the box (cfft)
1994 : !! n4,n5,n6=memory dimension of cfft
1995 : !! kg_k(3,npw)=integer coordinates of G vectors in basis sphere
1996 : !! nd2proc TO BE DESCRIBED SB 090831
1997 : !! iflag=option parameter. Possible values: -1, -2, 1, 2
1998 : !! tab_fftwf2_local(n2)=local i2 indices in fourwf
1999 : !!
2000 : !! OUTPUT
2001 : !! (see side effects)
2002 : !!
2003 : !! SIDE EFFECTS
2004 : !! Input/Output
2005 : !! iflag=1 and 2, insert cg(input) into cfft(output)
2006 : !! iflag=-1 and -2, extract cg(output) from cfft(input)
2007 : !!
2008 : !! NOTES
2009 : !! cg and cfft are assumed to be of type COMPLEX, although this routine treats
2010 : !! them as real of twice the length to avoid nonstandard complex*16.
2011 : !!
2012 : !! WARNING
2013 : !! NO CHECK is DONE over iflag.
2014 : !!
2015 : !! TODO
2016 : !! Order arguments
2017 : !! sphere_fft1 is similar to sphere_fft, the only difference being that ndat > 1 is not supported.
2018 : !! Why? Should merge the two APIs.
2019 : !!
2020 : !! SOURCE
2021 :
2022 696830 : subroutine sphere_fft1(cg,ndat,npw,cfft,n1,n2,n3,n4,n5,n6,kg_k,tab_fftwf2_local)
2023 :
2024 :
2025 : !Arguments ------------------------------------
2026 : !scalars
2027 : integer,intent(in) :: n1,n2,n3,n4,n5,n6,ndat,npw
2028 : !arrays
2029 : integer,intent(in) :: kg_k(3,npw)
2030 : integer,intent(in) :: tab_fftwf2_local(n2)
2031 : real(dp),intent(in) :: cg(2,npw*ndat)
2032 : real(dp),intent(inout) :: cfft(2,n4,n5,n6*ndat)
2033 :
2034 : !Local variables-------------------------------
2035 : !scalars
2036 : integer :: i1,i2,i2_local,i3,idat,ipw
2037 : ! *************************************************************************
2038 :
2039 : !Insert cg into cfft with extra 0 s around outside:
2040 :
2041 1247558986 : cfft = zero
2042 : !$OMP PARALLEL DO PRIVATE(i1,i2,i2_local,i3)
2043 1413984 : do idat=1,ndat
2044 139650584 : do ipw=1,npw
2045 138236600 : i1=kg_k(1,ipw); if(i1<0)i1=i1+n1; i1=i1+1
2046 138236600 : i2=kg_k(2,ipw); if(i2<0)i2=i2+n2; i2=i2+1
2047 138236600 : i3=kg_k(3,ipw); if(i3<0)i3=i3+n3; i3=i3+1
2048 138236600 : i2_local = tab_fftwf2_local(i2) + n6*(idat-1)
2049 138236600 : cfft(1,i1,i3,i2_local)=cg(1,ipw+npw*(idat-1))
2050 138953754 : cfft(2,i1,i3,i2_local)=cg(2,ipw+npw*(idat-1))
2051 : end do
2052 : end do
2053 :
2054 696830 : end subroutine sphere_fft1
2055 : !!***
2056 :
2057 : !----------------------------------------------------------------------
2058 :
2059 : !!****f* m_fftcore/change_istwfk
2060 : !! NAME
2061 : !! change_istwfk
2062 : !!
2063 : !! FUNCTION
2064 : !! This function allows one to change the time-reversal storage mode (istwfk)
2065 : !! of a *full* set of u(G). It does not support MPI-FFT!
2066 : !!
2067 : !! INPUTS
2068 : !! from_npw=number of G vectors in input from_cg
2069 : !! from_kg_k(3,npw)=integer coordinates of the G vectors of from_cg
2070 : !! from_istwfk=option parameter that describes the storage in from_cg
2071 : !! to_npw=number of G vectors in output to_cg
2072 : !! to_kg_k(3,npw)=integer coordinates of the G vectors in to_cg
2073 : !! to_istwfk=option parameter that describes the storage in to_cg
2074 : !! n1,n2,n3=physical dimension of the box (must be large enough to contain the sphere, no check is done)
2075 : !! ndat=number of wavefunctions
2076 : !! from_cg(2,from_npw*ndat)= Input u(g) values
2077 : !!
2078 : !! OUTPUTS
2079 : !! to_cg(2,to_npw*ndat)= Output u(g) defined on the list of vectors to_kg_k with time-reversal mode to_istwfk
2080 : !!
2081 : !! SOURCE
2082 :
2083 4 : subroutine change_istwfk(from_npw,from_kg,from_istwfk,to_npw,to_kg,to_istwfk,n1,n2,n3,ndat,from_cg,to_cg)
2084 :
2085 : !Arguments ------------------------------------
2086 : !scalars
2087 : integer,intent(in) :: from_npw,from_istwfk,to_npw,to_istwfk,n1,n2,n3,ndat
2088 : !arrays
2089 : integer,intent(in) :: from_kg(3,from_npw),to_kg(3,to_npw)
2090 : real(dp),intent(inout) :: from_cg(2,from_npw*ndat) ! out due to sphere!
2091 : real(dp),intent(inout) :: to_cg(2,to_npw*ndat)
2092 :
2093 : !Local variables-------------------------------
2094 : !scalars
2095 : integer :: n4,n5,n6
2096 : real(dp),parameter :: xnorm1=one
2097 : !arrays
2098 : integer,parameter :: shiftg0(3)=0,me_g0=1
2099 : integer,parameter :: symmE(3,3)=reshape([1,0,0,0,1,0,0,0,1],[3,3])
2100 4 : real(dp),allocatable :: cfft(:,:,:,:)
2101 : ! *************************************************************************
2102 :
2103 4 : n4=2*(n1/2)+1
2104 4 : n5=2*(n2/2)+1
2105 4 : n6=2*(n3/2)+1
2106 :
2107 20 : ABI_MALLOC(cfft, (2,n4,n5,n6*ndat))
2108 :
2109 : ! iflag=1 ==> insert from_cg into cfft.
2110 4 : call sphere(from_cg,ndat,from_npw,cfft,n1,n2,n3,n4,n5,n6,from_kg,from_istwfk,+1,me_g0,shiftg0,symmE,xnorm1)
2111 :
2112 : ! iflag=-1 ==> extract to_cg from cfft.
2113 4 : call sphere(to_cg,ndat,to_npw,cfft,n1,n2,n3,n4,n5,n6,to_kg,to_istwfk,-1,me_g0,shiftg0,symmE,xnorm1)
2114 :
2115 4 : ABI_FREE(cfft)
2116 :
2117 4 : end subroutine change_istwfk
2118 : !!***
2119 :
2120 : !----------------------------------------------------------------------
2121 :
2122 : !!****f* m_fftcore/switch
2123 : !! NAME
2124 : !! switch
2125 : !!
2126 : !! FUNCTION
2127 : !!
2128 : !! INPUTS
2129 : !!
2130 : !! OUTPUT
2131 : !!
2132 : !! SOURCE
2133 :
2134 1158611 : pure subroutine switch(n1dfft,n2,lot,n1,lzt,zt,zw)
2135 :
2136 : !Arguments ------------------------------------
2137 : integer,intent(in) :: n1dfft,n2,lot,n1,lzt
2138 : real(dp),intent(in) :: zt(2,lzt,n1)
2139 : real(dp),intent(inout) :: zw(2,lot,n2)
2140 :
2141 : !Local variables-------------------------------
2142 : integer :: i,j
2143 : ! *************************************************************************
2144 :
2145 17881710 : do j=1,n1dfft
2146 471276667 : do i=1,n2
2147 453394957 : zw(1,j,i)=zt(1,i,j)
2148 470118056 : zw(2,j,i)=zt(2,i,j)
2149 : end do
2150 : end do
2151 :
2152 1158611 : end subroutine switch
2153 : !!***
2154 :
2155 : !----------------------------------------------------------------------
2156 :
2157 : !!****f* m_fftcore/switch_cent
2158 : !! NAME
2159 : !! switch_cent
2160 : !!
2161 : !! FUNCTION
2162 : !! Perform the rotation:
2163 : !!
2164 : !! input: I2,i1,j3,(jp3)
2165 : !! output: i1,I2,j3,(jp3)
2166 : !!
2167 : !! and pad the signal with zeros.
2168 : !!
2169 : !! INPUTS
2170 : !! n1dfft=Number of 1D FFTs to perform
2171 : !! max2=Max G_y in the small box enclosing the G-sphere.
2172 : !! m2=Size of the small box enclosing the G-sphere along y
2173 : !! n2=Dimension of the transform along y
2174 : !! lot=Cache blocking factor.
2175 : !! n1=Dimension of the transform along x
2176 : !! lzt=Second dimension of z
2177 : !! zt(2,lzt,n1)
2178 : !!
2179 : !! OUTPUT
2180 : !! zw(2,lot,n2)=Cache working array
2181 : !!
2182 : !! SOURCE
2183 :
2184 10425179 : pure subroutine switch_cent(n1dfft,max2,m2,n2,lot,n1,lzt,zt,zw)
2185 :
2186 : !Arguments ------------------------------------
2187 : integer,intent(in) :: n1dfft,max2,m2,n2,lot,n1,lzt
2188 : real(dp),intent(in) :: zt(2,lzt,n1)
2189 : real(dp),intent(inout) :: zw(2,lot,n2)
2190 :
2191 : !Local variables-------------------------------
2192 : integer :: i,j
2193 : ! *************************************************************************
2194 :
2195 : ! Here, zero and positive frequencies
2196 216259320 : do j=1,n1dfft
2197 1514094604 : do i=1,max2+1
2198 1297835284 : zw(1,j,i)=zt(1,i,j)
2199 1503669425 : zw(2,j,i)=zt(2,i,j)
2200 : end do
2201 : end do
2202 :
2203 : ! Fill the center region with zeros
2204 146001875 : do i=max2+2,n2-m2+max2+1
2205 2752584651 : do j=1,n1dfft
2206 2606582776 : zw(1,j,i)=zero
2207 2742159472 : zw(2,j,i)=zero
2208 : end do
2209 : end do
2210 :
2211 : ! Here, negative frequencies
2212 10425179 : if (m2>=max2+2) then
2213 216259320 : do j=1,n1dfft
2214 1239573669 : do i=max2+2,m2
2215 1023314349 : zw(1,j,i+n2-m2)=zt(1,i,j)
2216 1229148490 : zw(2,j,i+n2-m2)=zt(2,i,j)
2217 : end do
2218 : end do
2219 : end if
2220 :
2221 10425179 : end subroutine switch_cent
2222 : !!***
2223 :
2224 : !----------------------------------------------------------------------
2225 :
2226 : !!****f* m_fftcore/switchreal
2227 : !! NAME
2228 : !! switchreal
2229 : !!
2230 : !! FUNCTION
2231 : !! Perform the rotation:
2232 : !!
2233 : !! input: I2,i1,j3,(jp3)
2234 : !! output: i1,I2,j3,(jp3)
2235 : !!
2236 : !! and pad the signal with zeros.
2237 : !! Used for real wavefunctions.
2238 : !!
2239 : !! INPUTS
2240 : !! includelast
2241 : !! n1dfft=Number of 1D FFTs to perform
2242 : !! n2=Dimension of the transform along y
2243 : !! n2eff
2244 : !! lot=Cache blocking factor.
2245 : !! n1zt
2246 : !! lzt
2247 : !! zt(2,lzt,n1zt)
2248 : !!
2249 : !! OUTPUT
2250 : !! zw(2,lot,n2)
2251 : !!
2252 : !! SOURCE
2253 :
2254 6480 : pure subroutine switchreal(includelast,n1dfft,n2,n2eff,lot,n1zt,lzt,zt,zw)
2255 :
2256 : !Arguments ------------------------------------
2257 : integer,intent(in) :: includelast,n1dfft,n2,n2eff,lot,n1zt,lzt
2258 : real(dp),intent(in) :: zt(2,lzt,n1zt)
2259 : real(dp),intent(inout) :: zw(2,lot,n2)
2260 :
2261 : !Local variables-------------------------------
2262 : integer :: i,j
2263 : ! *************************************************************************
2264 :
2265 6480 : if (includelast==1) then
2266 :
2267 : ! Compute symmetric and antisymmetric combinations
2268 74196 : do j=1,n1dfft
2269 67716 : zw(1,j,1)=zt(1,1,2*j-1)
2270 74196 : zw(2,j,1)=zt(1,1,2*j )
2271 : end do
2272 220698 : do i=2,n2eff
2273 2323620 : do j=1,n1dfft
2274 2102922 : zw(1,j,i)= zt(1,i,2*j-1)-zt(2,i,2*j)
2275 2102922 : zw(2,j,i)= zt(2,i,2*j-1)+zt(1,i,2*j)
2276 2102922 : zw(1,j,n2+2-i)= zt(1,i,2*j-1)+zt(2,i,2*j)
2277 2317140 : zw(2,j,n2+2-i)=-zt(2,i,2*j-1)+zt(1,i,2*j)
2278 : end do
2279 : end do
2280 :
2281 : else
2282 :
2283 : ! An odd number of FFTs
2284 : ! Compute symmetric and antisymmetric combinations
2285 0 : do j=1,n1dfft-1
2286 0 : zw(1,j,1)=zt(1,1,2*j-1)
2287 0 : zw(2,j,1)=zt(1,1,2*j )
2288 : end do
2289 0 : zw(1,n1dfft,1)=zt(1,1,2*n1dfft-1)
2290 0 : zw(2,n1dfft,1)=zero
2291 :
2292 0 : do i=2,n2eff
2293 0 : do j=1,n1dfft-1
2294 0 : zw(1,j,i)= zt(1,i,2*j-1)-zt(2,i,2*j)
2295 0 : zw(2,j,i)= zt(2,i,2*j-1)+zt(1,i,2*j)
2296 0 : zw(1,j,n2+2-i)= zt(1,i,2*j-1)+zt(2,i,2*j)
2297 0 : zw(2,j,n2+2-i)=-zt(2,i,2*j-1)+zt(1,i,2*j)
2298 : end do
2299 0 : zw(1,n1dfft,i)= zt(1,i,2*n1dfft-1)
2300 0 : zw(2,n1dfft,i)= zt(2,i,2*n1dfft-1)
2301 0 : zw(1,n1dfft,n2+2-i)= zt(1,i,2*n1dfft-1)
2302 0 : zw(2,n1dfft,n2+2-i)=-zt(2,i,2*n1dfft-1)
2303 : end do
2304 : end if
2305 :
2306 6480 : end subroutine switchreal
2307 : !!***
2308 :
2309 : !----------------------------------------------------------------------
2310 :
2311 : !!****f* m_fftcore/switchreal_cent
2312 : !! NAME
2313 : !! switchreal_cent
2314 : !!
2315 : !! FUNCTION
2316 : !! Perform the rotation:
2317 : !!
2318 : !! input: I2,i1,j3,(jp3)
2319 : !! output: i1,I2,j3,(jp3)
2320 : !!
2321 : !! and pad the signal with zeros.
2322 : !! Used for the Fourier transform of real wavefunctions.
2323 : !!
2324 : !! INPUTS
2325 : !! includelast
2326 : !! n1dfft=Number of 1D FFTs to perform
2327 : !! max2
2328 : !! n2=Dimension of the transform along y
2329 : !! lot=Cache blocking factor.
2330 : !! n1zt, lzt=Dimensions of zt.
2331 : !! zt(2,lzt,n1zt)
2332 : !!
2333 : !! OUTPUT
2334 : !! zw(2,lot,n2)
2335 : !!
2336 : !! SOURCE
2337 :
2338 22764 : pure subroutine switchreal_cent(includelast,n1dfft,max2,n2,lot,n1zt,lzt,zt,zw)
2339 :
2340 : !Arguments ------------------------------------
2341 : integer,intent(in) :: includelast,n1dfft,max2,n2,lot,n1zt,lzt
2342 : real(dp),intent(in) :: zt(2,lzt,n1zt)
2343 : real(dp),intent(inout) :: zw(2,lot,n2)
2344 :
2345 : !Local variables-------------------------------
2346 : integer :: i,j
2347 : ! *************************************************************************
2348 :
2349 22764 : if (includelast==1) then
2350 :
2351 : ! Compute symmetric and antisymmetric combinations
2352 244872 : do j=1,n1dfft
2353 224508 : zw(1,j,1)=zt(1,1,2*j-1)
2354 244872 : zw(2,j,1)=zt(1,1,2*j )
2355 : end do
2356 :
2357 459984 : do i=2,max2+1
2358 5171724 : do j=1,n1dfft
2359 4711740 : zw(1,j,i)= zt(1,i,2*j-1)-zt(2,i,2*j)
2360 4711740 : zw(2,j,i)= zt(2,i,2*j-1)+zt(1,i,2*j)
2361 4711740 : zw(1,j,n2+2-i)= zt(1,i,2*j-1)+zt(2,i,2*j)
2362 5151360 : zw(2,j,n2+2-i)=-zt(2,i,2*j-1)+zt(1,i,2*j)
2363 : end do
2364 : end do
2365 :
2366 20364 : if(max2+1<n2-max2)then
2367 979896 : do i=max2+2,n2-max2
2368 11345700 : do j=1,n1dfft
2369 10365804 : zw(1,j,i)=zero
2370 11325336 : zw(2,j,i)=zero
2371 : end do
2372 : end do
2373 : end if
2374 :
2375 : else
2376 : ! Compute symmetric and antisymmetric combinations
2377 24000 : do j=1,n1dfft-1
2378 21600 : zw(1,j,1)=zt(1,1,2*j-1)
2379 24000 : zw(2,j,1)=zt(1,1,2*j )
2380 : end do
2381 :
2382 2400 : zw(1,n1dfft,1)=zt(1,1,2*n1dfft-1)
2383 2400 : zw(2,n1dfft,1)=zero
2384 40800 : do i=2,max2+1
2385 384000 : do j=1,n1dfft-1
2386 345600 : zw(1,j,i)= zt(1,i,2*j-1)-zt(2,i,2*j)
2387 345600 : zw(2,j,i)= zt(2,i,2*j-1)+zt(1,i,2*j)
2388 345600 : zw(1,j,n2+2-i)= zt(1,i,2*j-1)+zt(2,i,2*j)
2389 384000 : zw(2,j,n2+2-i)=-zt(2,i,2*j-1)+zt(1,i,2*j)
2390 : end do
2391 38400 : zw(1,n1dfft,i)= zt(1,i,2*n1dfft-1)
2392 38400 : zw(2,n1dfft,i)= zt(2,i,2*n1dfft-1)
2393 38400 : zw(1,n1dfft,n2+2-i)= zt(1,i,2*n1dfft-1)
2394 40800 : zw(2,n1dfft,n2+2-i)=-zt(2,i,2*n1dfft-1)
2395 : end do
2396 :
2397 2400 : if(max2+1<n2-max2)then
2398 96000 : do i=max2+2,n2-max2
2399 1032000 : do j=1,n1dfft
2400 936000 : zw(1,j,i)=zero
2401 1029600 : zw(2,j,i)=zero
2402 : end do
2403 : end do
2404 : end if
2405 : end if
2406 :
2407 22764 : end subroutine switchreal_cent
2408 : !!***
2409 :
2410 : !----------------------------------------------------------------------
2411 :
2412 : !!****f* m_fftcore/scramble
2413 : !! NAME
2414 : !! scramble
2415 : !!
2416 : !! FUNCTION
2417 : !! This routine performs the local rotation
2418 : !!
2419 : !! input: G1,R3,G2,(Gp2)
2420 : !! output: G1,G2,R3,(Gp2)
2421 : !!
2422 : !! INPUTS
2423 : !! i1=Index of x in the small box enclosing the G-sphere.
2424 : !! j2
2425 : !! lot=Cache blocking factor
2426 : !! n1dfft=Number of 1D FFTs performed.
2427 : !! md1,md2proc,nnd3=Used to dimension zmpi2
2428 : !! n3=Dimension of the transform along z.
2429 : !! zw(2,lot,n3): zw(:,1:n1dfft,n3) contains the lines transformed along z
2430 : !!
2431 : !! OUTPTU
2432 : !! zmpi2(2,md1,md2proc,nnd3)
2433 : !!
2434 : !! SOURCE
2435 :
2436 5991720 : pure subroutine scramble(i1,j2,lot,n1dfft,md1,n3,md2proc,nnd3,zw,zmpi2)
2437 :
2438 : !Arguments ------------------------------------
2439 : integer,intent(in) :: i1,j2,lot,n1dfft,md1,n3,md2proc,nnd3
2440 : real(dp),intent(in) :: zw(2,lot,n3)
2441 : real(dp),intent(inout) :: zmpi2(2,md1,md2proc,nnd3)
2442 :
2443 : !Local variables-------------------------------
2444 : integer :: i3,i
2445 : ! *************************************************************************
2446 :
2447 149972498 : do i3=1,n3
2448 1685672926 : do i=0,n1dfft-1
2449 1535700428 : zmpi2(1,i1+i,j2,i3)=zw(1,i+1,i3)
2450 1679681206 : zmpi2(2,i1+i,j2,i3)=zw(2,i+1,i3)
2451 : end do
2452 : end do
2453 :
2454 5991720 : end subroutine scramble
2455 : !!***
2456 :
2457 : !----------------------------------------------------------------------
2458 :
2459 : !!****f* m_fftcore/fill
2460 : !! NAME
2461 : !! fill
2462 : !!
2463 : !! FUNCTION
2464 : !! Receives a set of z-lines in reciprocal space,
2465 : !! insert the values in the cache work array zw (no padding)
2466 : !!
2467 : !! INPUTS
2468 : !! nd1,nd3=Dimensions of the input array zf.
2469 : !! lot=Cache blocking factor.
2470 : !! n1dfft=Number of 1D FFTs to perform
2471 : !! n3=Dimension of the transform along z
2472 : !! zf(2,nd1,nd3)=Input array
2473 : !!
2474 : !! OUTPUT
2475 : !! zw(2,lot,n3)=Cache work array with the z-lines.
2476 : !!
2477 : !! SOURCE
2478 :
2479 1163090 : pure subroutine fill(nd1,nd3,lot,n1dfft,n3,zf,zw)
2480 :
2481 : !Arguments ------------------------------------
2482 : integer,intent(in) :: nd1,nd3,lot,n1dfft,n3
2483 : real(dp),intent(in) :: zf(2,nd1,nd3)
2484 : real(dp),intent(inout) :: zw(2,lot,n3)
2485 :
2486 : ! local variables
2487 : integer :: i1,i3
2488 : ! *************************************************************************
2489 :
2490 33608291 : do i3=1,n3
2491 491344524 : do i1=1,n1dfft
2492 457736233 : zw(1,i1,i3)=zf(1,i1,i3)
2493 490181434 : zw(2,i1,i3)=zf(2,i1,i3)
2494 : end do
2495 : end do
2496 :
2497 1163090 : end subroutine fill
2498 : !!***
2499 :
2500 : !----------------------------------------------------------------------
2501 :
2502 : !!****f* m_fftcore/fill_cent
2503 : !! NAME
2504 : !! fill_cent
2505 : !!
2506 : !! FUNCTION
2507 : !! Receives a set of z-lines in reciprocal space,
2508 : !! insert the values in cache work array defined on the FFT box
2509 : !! and pads the central of the frequency region with zeros.
2510 : !!
2511 : !! INPUTS
2512 : !! md1,md3=Leading dimension of zf along x and z
2513 : !! lot=second dimension of zw (cache blocking factor)
2514 : !! n1dfft=Number of 1d transforms to be performed along z.
2515 : !! max3=Max G_z in the small box enclosing the G-sphere.
2516 : !! m3=Number of points in the *small* box enclosing the G-sphere
2517 : !! n3=Dimension of the FFT transform along z
2518 : !! zf(2,md1,md3)=x-z planes in reciprocal space
2519 : !!
2520 : !! OUTPUT
2521 : !! zw(2,lot,n3)= Filled cache work array.
2522 : !! zw(:,1:n1dfft,n3) contains the lines to be transformed along.
2523 : !!
2524 : !! SOURCE
2525 :
2526 4828630 : pure subroutine fill_cent(md1,md3,lot,n1dfft,max3,m3,n3,zf,zw)
2527 :
2528 : !Arguments ------------------------------------
2529 : integer,intent(in) :: md1,md3,lot,n1dfft,max3,m3,n3
2530 : real(dp),intent(in) :: zf(2,md1,md3)
2531 : real(dp),intent(inout) :: zw(2,lot,n3)
2532 :
2533 : !Local variables-------------------------------
2534 : !scalars
2535 : integer :: i1,i3
2536 : ! *************************************************************************
2537 :
2538 : ! Here, zero and positive frequencies
2539 32935356 : do i3=1,max3+1
2540 303796692 : do i1=1,n1dfft
2541 270861336 : zw(1,i1,i3)=zf(1,i1,i3)
2542 298968062 : zw(2,i1,i3)=zf(2,i1,i3)
2543 : end do
2544 : end do
2545 :
2546 : ! Fill the center region with zeros
2547 64163636 : do i3=max3+2,n3-m3+max3+1
2548 638200577 : do i1=1,n1dfft
2549 574036941 : zw(1,i1,i3)=zero
2550 633371947 : zw(2,i1,i3)=zero
2551 : end do
2552 : end do
2553 :
2554 : ! Here, negative frequencies
2555 28922475 : do i3=max3+2,m3
2556 261988393 : do i1=1,n1dfft
2557 233065918 : zw(1,i1,i3+n3-m3)=zf(1,i1,i3)
2558 257159763 : zw(2,i1,i3+n3-m3)=zf(2,i1,i3)
2559 : end do
2560 : end do
2561 :
2562 4828630 : end subroutine fill_cent
2563 : !!***
2564 :
2565 : !----------------------------------------------------------------------
2566 :
2567 : !!****f* m_fftcore/unfill
2568 : !! NAME
2569 : !! unfill
2570 : !!
2571 : !! FUNCTION
2572 : !! Move data from the cache work array to zf
2573 : !!
2574 : !! INPUTS
2575 : !! nd1,nd3=Dimensions of the input array zf.
2576 : !! lot=Cache blocking factor.
2577 : !! n1dfft=Number of 1D FFTs to perform
2578 : !! n3=Dimension of the transform along z
2579 : !! zw(2,lot,n3)=Cache work array with the z-lines.
2580 : !!
2581 : !! OUTPUT
2582 : !! zf(2,nd1,nd3)= zf(:,1:n1dfft,:1:n3) is filled with the results stored in zw
2583 : !!
2584 : !! SOURCE
2585 :
2586 1205401 : pure subroutine unfill(nd1,nd3,lot,n1dfft,n3,zw,zf)
2587 :
2588 : !Arguments ------------------------------------
2589 : integer,intent(in) :: nd1,nd3,lot,n1dfft,n3
2590 : real(dp),intent(in) :: zw(2,lot,n3)
2591 : real(dp),intent(inout) :: zf(2,nd1,nd3)
2592 :
2593 : !Local variables-------------------------------
2594 : integer :: i1,i3
2595 : ! *************************************************************************
2596 :
2597 34634785 : do i3=1,n3
2598 524509437 : do i1=1,n1dfft
2599 489874652 : zf(1,i1,i3)=zw(1,i1,i3)
2600 523304036 : zf(2,i1,i3)=zw(2,i1,i3)
2601 : end do
2602 : end do
2603 :
2604 1205401 : end subroutine unfill
2605 : !!***
2606 :
2607 : !----------------------------------------------------------------------
2608 :
2609 : !!****f* m_fftcore/unfill_cent
2610 : !! NAME
2611 : !! unfill_cent
2612 : !!
2613 : !! FUNCTION
2614 : !! Transfer data from the cache work array to zf.
2615 : !! Takes into account zero padding (only the non-zero entries are moved)
2616 : !!
2617 : !! INPUTS
2618 : !! md1,md3=Leading dimension of zf along x and z
2619 : !! lot=Cache blocking factor.
2620 : !! n1dfft=Number of 1d transforms performed along z.
2621 : !! max3=Max index of G_z the small box enclosing the G-sphere.
2622 : !! m3=Number of points in the *small* box enclosing the G-sphere
2623 : !! n3=Dimension of the FFT transform along z
2624 : !! zw(2,lot,n3)=Cache work array
2625 : !!
2626 : !! OUTPUT
2627 : !! zf(2,md1,md3)= zf(:,1:n1dfft,1:m3) is filled with the non-zero components.
2628 : !!
2629 : !! SOURCE
2630 :
2631 4423910 : pure subroutine unfill_cent(md1,md3,lot,n1dfft,max3,m3,n3,zw,zf)
2632 :
2633 : !Arguments ------------------------------------
2634 : integer,intent(in) :: md1,md3,lot,n1dfft,max3,m3,n3
2635 : real(dp),intent(in) :: zw(2,lot,n3)
2636 : real(dp),intent(inout) :: zf(2,md1,md3)
2637 :
2638 : !Local variables-------------------------------
2639 : integer :: i1,i3
2640 : ! *************************************************************************
2641 :
2642 : ! Here, zero and positive frequencies
2643 29728922 : do i3=1,max3+1
2644 273951362 : do i1=1,n1dfft
2645 244222440 : zf(1,i1,i3)=zw(1,i1,i3)
2646 269527452 : zf(2,i1,i3)=zw(2,i1,i3)
2647 : end do
2648 : end do
2649 :
2650 : ! Here, negative frequencies
2651 26044554 : do i3=max3+2,m3
2652 235512128 : do i1=1,n1dfft
2653 209467574 : zf(1,i1,i3)=zw(1,i1,i3+n3-m3)
2654 231088218 : zf(2,i1,i3)=zw(2,i1,i3+n3-m3)
2655 : end do
2656 : end do
2657 :
2658 4423910 : end subroutine unfill_cent
2659 : !!***
2660 :
2661 : !----------------------------------------------------------------------
2662 :
2663 : !!****f* m_fftcore/unmpiswitch
2664 : !! NAME
2665 : !! unmpiswitch
2666 : !!
2667 : !! FUNCTION
2668 : !!
2669 : !! INPUTS
2670 : !!
2671 : !! OUTPUT
2672 : !!
2673 : !! SOURCE
2674 :
2675 1207862 : pure subroutine unmpiswitch(j3,n1dfft,Jp2st,J2st,lot,n1,nd2proc,nd3proc,nproc,ioption,zw,zmpi1)
2676 :
2677 : !Arguments ------------------------------------
2678 : integer,intent(in) :: j3,n1dfft,lot,n1,nd2proc,nd3proc,nproc,ioption
2679 : integer,intent(inout) :: Jp2st,J2st
2680 : real(dp),intent(in) :: zw(2,lot,n1)
2681 : real(dp),intent(inout) :: zmpi1(2,n1,nd2proc,nd3proc,nproc)
2682 :
2683 : !Local variables-------------------------------
2684 : integer :: i1,jp2,j2,ind,jjp2,mfft,jj2
2685 : ! *************************************************************************
2686 :
2687 1207862 : mfft=0
2688 1207862 : if (ioption == 2) then
2689 2347290 : do Jp2=Jp2st,nproc
2690 19093694 : do J2=J2st,nd2proc
2691 17954266 : mfft=mfft+1
2692 17954266 : if (mfft.gt.n1dfft) then
2693 275482 : Jp2st=Jp2
2694 275482 : J2st=J2
2695 275482 : return
2696 : end if
2697 508692864 : do I1=1,n1
2698 489874652 : zmpi1(1,I1,J2,j3,Jp2)=zw(1,mfft,I1)
2699 507553436 : zmpi1(2,I1,J2,j3,Jp2)=zw(2,mfft,I1)
2700 : end do
2701 : end do
2702 2071808 : J2st=1
2703 : end do
2704 :
2705 : else
2706 0 : do Jp2=Jp2st,nproc
2707 0 : do J2=J2st,nd2proc
2708 0 : mfft=mfft+1
2709 0 : if (mfft.gt.n1dfft) then
2710 0 : Jp2st=Jp2
2711 0 : J2st=J2
2712 0 : return
2713 : end if
2714 0 : ind=(Jp2-1) * nd2proc + J2
2715 0 : jj2=(ind-1)/nproc +1
2716 :
2717 : !jjp2=modulo(ind,nproc) +1
2718 0 : jjp2=modulo(ind-1,nproc)+1
2719 :
2720 0 : do I1=1,n1
2721 0 : zmpi1(1,I1,jj2,j3,jjp2)=zw(1,mfft,I1)
2722 0 : zmpi1(2,I1,jj2,j3,jjp2)=zw(2,mfft,I1)
2723 : end do
2724 : end do
2725 0 : J2st=1
2726 : end do
2727 : end if
2728 :
2729 : end subroutine unmpiswitch
2730 : !!***
2731 :
2732 : !----------------------------------------------------------------------
2733 :
2734 : !!****f* m_fftcore/unmpiswitch_cent
2735 : !! NAME
2736 : !! unmpiswitch_cent
2737 : !!
2738 : !! FUNCTION
2739 : !!
2740 : !! INPUTS
2741 : !!
2742 : !! OUTPUT
2743 : !!
2744 : !! SOURCE
2745 :
2746 9179512 : pure subroutine unmpiswitch_cent(j3,n1dfft,Jp2stf,J2stf,lot,max1,md1,m1,n1,md2proc,nd3proc,nproc,ioption,zw,zmpi1)
2747 :
2748 : !Arguments ------------------------------------
2749 : integer,intent(in) :: j3,n1dfft,lot,max1,md1,m1,n1,md2proc,nd3proc,nproc,ioption
2750 : integer,intent(inout) :: Jp2stf,J2stf
2751 : real(dp),intent(inout) :: zmpi1(2,md1,md2proc,nd3proc,nproc)
2752 : real(dp),intent(in) :: zw(2,lot,n1)
2753 :
2754 : !Local variables-------------------------------
2755 : integer :: mfft,Jp2,J2,I1,ind,jj2,jjp2
2756 : ! *************************************************************************
2757 :
2758 9179512 : mfft=0
2759 :
2760 9179512 : if (ioption == 2) then
2761 0 : do Jp2=Jp2stf,nproc
2762 0 : do J2=J2stf,md2proc
2763 0 : mfft=mfft+1
2764 :
2765 0 : if (mfft.gt.n1dfft) then
2766 0 : Jp2stf=Jp2
2767 0 : J2stf=J2
2768 0 : return
2769 : end if
2770 :
2771 : ! Here, zero and positive frequencies
2772 0 : do I1=1,max1+1
2773 0 : zmpi1(1,I1,J2,j3,Jp2)=zw(1,mfft,I1)
2774 0 : zmpi1(2,I1,J2,j3,Jp2)=zw(2,mfft,I1)
2775 : end do
2776 :
2777 : ! Here, negative frequencies
2778 0 : do I1=max1+2,m1
2779 0 : zmpi1(1,I1,J2,j3,Jp2)=zw(1,mfft,I1+n1-m1)
2780 0 : zmpi1(2,I1,J2,j3,Jp2)=zw(2,mfft,I1+n1-m1)
2781 : end do
2782 :
2783 : end do
2784 0 : J2stf=1
2785 : end do
2786 :
2787 : else
2788 25525700 : do Jp2=Jp2stf,nproc
2789 107067504 : do J2=J2stf,md2proc
2790 90721316 : mfft=mfft+1
2791 90721316 : if (mfft.gt.n1dfft) then
2792 320636 : Jp2stf=Jp2
2793 320636 : J2stf=J2
2794 320636 : return
2795 : end if
2796 90400680 : ind=(Jp2-1) * md2proc + J2
2797 90400680 : jj2=(ind-1)/nproc +1
2798 :
2799 : !jjp2=modulo(ind,nproc) +1
2800 90400680 : jjp2=modulo(ind-1,nproc)+1
2801 :
2802 : ! Here, zero and positive frequencies
2803 626085608 : do I1=1,max1+1
2804 535684928 : zmpi1(1,I1,Jj2,j3,Jjp2)=zw(1,mfft,I1)
2805 626085608 : zmpi1(2,I1,Jj2,j3,Jjp2)=zw(2,mfft,I1)
2806 : end do
2807 :
2808 : ! Here, negative frequencies
2809 542520640 : do I1=max1+2,m1
2810 435773772 : zmpi1(1,I1,Jj2,j3,Jjp2)=zw(1,mfft,I1+n1-m1)
2811 526174452 : zmpi1(2,I1,Jj2,j3,Jjp2)=zw(2,mfft,I1+n1-m1)
2812 : end do
2813 : end do
2814 25205064 : J2stf=1
2815 : end do
2816 : end if
2817 :
2818 : end subroutine unmpiswitch_cent
2819 : !!***
2820 :
2821 : !----------------------------------------------------------------------
2822 :
2823 : !!****f* m_fftcore/unscramble
2824 : !! NAME
2825 : !! unscramble
2826 : !!
2827 : !! FUNCTION
2828 : !!
2829 : !! INPUTS
2830 : !! i1
2831 : !! j2
2832 : !! lot=Cache blocking factor.
2833 : !! n1dfft=Number of 1D FFTs to perform
2834 : !! md1,n3,md2proc,nnd3
2835 : !! zmpi2(2,md1,md2proc,nnd3)
2836 : !!
2837 : !! OUTPUT
2838 : !! zw(2,lot,n3)= cache work array
2839 : !!
2840 : !! SOURCE
2841 :
2842 5629311 : pure subroutine unscramble(i1,j2,lot,n1dfft,md1,n3,md2proc,nnd3,zmpi2,zw)
2843 :
2844 : !Arguments ------------------------------------
2845 : integer,intent(in) :: i1,j2,lot,n1dfft,md1,n3,md2proc,nnd3
2846 : real(dp),intent(in) :: zmpi2(2,md1,md2proc,nnd3)
2847 : real(dp),intent(inout) :: zw(2,lot,n3)
2848 :
2849 : !Local variables-------------------------------
2850 : !scalars
2851 : integer :: i,i3
2852 : ! *************************************************************************
2853 :
2854 139400815 : do i3=1,n3
2855 1600734167 : do i=0,n1dfft-1
2856 1461333352 : zw(1,i+1,i3)=zmpi2(1,i1+i,j2,i3)
2857 1595104856 : zw(2,i+1,i3)=zmpi2(2,i1+i,j2,i3)
2858 : end do
2859 : end do
2860 :
2861 5629311 : end subroutine unscramble
2862 : !!***
2863 :
2864 : !----------------------------------------------------------------------
2865 :
2866 : !!****f* m_fftcore/unswitch
2867 : !! NAME
2868 : !! unswitch
2869 : !!
2870 : !! FUNCTION
2871 : !!
2872 : !! INPUTS
2873 : !! n1dfft=Number of 1D FFTs
2874 : !! n2=Dimension of the transform along y
2875 : !! lot=Cache blocking factor.
2876 : !! n1=Dimension of the transform along x.
2877 : !! lzt
2878 : !! zw(2,lot,n2)=Cache work array
2879 : !!
2880 : !! OUTPUT
2881 : !! zt(2,lzt,n1)
2882 : !!
2883 : !! SOURCE
2884 :
2885 1201940 : pure subroutine unswitch(n1dfft,n2,lot,n1,lzt,zw,zt)
2886 :
2887 : !Arguments ------------------------------------
2888 : integer,intent(in) :: n1dfft,n2,lot,n1,lzt
2889 : real(dp),intent(in) :: zw(2,lot,n2)
2890 : real(dp),intent(inout) :: zt(2,lzt,n1)
2891 :
2892 : !Local variables-------------------------------
2893 : integer :: i,j
2894 : ! *************************************************************************
2895 :
2896 18833000 : do j=1,n1dfft
2897 504686164 : do i=1,n2
2898 485853164 : zt(1,i,j)=zw(1,j,i)
2899 503484224 : zt(2,i,j)=zw(2,j,i)
2900 : end do
2901 : end do
2902 :
2903 1201940 : end subroutine unswitch
2904 : !!***
2905 :
2906 : !----------------------------------------------------------------------
2907 :
2908 : !!****f* m_fftcore/unswitch_cent
2909 : !! NAME
2910 : !! unswitch_cent
2911 : !!
2912 : !! FUNCTION
2913 : !!
2914 : !! INPUTS
2915 : !! n1dfft=Number of 1D FFTs to perform
2916 : !! max2=Max G_y in the small box enclosing the G-sphere.
2917 : !! m2=Size of the small box enclosing the G-sphere along y
2918 : !! n2=Dimension of the transform along y
2919 : !! lot=Cache blocking factor.
2920 : !! n1=Dimension of the transform along x
2921 : !! lzt
2922 : !! zw(2,lot,n2)=Cache working array
2923 : !!
2924 : !! OUTPUT
2925 : !! zt(2,lzt,n1)
2926 : !!
2927 : !! SOURCE
2928 :
2929 9503572 : pure subroutine unswitch_cent(n1dfft,max2,m2,n2,lot,n1,lzt,zw,zt)
2930 :
2931 : !Arguments ------------------------------------
2932 : integer,intent(in) :: n1dfft,max2,m2,n2,lot,n1,lzt
2933 : real(dp),intent(in) :: zw(2,lot,n2)
2934 : real(dp),intent(inout) :: zt(2,lzt,n1)
2935 :
2936 : !Local variables-------------------------------
2937 : integer :: i,j
2938 : ! *************************************************************************
2939 :
2940 : ! Here, zero and positive frequencies
2941 198521796 : do j=1,n1dfft
2942 1376154088 : do i=1,max2+1
2943 1177632292 : zt(1,i,j)=zw(1,j,i)
2944 1366650516 : zt(2,i,j)=zw(2,j,i)
2945 : end do
2946 : end do
2947 :
2948 : ! Here, negative frequencies
2949 9503572 : if(m2>=max2+2)then
2950 198521796 : do j=1,n1dfft
2951 1124123960 : do i=max2+2,m2
2952 925602164 : zt(1,i,j)=zw(1,j,i+n2-m2)
2953 1114620388 : zt(2,i,j)=zw(2,j,i+n2-m2)
2954 : end do
2955 : end do
2956 : end if
2957 :
2958 9503572 : end subroutine unswitch_cent
2959 : !!***
2960 :
2961 : !----------------------------------------------------------------------
2962 :
2963 : !!****f* m_fftcore/unswitchreal
2964 : !! NAME
2965 : !! unswitchreal
2966 : !!
2967 : !! FUNCTION
2968 : !!
2969 : !! INPUTS
2970 : !! n1dfft=Number of 1D FFTs to perform
2971 : !! n2=Dimension of the transform along y
2972 : !! n2eff=
2973 : !! lot=Cache blocking factor.
2974 : !! n1zt
2975 : !! lzt
2976 : !! zw(2,lot,n2)=Cache working array
2977 : !!
2978 : !! OUTPUT
2979 : !! zt(2,lzt,n1)
2980 : !!
2981 : !! SOURCE
2982 :
2983 5922 : pure subroutine unswitchreal(n1dfft,n2,n2eff,lot,n1zt,lzt,zw,zt)
2984 :
2985 : !Arguments ------------------------------------
2986 : integer,intent(in) :: n1dfft,n2,n2eff,lot,n1zt,lzt
2987 : real(dp),intent(in) :: zw(2,lot,n2)
2988 : real(dp),intent(inout) :: zt(2,lzt,n1zt)
2989 :
2990 : !Local variables-------------------------------
2991 : integer :: i,j
2992 : ! *************************************************************************
2993 :
2994 : ! Decompose symmetric and antisymmetric parts
2995 67320 : do j=1,n1dfft
2996 61398 : zt(1,1,2*j-1)=zw(1,j,1)
2997 61398 : zt(2,1,2*j-1)=zero
2998 61398 : zt(1,1,2*j) =zw(2,j,1)
2999 67320 : zt(2,1,2*j) =zero
3000 : end do
3001 :
3002 205668 : do i=2,n2eff
3003 2155014 : do j=1,n1dfft
3004 1949346 : zt(1,i,2*j-1)= (zw(1,j,i)+zw(1,j,n2+2-i))*half
3005 1949346 : zt(2,i,2*j-1)= (zw(2,j,i)-zw(2,j,n2+2-i))*half
3006 1949346 : zt(1,i,2*j) = (zw(2,j,i)+zw(2,j,n2+2-i))*half
3007 2149092 : zt(2,i,2*j) =-(zw(1,j,i)-zw(1,j,n2+2-i))*half
3008 : end do
3009 : end do
3010 :
3011 5922 : end subroutine unswitchreal
3012 : !!***
3013 :
3014 : !----------------------------------------------------------------------
3015 :
3016 : !!****f* m_fftcore/unswitchreal_cent
3017 : !! NAME
3018 : !! unswitchreal_cent
3019 : !!
3020 : !! FUNCTION
3021 : !!
3022 : !! INPUTS
3023 : !! n1dfft=Number of 1D FFTs to perform
3024 : !! max2=Max G_y in the small box enclosing the G-sphere.
3025 : !! n2=Dimension of the transform along y
3026 : !! lot=Cache blocking factor.
3027 : !! n1zt
3028 : !! lzt
3029 : !! zw(2,lot,n2)=Cache working array
3030 : !!
3031 : !! OUTPUT
3032 : !! zt(2,lzt,n1)
3033 : !!
3034 : !! SOURCE
3035 :
3036 15052 : pure subroutine unswitchreal_cent(n1dfft,max2,n2,lot,n1zt,lzt,zw,zt)
3037 :
3038 : !Arguments ------------------------------------
3039 : integer,intent(in) :: n1dfft,max2,n2,lot,n1zt,lzt
3040 : real(dp),intent(in) :: zw(2,lot,n2)
3041 : real(dp),intent(inout) :: zt(2,lzt,n1zt)
3042 :
3043 : !Local variables-------------------------------
3044 : integer :: i,j
3045 : ! *************************************************************************
3046 :
3047 179056 : do j=1,n1dfft
3048 164004 : zt(1,1,2*j-1)=zw(1,j,1)
3049 164004 : zt(2,1,2*j-1)=zero
3050 164004 : zt(1,1,2*j) =zw(2,j,1)
3051 179056 : zt(2,1,2*j) =zero
3052 : end do
3053 :
3054 333112 : do i=2,max2+1
3055 3721932 : do j=1,n1dfft
3056 3388820 : zt(1,i,2*j-1)= (zw(1,j,i)+zw(1,j,n2+2-i))*half
3057 3388820 : zt(2,i,2*j-1)= (zw(2,j,i)-zw(2,j,n2+2-i))*half
3058 3388820 : zt(1,i,2*j) = (zw(2,j,i)+zw(2,j,n2+2-i))*half
3059 3706880 : zt(2,i,2*j) =-(zw(1,j,i)-zw(1,j,n2+2-i))*half
3060 : end do
3061 : end do
3062 :
3063 : ! Here, zero and positive frequencies
3064 : ! do 90,j=1,n1dfft
3065 : ! do 90,i=1,max2+1
3066 : ! zt(1,i,j)=zw(1,j,i)
3067 : ! zt(2,i,j)=zw(2,j,i)
3068 : !90 continue
3069 :
3070 : ! Here, negative frequencies
3071 : ! if(m2>=max2+2)then
3072 : ! do 110,j=1,n1dfft
3073 : ! do 110,i=max2+2,m2
3074 : ! zt(1,i,j)=zw(1,j,i+n2-m2)
3075 : ! zt(2,i,j)=zw(2,j,i+n2-m2)
3076 : !110 continue
3077 : ! end if
3078 :
3079 15052 : end subroutine unswitchreal_cent
3080 : !!***
3081 :
3082 : !----------------------------------------------------------------------
3083 :
3084 : !!****f* m_fftcore/mpiswitch
3085 : !! NAME
3086 : !! mpiswitch
3087 : !!
3088 : !! FUNCTION
3089 : !!
3090 : !! INPUTS
3091 : !!
3092 : !! OUTPUT
3093 : !!
3094 : !! SOURCE
3095 :
3096 1165091 : pure subroutine mpiswitch(j3,n1dfft,Jp2st,J2st,lot,n1,nd2proc,nd3proc,nproc,ioption,zmpi1,zw)
3097 :
3098 : !Arguments ------------------------------------
3099 : integer,intent(in) :: j3,n1dfft,lot,n1,nd2proc,nd3proc,nproc,ioption
3100 : integer,intent(inout) :: Jp2st,J2st
3101 : real(dp),intent(in) :: zmpi1(2,n1,nd2proc,nd3proc,nproc)
3102 : real(dp),intent(inout) :: zw(2,lot,n1)
3103 :
3104 : !Local variables-------------------------------
3105 : integer :: Jp2,J2,I1,ind,jj2,mfft,jjp2
3106 : ! *************************************************************************
3107 1165091 : mfft=0
3108 :
3109 1165091 : if (ioption /= 1) then
3110 2277840 : do Jp2=Jp2st,nproc
3111 18124028 : do J2=J2st,nd2proc
3112 17011279 : mfft=mfft+1
3113 17011279 : if (mfft.gt.n1dfft) then
3114 244558 : Jp2st=Jp2
3115 244558 : J2st=J2
3116 244558 : return
3117 : end if
3118 475615703 : do I1=1,n1
3119 457736233 : zw(1,mfft,I1)=zmpi1(1,I1,J2,j3,Jp2)
3120 474502954 : zw(2,mfft,I1)=zmpi1(2,I1,J2,j3,Jp2)
3121 : end do
3122 : end do
3123 2033282 : J2st=1
3124 : end do
3125 :
3126 : else
3127 0 : do Jp2=Jp2st,nproc
3128 0 : do J2=J2st,nd2proc
3129 0 : mfft=mfft+1
3130 0 : if (mfft.gt.n1dfft) then
3131 0 : Jp2st=Jp2
3132 0 : J2st=J2
3133 0 : return
3134 : end if
3135 0 : ind=(Jp2-1) * nd2proc + J2
3136 0 : jj2=(ind-1)/nproc +1
3137 :
3138 : !jjp2=modulo(ind,nproc) +1
3139 0 : jjp2=modulo(ind-1,nproc)+1
3140 :
3141 : !in other words: mfft=(jj2-1)*nproc+jjp2 (modulo case)
3142 : !instead of mfft=(Jjp2-1) * nd2proc + Jj2 (slice case)
3143 : !with 1<=jjp2<=nproc, jj2=1,nd2proc
3144 0 : do I1=1,n1
3145 : ! zw(1,mfft,I1)=zmpi1(1,I1,J2,j3,Jp2)
3146 : ! zw(2,mfft,I1)=zmpi1(2,I1,J2,j3,Jp2)
3147 0 : zw(1,mfft,I1)=zmpi1(1,I1,jj2,j3,jjp2)
3148 0 : zw(2,mfft,I1)=zmpi1(2,I1,jj2,j3,jjp2)
3149 : end do
3150 : end do
3151 0 : J2st=1
3152 : end do
3153 : end if
3154 :
3155 : end subroutine mpiswitch
3156 : !!***
3157 :
3158 : !----------------------------------------------------------------------
3159 :
3160 : !!****f* m_fftcore/mpiswitch_cent
3161 : !! NAME
3162 : !! mpiswitch_cent
3163 : !!
3164 : !! FUNCTION
3165 : !! Perform the local rotation
3166 : !!
3167 : !! input: I1,J2,j3,Jp2,(jp3)
3168 : !! output: J2,Jp2,I1,j3,(jp3)
3169 : !!
3170 : !! and fill the central region of the frequency spectrum with zeros
3171 : !!
3172 : !! INPUTS
3173 : !!
3174 : !! OUTPUT
3175 : !!
3176 : !! SOURCE
3177 :
3178 :
3179 10021215 : pure subroutine mpiswitch_cent(j3,n1dfft,Jp2stb,J2stb,lot,max1,md1,m1,n1,md2proc,&
3180 10021215 : nd3proc,nproc,ioption,zmpi1,zw,max2,m2,n2)
3181 :
3182 : !Arguments ------------------------------------
3183 : integer,intent(in) :: j3,n1dfft,lot,max1,md1,m1,n1,md2proc,nd3proc,nproc,ioption
3184 : integer,intent(in) :: m2,max2,n2
3185 : integer,intent(inout) :: Jp2stb,J2stb
3186 : real(dp),intent(in) :: zmpi1(2,md1,md2proc,nd3proc,nproc)
3187 : real(dp),intent(inout) :: zw(2,lot,n1)
3188 :
3189 : !Local variables-------------------------------
3190 : integer :: mfft,jp2,j2,jjp2,jj2,i1,ind
3191 : ! *************************************************************************
3192 :
3193 : ABI_UNUSED((/m2,max2,n2/))
3194 :
3195 10021215 : mfft=0
3196 :
3197 10021215 : if (ioption /= 1) then
3198 0 : do Jp2=Jp2stb,nproc
3199 0 : do J2=J2stb,md2proc
3200 :
3201 0 : mfft=mfft+1
3202 0 : if (mfft.gt.n1dfft) then
3203 0 : Jp2stb=Jp2
3204 0 : J2stb=J2
3205 : !ABI_WARNING("Returning from mpiswithc_cent")
3206 0 : return
3207 : end if
3208 :
3209 : ! Here, zero and positive frequencies
3210 : ! In zmpi1, they are stored from 1 to max1+1
3211 0 : do I1=1,max1+1
3212 0 : zw(1,mfft,I1)=zmpi1(1,I1,J2,j3,Jp2)
3213 0 : zw(2,mfft,I1)=zmpi1(2,I1,J2,j3,Jp2)
3214 : end do
3215 :
3216 : ! Fill the center region with zeros
3217 0 : do I1=max1+2,n1-m1+max1+1
3218 0 : zw(1,mfft,I1)=zero
3219 0 : zw(2,mfft,I1)=zero
3220 : end do
3221 :
3222 : ! Here, negative frequencies
3223 : ! In zmpi1, they are stored from 1 to m1half
3224 0 : do I1=max1+2,m1
3225 0 : zw(1,mfft,I1+n1-m1)=zmpi1(1,I1,J2,j3,Jp2)
3226 0 : zw(2,mfft,I1+n1-m1)=zmpi1(2,I1,J2,j3,Jp2)
3227 : end do
3228 : end do
3229 0 : J2stb=1
3230 : end do
3231 :
3232 : else
3233 27644968 : do Jp2=Jp2stb,nproc
3234 116430980 : do J2=J2stb,md2proc
3235 :
3236 98807227 : mfft=mfft+1
3237 98807227 : if (mfft.gt.n1dfft) then
3238 397780 : Jp2stb=Jp2
3239 397780 : J2stb=J2
3240 : !ABI_WARNING("Returning from mpiswithc_cent")
3241 397780 : return
3242 : end if
3243 :
3244 98409447 : ind=(Jp2-1) * md2proc + J2
3245 98409447 : jj2=(ind-1)/nproc +1
3246 :
3247 : !jjp2=modulo(ind,nproc) +1
3248 98409447 : jjp2=modulo(ind-1,nproc)+1
3249 :
3250 : ! I gather consecutive I2 indexes in mfft in the modulo case
3251 : ! Here, zero and positive frequencies
3252 : ! In zmpi1, they are stored from 1 to max1+1
3253 689750779 : do I1=1,max1+1
3254 591341332 : zw(1,mfft,I1)=zmpi1(1,I1,Jj2,j3,Jjp2)
3255 689750779 : zw(2,mfft,I1)=zmpi1(2,I1,Jj2,j3,Jjp2)
3256 : end do
3257 :
3258 : ! Fill the center region with zeros
3259 1355559091 : do I1=max1+2,n1-m1+max1+1
3260 1257149644 : zw(1,mfft,I1)=zero
3261 1355559091 : zw(2,mfft,I1)=zero
3262 : end do
3263 :
3264 : ! Here, negative frequencies
3265 : ! In zmpi1, they are stored from 1 to m1half
3266 599339553 : do I1=max1+2,m1
3267 483306353 : zw(1,mfft,I1+n1-m1)=zmpi1(1,I1,Jj2,j3,Jjp2)
3268 581715800 : zw(2,mfft,I1+n1-m1)=zmpi1(2,I1,Jj2,j3,Jjp2)
3269 : end do
3270 :
3271 : end do
3272 27247188 : J2stb=1
3273 : end do
3274 : end if
3275 :
3276 : end subroutine mpiswitch_cent
3277 : !!***
3278 :
3279 : !----------------------------------------------------------------------
3280 :
3281 : !!****f* m_fftcore/mpifft_fg2dbox
3282 : !! NAME
3283 : !! mpifft_fg2dbox
3284 : !!
3285 : !! FUNCTION
3286 : !!
3287 : !! INPUTS
3288 : !!
3289 : !! OUTPUT
3290 : !!
3291 : !! SOURCE
3292 :
3293 67683 : pure subroutine mpifft_fg2dbox(nfft,ndat,fofg,n1,n2,n3,n4,nd2proc,n6,fftn2_distrib,ffti2_local,me_fft,workf)
3294 :
3295 : !Arguments ------------------------------------
3296 : !scalars
3297 : integer,intent(in) :: nfft,ndat,n1,n2,n3,n4,nd2proc,n6,me_fft
3298 : !arrays
3299 : integer,intent(in) :: fftn2_distrib(n2),ffti2_local(n2)
3300 : real(dp),intent(in) :: fofg(2,nfft*ndat)
3301 : real(dp),intent(inout) :: workf(2,n4,n6,nd2proc*ndat)
3302 :
3303 : !Local variables-------------------------------
3304 : integer :: idat,i1,i2,i3,i2_local,i2_ldat,fgbase
3305 : ! *************************************************************************
3306 :
3307 135374 : do idat=1,ndat
3308 1202910 : do i3=1,n3
3309 22358765 : do i2=1,n2
3310 22291074 : if (fftn2_distrib(i2) == me_fft) then
3311 15318706 : i2_local = ffti2_local(i2)
3312 15318706 : i2_ldat = i2_local + (idat-1) * nd2proc
3313 15318706 : fgbase= n1*(i2_local-1 + nd2proc*(i3-1)) + (idat-1) * nfft
3314 377619812 : do i1=1,n1
3315 362301106 : workf(1,i1,i3,i2_ldat)=fofg(1,i1+fgbase)
3316 377619812 : workf(2,i1,i3,i2_ldat)=fofg(2,i1+fgbase)
3317 : end do
3318 : end if
3319 : end do
3320 : end do
3321 : end do
3322 :
3323 67683 : end subroutine mpifft_fg2dbox
3324 : !!***
3325 :
3326 : !----------------------------------------------------------------------
3327 :
3328 : !!****f* m_fftcore/mpifft_fg2dbox_dpc
3329 : !! NAME
3330 : !! mpifft_fg2dbox_dpc
3331 : !!
3332 : !! FUNCTION
3333 : !!
3334 : !! INPUTS
3335 : !!
3336 : !! OUTPUT
3337 : !!
3338 : !! SOURCE
3339 :
3340 0 : pure subroutine mpifft_fg2dbox_dpc(nfft,ndat,fofg,n1,n2,n3,n4,nd2proc,n6,fftn2_distrib,ffti2_local,me_fft,workf)
3341 :
3342 : !Arguments ------------------------------------
3343 : !scalars
3344 : integer,intent(in) :: nfft,ndat,n1,n2,n3,n4,nd2proc,n6,me_fft
3345 : !arrays
3346 : integer,intent(in) :: fftn2_distrib(n2),ffti2_local(n2)
3347 : real(dp),intent(in) :: fofg(2,nfft*ndat)
3348 : complex(dp),intent(inout) :: workf(n4,n6,nd2proc*ndat)
3349 :
3350 : !Local variables-------------------------------
3351 : integer :: idat,i1,i2,i3,i2_local,i2_ldat,fgbase
3352 : ! *************************************************************************
3353 :
3354 0 : do idat=1,ndat
3355 0 : do i3=1,n3
3356 0 : do i2=1,n2
3357 0 : if (fftn2_distrib(i2) == me_fft) then
3358 0 : i2_local = ffti2_local(i2)
3359 0 : i2_ldat = i2_local + (idat-1) * nd2proc
3360 0 : fgbase= n1*(i2_local-1 + nd2proc*(i3-1)) + (idat-1) * nfft
3361 0 : do i1=1,n1
3362 0 : workf(i1,i3,i2_ldat)=CMPLX(fofg(1,i1+fgbase), fofg(2,i1+fgbase), kind=dp)
3363 : end do
3364 : end if
3365 : end do
3366 : end do
3367 : end do
3368 :
3369 0 : end subroutine mpifft_fg2dbox_dpc
3370 : !!***
3371 :
3372 : !----------------------------------------------------------------------
3373 :
3374 : !!****f* m_fftcore/mpifft_dbox2fg
3375 : !! NAME
3376 : !! mpifft_dbox2fg
3377 : !!
3378 : !! FUNCTION
3379 : !!
3380 : !! INPUTS
3381 : !!
3382 : !! OUTPUT
3383 : !!
3384 : !! SOURCE
3385 :
3386 67437 : pure subroutine mpifft_dbox2fg(n1,n2,n3,n4,nd2proc,n6,ndat,fftn2_distrib,ffti2_local,me_fft,workf,nfft,fofg)
3387 :
3388 : !Arguments ------------------------------------
3389 : !scalars
3390 : integer,intent(in) :: n1,n2,n3,n4,nd2proc,n6,ndat,me_fft,nfft
3391 : !arrays
3392 : integer,intent(in) :: fftn2_distrib(n2),ffti2_local(n2)
3393 : real(dp),intent(in) :: workf(2,n4,n6,nd2proc*ndat)
3394 : real(dp),intent(out) :: fofg(2,nfft*ndat)
3395 :
3396 : !Local variables-------------------------------
3397 : integer :: idat,i1,i2,i3,i2_local,i2_ldat,fgbase
3398 : real(dp) :: xnorm
3399 : ! *************************************************************************
3400 :
3401 67437 : xnorm=one/dble(n1*n2*n3)
3402 :
3403 : ! Transfer fft output to the original fft box
3404 134882 : do idat=1,ndat
3405 1236953 : do i2=1,n2
3406 1169516 : if( fftn2_distrib(i2) == me_fft) then
3407 895075 : i2_local = ffti2_local(i2)
3408 895075 : i2_ldat = i2_local + (idat-1) * nd2proc
3409 17511538 : do i3=1,n3
3410 16616463 : fgbase = n1*(i2_local - 1 + nd2proc*(i3-1)) + (idat - 1) * nfft
3411 440298291 : do i1=1,n1
3412 422786753 : fofg(1,i1+fgbase)=workf(1,i1,i3,i2_ldat)*xnorm
3413 439403216 : fofg(2,i1+fgbase)=workf(2,i1,i3,i2_ldat)*xnorm
3414 : end do
3415 : end do
3416 : end if
3417 : end do
3418 : end do
3419 :
3420 67437 : end subroutine mpifft_dbox2fg
3421 : !!***
3422 :
3423 : !----------------------------------------------------------------------
3424 :
3425 : !!****f* m_fftcore/mpifft_dbox2fg_dpc
3426 : !! NAME
3427 : !! mpifft_dbox2fg_dpc
3428 : !!
3429 : !! FUNCTION
3430 : !!
3431 : !! INPUTS
3432 : !!
3433 : !! OUTPUT
3434 : !!
3435 : !! SOURCE
3436 :
3437 0 : pure subroutine mpifft_dbox2fg_dpc(n1,n2,n3,n4,nd2proc,n6,ndat,fftn2_distrib,ffti2_local,me_fft,workf,nfft,fofg)
3438 :
3439 : !Arguments ------------------------------------
3440 : !scalars
3441 : integer,intent(in) :: n1,n2,n3,n4,nd2proc,n6,ndat,me_fft,nfft
3442 : !arrays
3443 : integer,intent(in) :: fftn2_distrib(n2),ffti2_local(n2)
3444 : complex(dp),intent(in) :: workf(n4,n6,nd2proc*ndat)
3445 : real(dp),intent(out) :: fofg(2,nfft*ndat)
3446 :
3447 : !Local variables-------------------------------
3448 : integer :: idat,i1,i2,i3,i2_local,i2_ldat,fgbase
3449 : real(dp) :: xnorm
3450 : ! *************************************************************************
3451 :
3452 0 : xnorm=one/dble(n1*n2*n3)
3453 :
3454 : ! Transfer fft output to the original fft box
3455 0 : do idat=1,ndat
3456 0 : do i2=1,n2
3457 0 : if( fftn2_distrib(i2) == me_fft) then
3458 0 : i2_local = ffti2_local(i2)
3459 0 : i2_ldat = i2_local + (idat-1) * nd2proc
3460 0 : do i3=1,n3
3461 0 : fgbase = n1*(i2_local - 1 + nd2proc*(i3-1)) + (idat - 1) * nfft
3462 0 : do i1=1,n1
3463 0 : fofg(1,i1+fgbase)=REAL (workf(i1,i3,i2_ldat))*xnorm
3464 0 : fofg(2,i1+fgbase)=AIMAG(workf(i1,i3,i2_ldat))*xnorm
3465 : end do
3466 : end do
3467 : end if
3468 : end do
3469 : end do
3470 :
3471 0 : end subroutine mpifft_dbox2fg_dpc
3472 : !!***
3473 :
3474 : !----------------------------------------------------------------------
3475 :
3476 : !!****f* m_fftcore/mpifft_dbox2fr
3477 : !! NAME
3478 : !! mpifft_dbox2fr
3479 : !!
3480 : !! FUNCTION
3481 : !!
3482 : !! INPUTS
3483 : !!
3484 : !! OUTPUT
3485 : !!
3486 : !! SOURCE
3487 :
3488 67683 : pure subroutine mpifft_dbox2fr(n1,n2,n3,n4,n5,nd3proc,ndat,fftn3_distrib,ffti3_local,me_fft,workr,cplex,nfft,fofr)
3489 :
3490 : !Arguments ------------------------------------
3491 : !scalars
3492 : integer,intent(in) :: n1,n2,n3,n4,n5,nd3proc,ndat,me_fft,nfft,cplex
3493 : !!arrays
3494 : integer,intent(in) :: fftn3_distrib(n3),ffti3_local(n3)
3495 : real(dp),intent(in) :: workr(2,n4,n5,nd3proc*ndat)
3496 : real(dp),intent(out) :: fofr(cplex*nfft*ndat)
3497 :
3498 : !Local variables-------------------------------
3499 : integer :: idat,i1,i2,i3,i3_local,i3_ldat,frbase
3500 : ! *************************************************************************
3501 :
3502 : select case (cplex)
3503 : case (1)
3504 :
3505 135352 : do idat=1,ndat
3506 1202318 : do i3=1,n3
3507 1134644 : if( fftn3_distrib(i3) == me_fft) then
3508 874750 : i3_local = ffti3_local(i3)
3509 874750 : i3_ldat = i3_local + (idat - 1) * nd3proc
3510 16150796 : do i2=1,n2
3511 15276046 : frbase=n1*(i2-1+n2*(i3_local-1)) + (idat - 1) * nfft
3512 374780982 : do i1=1,n1
3513 373906232 : fofr(i1+frbase)=workr(1,i1,i2,i3_ldat)
3514 : end do
3515 : end do
3516 : end if
3517 : end do
3518 : end do
3519 :
3520 : case (2)
3521 :
3522 22 : do idat=1,ndat
3523 592 : do i3=1,n3
3524 583 : if (fftn3_distrib(i3) == me_fft) then
3525 570 : i3_local = ffti3_local(i3)
3526 570 : i3_ldat = i3_local + (idat - 1) * nd3proc
3527 43230 : do i2=1,n2
3528 42660 : frbase=2*n1*(i2-1+n2*(i3_local-1)) + (idat - 1) * cplex * nfft
3529 : !if (frbase > cplex*nfft*ndat - 2*n1) then
3530 : ! write(std_out,*)i2,i3_local,frbase,cplex*nfft*ndat
3531 : ! ABI_ERROR("frbase")
3532 : !end if
3533 3714150 : do i1=1,n1
3534 3670920 : fofr(2*i1-1+frbase)=workr(1,i1,i2,i3_ldat)
3535 3713580 : fofr(2*i1 +frbase)=workr(2,i1,i2,i3_ldat)
3536 : end do
3537 : end do
3538 : end if
3539 : end do
3540 : end do
3541 :
3542 : case default
3543 : !ABI_BUG("Wrong cplex")
3544 67683 : fofr = huge(one)
3545 : end select
3546 :
3547 67683 : end subroutine mpifft_dbox2fr
3548 : !!***
3549 :
3550 : !----------------------------------------------------------------------
3551 :
3552 : !!****f* m_fftcore/mpifft_dbox2fr_dpc
3553 : !! NAME
3554 : !! mpifft_dbox2fr_dpc
3555 : !!
3556 : !! FUNCTION
3557 : !!
3558 : !! INPUTS
3559 : !!
3560 : !! OUTPUT
3561 : !!
3562 : !! SOURCE
3563 :
3564 0 : pure subroutine mpifft_dbox2fr_dpc(n1,n2,n3,n4,n5,nd3proc,ndat,fftn3_distrib,ffti3_local,me_fft,workr,cplex,nfft,fofr)
3565 :
3566 : !Arguments ------------------------------------
3567 : !scalars
3568 : integer,intent(in) :: n1,n2,n3,n4,n5,nd3proc,ndat,me_fft,nfft,cplex
3569 : !!arrays
3570 : integer,intent(in) :: fftn3_distrib(n3),ffti3_local(n3)
3571 : complex(dp),intent(in) :: workr(n4,n5,nd3proc*ndat)
3572 : real(dp),intent(out) :: fofr(cplex*nfft*ndat)
3573 :
3574 : !Local variables-------------------------------
3575 : integer :: idat,i1,i2,i3,i3_local,i3_ldat,frbase
3576 : ! *************************************************************************
3577 :
3578 : select case (cplex)
3579 : case (1)
3580 :
3581 0 : do idat=1,ndat
3582 0 : do i3=1,n3
3583 0 : if( fftn3_distrib(i3) == me_fft) then
3584 0 : i3_local = ffti3_local(i3)
3585 0 : i3_ldat = i3_local + (idat - 1) * nd3proc
3586 0 : do i2=1,n2
3587 0 : frbase=n1*(i2-1+n2*(i3_local-1)) + (idat - 1) * nfft
3588 0 : do i1=1,n1
3589 0 : fofr(i1+frbase)=REAL(workr(i1,i2,i3_ldat))
3590 : end do
3591 : end do
3592 : end if
3593 : end do
3594 : end do
3595 :
3596 : case (2)
3597 :
3598 0 : do idat=1,ndat
3599 0 : do i3=1,n3
3600 0 : if (fftn3_distrib(i3) == me_fft) then
3601 0 : i3_local = ffti3_local(i3)
3602 0 : i3_ldat = i3_local + (idat - 1) * nd3proc
3603 0 : do i2=1,n2
3604 0 : frbase=2*n1*(i2-1+n2*(i3_local-1)) + (idat - 1) * cplex * nfft
3605 0 : do i1=1,n1
3606 0 : fofr(2*i1-1+frbase)=REAL (workr(i1,i2,i3_ldat))
3607 0 : fofr(2*i1 +frbase)=AIMAG(workr(i1,i2,i3_ldat))
3608 : end do
3609 : end do
3610 : end if
3611 : end do
3612 : end do
3613 :
3614 : case default
3615 : !ABI_BUG("Wrong cplex")
3616 0 : fofr = huge(one)
3617 : end select
3618 :
3619 0 : end subroutine mpifft_dbox2fr_dpc
3620 : !!***
3621 :
3622 : !----------------------------------------------------------------------
3623 :
3624 : !!****f* m_fftcore/mpifft_fr2dbox
3625 : !! NAME
3626 : !! mpifft_fr2dbox
3627 : !!
3628 : !! FUNCTION
3629 : !!
3630 : !! INPUTS
3631 : !!
3632 : !! OUTPUT
3633 : !!
3634 : !! SOURCE
3635 :
3636 67437 : pure subroutine mpifft_fr2dbox(cplex,nfft,ndat,fofr,n1,n2,n3,n4,n5,nd3proc,fftn3_distrib,ffti3_local,me_fft,workr)
3637 :
3638 : !Arguments ------------------------------------
3639 : !scalars
3640 : integer,intent(in) :: cplex,nfft,ndat,n1,n2,n3,n4,n5,nd3proc,me_fft
3641 : !!arrays
3642 : integer,intent(in) :: fftn3_distrib(n3),ffti3_local(n3)
3643 : real(dp),intent(in) :: fofr(cplex*nfft*ndat)
3644 : real(dp),intent(inout) :: workr(2,n4,n5,nd3proc*ndat)
3645 :
3646 : !Local variables-------------------------------
3647 : integer :: idat,i1,i2,i3,i3_local,i3_ldat,frbase
3648 : ! *************************************************************************
3649 :
3650 : select case (cplex)
3651 : case (1)
3652 :
3653 134860 : do idat=1,ndat
3654 1236637 : do i3=1,n3
3655 1169209 : if( me_fft == fftn3_distrib(i3) ) then
3656 894729 : i3_local = ffti3_local(i3)
3657 894729 : i3_ldat = i3_local + (idat-1) * nd3proc
3658 17468532 : do i2=1,n2
3659 16573803 : frbase=n1*(i2-1+n2*(i3_local-1)) + (idat-1) * nfft
3660 436584365 : do i1=1,n1
3661 419115833 : workr(1,i1,i2,i3_ldat)=fofr(i1+frbase)
3662 435689636 : workr(2,i1,i2,i3_ldat)=zero
3663 : end do
3664 : end do
3665 : end if
3666 : end do
3667 : end do
3668 :
3669 : case (2)
3670 :
3671 22 : do idat=1,ndat
3672 592 : do i3=1,n3
3673 583 : if( me_fft == fftn3_distrib(i3) ) then
3674 570 : i3_local = ffti3_local(i3)
3675 570 : i3_ldat = i3_local + (idat-1) * nd3proc
3676 43230 : do i2=1,n2
3677 42660 : frbase=2*n1*(i2-1+n2*(i3_local-1)) + (idat-1) * cplex * nfft
3678 3714150 : do i1=1,n1
3679 3670920 : workr(1,i1,i2,i3_ldat)=fofr(2*i1-1+frbase)
3680 3713580 : workr(2,i1,i2,i3_ldat)=fofr(2*i1 +frbase)
3681 : end do
3682 : end do
3683 : end if
3684 : end do
3685 : end do
3686 :
3687 : case default
3688 : !ABI_BUG("Wrong cplex")
3689 67437 : workr = huge(one)
3690 : end select
3691 :
3692 67437 : end subroutine mpifft_fr2dbox
3693 : !!***
3694 :
3695 : !----------------------------------------------------------------------
3696 :
3697 : !!****f* m_fftcore/mpifft_fr2dbox_dpc
3698 : !! NAME
3699 : !! mpifft_fr2dbox_dpc
3700 : !!
3701 : !! FUNCTION
3702 : !!
3703 : !! INPUTS
3704 : !!
3705 : !! OUTPUT
3706 : !!
3707 : !! SOURCE
3708 :
3709 0 : pure subroutine mpifft_fr2dbox_dpc(cplex,nfft,ndat,fofr,n1,n2,n3,n4,n5,nd3proc,fftn3_distrib,ffti3_local,me_fft,workr)
3710 :
3711 : !Arguments ------------------------------------
3712 : !scalars
3713 : integer,intent(in) :: cplex,nfft,ndat,n1,n2,n3,n4,n5,nd3proc,me_fft
3714 : !!arrays
3715 : integer,intent(in) :: fftn3_distrib(n3),ffti3_local(n3)
3716 : real(dp),intent(in) :: fofr(cplex*nfft*ndat)
3717 : complex(dp),intent(inout) :: workr(n4,n5,nd3proc*ndat)
3718 :
3719 : !Local variables-------------------------------
3720 : integer :: idat,i1,i2,i3,i3_local,i3_ldat,frbase
3721 : ! *************************************************************************
3722 :
3723 : select case (cplex)
3724 : case (1)
3725 :
3726 0 : do idat=1,ndat
3727 0 : do i3=1,n3
3728 0 : if( me_fft == fftn3_distrib(i3) ) then
3729 0 : i3_local = ffti3_local(i3)
3730 0 : i3_ldat = i3_local + (idat-1) * nd3proc
3731 0 : do i2=1,n2
3732 0 : frbase=n1*(i2-1+n2*(i3_local-1)) + (idat-1) * nfft
3733 0 : do i1=1,n1
3734 0 : workr(i1,i2,i3_ldat)=CMPLX(fofr(i1+frbase), zero, kind=dp)
3735 : end do
3736 : end do
3737 : end if
3738 : end do
3739 : end do
3740 :
3741 : case (2)
3742 :
3743 0 : do idat=1,ndat
3744 0 : do i3=1,n3
3745 0 : if( me_fft == fftn3_distrib(i3) ) then
3746 0 : i3_local = ffti3_local(i3)
3747 0 : i3_ldat = i3_local + (idat-1) * nd3proc
3748 0 : do i2=1,n2
3749 0 : frbase=2*n1*(i2-1+n2*(i3_local-1)) + (idat-1) * cplex * nfft
3750 0 : do i1=1,n1
3751 0 : workr(i1,i2,i3_ldat)=CMPLX(fofr(2*i1-1+frbase), fofr(2*i1 +frbase), kind=dp)
3752 : end do
3753 : end do
3754 : end if
3755 : end do
3756 : end do
3757 :
3758 : case default
3759 : !ABI_BUG("Wrong cplex")
3760 0 : workr = huge(one)
3761 : end select
3762 :
3763 0 : end subroutine mpifft_fr2dbox_dpc
3764 : !!***
3765 :
3766 : !----------------------------------------------------------------------
3767 :
3768 : !!****f* m_fftcore/indfftrisc
3769 : !!
3770 : !! NAME
3771 : !! indfftrisc
3772 : !!
3773 : !! FUNCTION
3774 : !! Take the data for sphere boundary and list of planewave in sphere (kg_k), manipulate them
3775 : !! for convenient use in fourwf, and output them in indpw_k
3776 : !!
3777 : !! INPUTS
3778 : !! gbound(2*mgfft+4)=sphere boundary data
3779 : !! kg_k(3,npw_k)=reduced planewave coordinates
3780 : !! mgfft=maximum size of 1D FFTs
3781 : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
3782 : !! npw_k=number of G vectors in basis at this k point
3783 : !!
3784 : !! OUTPUT
3785 : !! indpw_k(4,npw_k)=array which gives fft box index for given basis sphere
3786 : !! in a representation that is directly usable by sg_fftrisc.f
3787 : !! ngb=number of FFTs along z
3788 : !!
3789 : !! SOURCE
3790 :
3791 117247689 : subroutine indfftrisc(gbound,indpw_k,kg_k,mgfft,ngb,ngfft,npw_k)
3792 :
3793 : !Arguments ------------------------------------
3794 : !scalars
3795 : integer,intent(in) :: mgfft,npw_k
3796 : integer,intent(out) :: ngb
3797 : !arrays
3798 : integer,intent(in) :: gbound(2*mgfft+4),kg_k(3,npw_k),ngfft(18)
3799 : integer,intent(out) :: indpw_k(4,npw_k)
3800 :
3801 : !Local variables-------------------------------
3802 : !scalars
3803 : integer :: g1,g2,i1,i2,i3,igb,index,ipw,n1,n2,n3
3804 : !arrays
3805 117247689 : integer,allocatable :: index2d(:,:)
3806 : ! *************************************************************************
3807 :
3808 117247689 : n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
3809 :
3810 : !First, generate a 2d index for each column of data
3811 468990756 : ABI_MALLOC(index2d,(n1,n2))
3812 36318395895 : index2d(:,:)=0
3813 117247689 : index=1
3814 117247689 : igb=3
3815 613473582 : do g2=0,gbound(2) ! g2max
3816 2567075530 : do g1=0,gbound(igb+1) ! g1max
3817 2070849637 : index2d(g1+1,g2+1)=index
3818 2567075530 : index=index+1
3819 : end do
3820 496225893 : if(gbound(igb)<=-1)then ! g1min
3821 1460826527 : do g1=gbound(igb)+n1,n1-1
3822 1063715045 : index2d(g1+1,g2+1)=index
3823 1460826527 : index=index+1
3824 : end do
3825 : end if
3826 613473582 : igb=igb+2
3827 : end do
3828 :
3829 117247689 : if(gbound(1)<=-1)then ! g2min
3830 504282407 : do g2=gbound(1)+n2,n2-1
3831 1397552686 : do g1=0,gbound(igb+1)
3832 1007899391 : index2d(g1+1,g2+1)=index
3833 1397552686 : index=index+1
3834 : end do
3835 389653295 : if(gbound(igb)<=-1)then
3836 1702060799 : do g1=gbound(igb)+n1,n1-1
3837 1324378791 : index2d(g1+1,g2+1)=index
3838 1702060799 : index=index+1
3839 : end do
3840 : end if
3841 504282407 : igb=igb+2
3842 : end do
3843 : end if
3844 :
3845 117247689 : ngb=index-1
3846 :
3847 :
3848 : !The 2d index has been generated
3849 : !Now, contract indpw_k(1,ipw) and indpw_k(2,ipw) into indpw_k(4,ipw)
3850 : !indpw_k(1,ipw) and indpw_k(2,ipw) are used to hold inverse of index2d,
3851 : !and for them, the second index does not fill 1:npw . It is only
3852 : !the number of z-transform FFTs.
3853 :
3854 : !$OMP PARALLEL DO PRIVATE(i1,i2,i3)
3855 31864812876 : do ipw=1,npw_k
3856 31747565187 : i1=kg_k(1,ipw); if(i1<0)i1=i1+n1 ; i1=i1+1
3857 31747565187 : i2=kg_k(2,ipw); if(i2<0)i2=i2+n2 ; i2=i2+1
3858 31747565187 : i3=kg_k(3,ipw); if(i3<0)i3=i3+n3 ; i3=i3+1
3859 31747565187 : indpw_k(4,ipw)=index2d(i1,i2)
3860 31864812876 : indpw_k(3,ipw)=i3
3861 : end do
3862 :
3863 2027861285 : do i1=1,n1
3864 36323241967 : do i2=1,n2
3865 34295380682 : index=index2d(i1,i2)
3866 36205994278 : if(index/=0)then
3867 5466842864 : indpw_k(1,index)=i1
3868 5466842864 : indpw_k(2,index)=i2
3869 : end if
3870 : end do
3871 : end do
3872 :
3873 117247689 : ABI_FREE(index2d)
3874 :
3875 117247689 : end subroutine indfftrisc
3876 : !!***
3877 :
3878 : !----------------------------------------------------------------------
3879 :
3880 : !!****f* m_fftcore/kpgsph
3881 : !! NAME
3882 : !! kpgsph
3883 : !!
3884 : !! FUNCTION
3885 : !! Use reciprocal space metric gmet(3,3) to set up the list
3886 : !! of G vectors inside a sphere out to $ (1/2)*(2*\pi*(k+G))^2=ecut $.
3887 : !! If mkmem=0 and mpw=0, then only count the number of planewaves
3888 : !!
3889 : !! INPUTS
3890 : !! ecut=planewave kinetic energy cutoff (hartrees)
3891 : !! exchn2n3d=if 1, n2 and n3 are exchanged
3892 : !! gmet(3,3)=reciprocal space metric (bohr^-2)
3893 : !! ikg=shift to be given to the location of the output data in the array kg
3894 : !! ikpt=number of the k-point
3895 : !! istwf_k=option parameter that describes the storage of wfs
3896 : !! kpt(3)=reduced coords of k point (in terms of recip latt vecs)
3897 : !! mkmem =maximum number of k points which can fit in core memory
3898 : !! mpi_enreg=information about MPI parallelization
3899 : !! mpw=maximum number of planewaves as dimensioned in calling routine
3900 : !!
3901 : !! OUTPUT
3902 : !! kg(3,mpw*mkmem)=dimensionless coords of resulting G vecs (integer)
3903 : !! npw=resulting number of planewaves inside ecut centered at kpt
3904 : !!
3905 : !! SIDE EFFECTS
3906 : !! mpi_enreg
3907 : !! %me_g0=if 1, the plane wave G(0 0 0) is in the set of plane waves (and is the first)
3908 : !! TODO: other SIDE EFFECTS on mpi_enreg should be described !!!
3909 : !!
3910 : !! NOTES
3911 : !! Must take into account the time-reversal symmetry when istwf_k is not 1.
3912 : !!
3913 : !! SOURCE
3914 :
3915 1787939 : subroutine kpgsph(ecut, exchn2n3d, gmet, ikg, ikpt, istwf_k, kg, kpt, mkmem, mpi_enreg, mpw, npw)
3916 :
3917 : !Arguments ------------------------------------
3918 : !scalars
3919 : integer,intent(in) :: exchn2n3d,ikg,ikpt,istwf_k,mkmem,mpw
3920 : integer,intent(out) :: npw
3921 : real(dp),intent(in) :: ecut
3922 : type(MPI_type),intent(inout) :: mpi_enreg
3923 : !arrays
3924 : integer,intent(inout) :: kg(3,mpw*mkmem)
3925 : real(dp),intent(in) :: gmet(3,3),kpt(3)
3926 :
3927 : !Local variables-------------------------------
3928 : !scalars
3929 : integer :: i1,ig,ig1p,ig1pmax,ig2,ig2p,ig2pmax,ig2pmin,ig3,ig3p,ig3pmax
3930 : integer :: ig3pmin,igtot,ii,ikpt_this_proc,in,ind,np_band,np_fft,npw_before,npw_remain,npw_split
3931 : integer, save :: alloc_size=0
3932 : real(dp) :: gap_pw,gmet11,gmet_trace,gmin,gs_fact,gs_part,gscut,v1,v2,v3,xx
3933 : logical :: ipw_ok
3934 : character(len=500) :: msg
3935 : !arrays
3936 : integer :: ngrid(3),nmax(3),nmin(3),n2,ierr
3937 1787939 : integer,allocatable :: array_ipw(:),ig1arr(:),ig2arr(:)
3938 1787939 : integer,allocatable :: ig3arr(:),kg_ind(:),kg_small(:,:)
3939 1787939 : integer, allocatable :: npw_gather(:),npw_disp(:) ,kg_ind_gather(:),kg_small_gather(:,:)
3940 : real(dp) :: kmax(3),minor(3),numer_(3),tsec(2)
3941 1787939 : real(dp),allocatable :: kg1arr(:),kg2arr(:),kg3arr(:)
3942 : ! *************************************************************************
3943 :
3944 : DBG_ENTER("COLL")
3945 :
3946 1787939 : call timab(23,1,tsec)
3947 1787939 : if(istwf_k<1 .or. istwf_k>9)then
3948 : write(msg,'(3a,i0,a)' )&
3949 0 : 'The variable istwf_k must be between 1 and 9, while',ch10,&
3950 0 : 'the argument of the routine istwf_k =',istwf_k,'.'
3951 0 : ABI_BUG(msg)
3952 : end if
3953 :
3954 1787939 : if(ikg+mpw>mkmem*mpw)then
3955 : write(msg,'(5a,i0,a,i0,a,i0,4a)')&
3956 0 : 'The variables ikg, mkmem, and mpw must satisfy ikg<=(mkmem-1)*mpw,',ch10,&
3957 0 : 'while the arguments of the routine are',ch10,&
3958 0 : 'ikg =',ikg,', mkmem =',mkmem,', mpw =',mpw,ch10,&
3959 0 : 'Probable cause: Known error in invars1 for parallel spin-polarized case.',ch10,&
3960 0 : 'Temporary solution: Change the number of parallel processes.'
3961 0 : ABI_BUG(msg)
3962 : end if
3963 :
3964 1787939 : np_band=0
3965 1787939 : if (mpw>0) then
3966 918203 : np_band=1; if(mpi_enreg%paral_kgb==1) np_band=max(1,mpi_enreg%nproc_band)
3967 918203 : alloc_size=max(alloc_size,(mpw+1)*np_band)
3968 2754609 : ABI_MALLOC(kg_small,(3, alloc_size))
3969 2754609 : ABI_MALLOC(kg_ind,(alloc_size))
3970 326396457 : kg_ind(:)=0
3971 : end if
3972 :
3973 : !A larger array, that will be split on the correct processor
3974 : !G**2 cutoff, gscut=Ecut/2 /Pi^2
3975 :
3976 1787939 : gscut=0.5_dp*ecut*piinv**2
3977 :
3978 : !In reduced coordinates, determine maximal value of k+G and G for each direction
3979 :
3980 1787939 : minor(1)=gmet(2,2)*gmet(3,3)-gmet(2,3)**2
3981 1787939 : numer_(1)=gmet(1,2)**2*gmet(3,3)-2.0_dp*gmet(1,2)*gmet(1,3)*gmet(2,3) +gmet(1,3)**2*gmet(2,2)
3982 1787939 : minor(2)=gmet(1,1)*gmet(3,3)-gmet(1,3)**2
3983 1787939 : numer_(2)=gmet(2,3)**2*gmet(1,1)-2.0_dp*gmet(1,2)*gmet(1,3)*gmet(2,3) +gmet(2,1)**2*gmet(3,3)
3984 1787939 : minor(3)=gmet(2,2)*gmet(1,1)-gmet(1,2)**2
3985 1787939 : numer_(3)=gmet(3,2)**2*gmet(1,1)-2.0_dp*gmet(1,2)*gmet(1,3)*gmet(2,3) +gmet(1,3)**2*gmet(2,2)
3986 :
3987 : !Take the trace of the gmet tensor as dimensional reference
3988 1787939 : gmet_trace=gmet(1,1)+gmet(2,2)+gmet(3,3)
3989 :
3990 7151756 : do ii=1,3
3991 5363817 : xx=gmet(ii,ii)*minor(ii)-numer_(ii)
3992 5363817 : if(xx<tol10*gmet_trace**3 .or. minor(ii)<tol10*gmet_trace**2)then
3993 0 : ABI_BUG('The metric tensor seem incorrect')
3994 : end if
3995 5363817 : kmax(ii)=sqrt(gscut*minor(ii)/xx)
3996 5363817 : nmax(ii)=floor(kmax(ii)-kpt(ii)+tol10)
3997 5363817 : nmin(ii)=ceiling(-kmax(ii)-kpt(ii)-tol10)
3998 7151756 : ngrid(ii)=nmax(ii)-nmin(ii)+1
3999 : end do
4000 : !perform looping over fft box grid of size ngfft(1)*ngfft(2)*ngfft(3):
4001 1787939 : ig=0;ind=0
4002 1787939 : in=0
4003 1787939 : gmet11=gmet(1,1)
4004 :
4005 : !Set up standard search sequence for grid points, in standard storage mode :
4006 : !0 1 2 3 ... nmax nmin ... -1
4007 : !If the mode is not standard, then some part of the FFT grid must be selected
4008 : !
4009 5363817 : ABI_MALLOC(ig1arr,(ngrid(1)))
4010 5363817 : ABI_MALLOC(ig2arr,(ngrid(2)))
4011 5363817 : ABI_MALLOC(ig3arr,(ngrid(3)))
4012 5363817 : ABI_MALLOC(kg1arr,(ngrid(1)))
4013 5363817 : ABI_MALLOC(kg2arr,(ngrid(2)))
4014 5363817 : ABI_MALLOC(kg3arr,(ngrid(3)))
4015 :
4016 16686838 : do ig1p=1,ngrid(1)
4017 14898899 : ig1arr(ig1p)=ig1p-1
4018 14898899 : if (ig1p-1>nmax(1)) ig1arr(ig1p)=ig1p-ngrid(1)-1
4019 16686838 : kg1arr(ig1p)=kpt(1)+dble(ig1arr(ig1p))
4020 : end do
4021 :
4022 : !For the second direction, the number of points might depend on istwf_k
4023 : !---------------------------------------------------------------------
4024 1787939 : ig2pmax=ngrid(2)
4025 1787939 : if(istwf_k>=2 .and. exchn2n3d==0) ig2pmax=nmax(2)+1
4026 5363817 : ABI_MALLOC(array_ipw,(-ig2pmax:ig2pmax))
4027 33266572 : array_ipw(:)=0
4028 16633286 : do ig2p=1,ig2pmax
4029 14845347 : ig2arr(ig2p)=ig2p-1
4030 14845347 : if (ig2p-1>nmax(2)) ig2arr(ig2p)=ig2p-ngrid(2)-1
4031 16633286 : kg2arr(ig2p)=kpt(2)+dble(ig2arr(ig2p))
4032 : end do
4033 :
4034 : !For the third direction, the number of points might depend on istwf_k
4035 : !---------------------------------------------------------------------
4036 1787939 : ig3pmax=ngrid(3)
4037 1787939 : if (istwf_k>=2 .and. exchn2n3d==1) ig3pmax=nmax(3)+1
4038 :
4039 16933611 : do ig3p=1,ig3pmax
4040 15145672 : ig3arr(ig3p)=ig3p-1
4041 15145672 : if(ig3p-1>nmax(3)) ig3arr(ig3p)=ig3p-ngrid(3)-1
4042 16933611 : kg3arr(ig3p)=kpt(3)+dble(ig3arr(ig3p))
4043 : end do
4044 :
4045 : !Performs loop on all grid points.
4046 : !---------------------------------------------------------------------
4047 1787939 : igtot = 0
4048 1787939 : if(exchn2n3d==0)then
4049 1787937 : mpi_enreg%me_g0=0
4050 16933575 : do ig3p=1,ngrid(3)
4051 15145638 : ig3=ig3arr(ig3p)
4052 15145638 : v3=kg3arr(ig3p)
4053 15145638 : ig2pmin=1
4054 15145638 : if( istwf_k>=2 .and. istwf_k<=5 .and. ig3<0)then
4055 30246 : ig2pmin=2
4056 : end if
4057 : ! ig2pmax was initialized previously
4058 161625722 : do ig2p=ig2pmin,ig2pmax
4059 144692147 : ig2=ig2arr(ig2p)
4060 : ! PAY ATTENTION : the proc 0 must have me_g0=1
4061 144692147 : ipw_ok = .true.
4062 144692147 : if(mpi_enreg%paral_kgb==1 ) then
4063 504583 : n2 =mpi_enreg%distribfft%n2_coarse
4064 504583 : ipw_ok = ipw_ok.and.(mpi_enreg%me_fft == mpi_enreg%distribfft%tab_fftwf2_distrib( modulo(ig2,n2) + 1))
4065 : end if
4066 144692147 : if (ig2==0 .and. ipw_ok) mpi_enreg%me_g0=1
4067 144692147 : v2=kg2arr(ig2p)
4068 144692147 : gs_part=gmet(2,2)*v2*v2+gmet(3,3)*v3*v3+2.0_dp*gmet(2,3)*v2*v3
4069 144692147 : gs_fact=2.0_dp*(gmet(1,2)*v2+gmet(3,1)*v3)
4070 144692147 : ig1pmax=ngrid(1)
4071 144692147 : if( (istwf_k==2.or.istwf_k==3) .and. ig3p==1 .and. ig2p==1)ig1pmax=nmax(1)+1
4072 1763033375 : do ig1p=1,ig1pmax
4073 1603195590 : v1=kg1arr(ig1p)
4074 1603195590 : gmin=gs_part+v1*(gs_fact+v1*gmet11)
4075 : ! If inside sphere:
4076 1747887737 : if (gmin<=gscut) then
4077 623286029 : if (ipw_ok) then
4078 622831221 : ig=ig+1 ! inside sphere
4079 622831221 : igtot=igtot+1
4080 622831221 : if (mpw>0.and.ig<=alloc_size) then
4081 : ! Keep coords of pw:
4082 312218333 : kg_small(1,ig)=ig1arr(ig1p)
4083 312218333 : kg_small(2,ig)=ig2
4084 312218333 : kg_small(3,ig)=ig3
4085 312218333 : kg_ind(ig)=igtot
4086 : end if
4087 622831221 : array_ipw(ig2)=array_ipw(ig2)+1
4088 : else
4089 454808 : igtot=igtot+1
4090 : end if
4091 : end if
4092 : end do !ig1p
4093 : end do !ig2p
4094 : end do !ig3p
4095 :
4096 : else ! if (exchn2n3d/=0)
4097 :
4098 : ! ig2pmax was initialized previously
4099 2 : mpi_enreg%me_g0=0
4100 68 : do ig2p=1,ngrid(2)
4101 66 : ig2=ig2arr(ig2p)
4102 : ! PAY ATTENTION : the proc 0 must have me_g0=1
4103 66 : ipw_ok = .true.
4104 66 : if(mpi_enreg%paral_kgb==1 ) then
4105 0 : n2 =mpi_enreg%distribfft%n2_coarse
4106 0 : ipw_ok = ipw_ok.and.(mpi_enreg%me_fft == mpi_enreg%distribfft%tab_fftwf2_distrib( modulo(ig2,n2) + 1))
4107 : end if
4108 66 : if(ig2==0 .and. istwf_k>=2 .and. ipw_ok) mpi_enreg%me_g0=1
4109 66 : v2 =kg2arr(ig2p)
4110 66 : ig3pmin=1
4111 66 : if( (istwf_k==2 .or. istwf_k==3 .or. istwf_k==6 .or. istwf_k==7) .and. ig2<0)then
4112 0 : ig3pmin=2
4113 : end if
4114 1190 : do ig3p=ig3pmin,ig3pmax
4115 1122 : ig3=ig3arr(ig3p)
4116 1122 : v3=kg3arr(ig3p)
4117 1122 : gs_part=gmet(2,2)*v2*v2+gmet(3,3)*v3*v3+2.0_dp*gmet(2,3)*v2*v3
4118 1122 : gs_fact=2.0_dp*(gmet(1,2)*v2+gmet(3,1)*v3)
4119 1122 : ig1pmax=ngrid(1)
4120 1122 : if( (istwf_k==2.or.istwf_k==3) .and. ig3p==1 .and. ig2p==1)ig1pmax=nmax(1)+1
4121 32604 : do ig1p=1,ig1pmax
4122 31416 : v1=kg1arr(ig1p)
4123 31416 : gmin=gs_part+v1*(gs_fact+v1*gmet11)
4124 : ! If inside sphere:
4125 32538 : if (gmin<=gscut) then
4126 16078 : if (ipw_ok) then
4127 16078 : ig=ig+1 ! inside sphere
4128 16078 : igtot=igtot+1
4129 : ! Make sure not to overrun array, or simply do not store if mpw=0
4130 16078 : if (mpw>0.and.ig<=alloc_size) then
4131 : ! Keep coords of pw:
4132 8039 : kg_small(1,ig)=ig1arr(ig1p)
4133 8039 : kg_small(2,ig)=ig2
4134 8039 : kg_small(3,ig)=ig3
4135 8039 : kg_ind(ig)=igtot
4136 : end if
4137 : else
4138 0 : igtot=igtot+1
4139 : end if
4140 : end if
4141 :
4142 : end do ! ig1p
4143 : end do ! ig3p
4144 : ! end if ! if the ig2 plane is to be treated by this processor
4145 : end do ! ig2p
4146 :
4147 : end if ! exchn2n3d==0 or ==1
4148 :
4149 : !Total number of G vectors at this k point is assigned: npw
4150 : !when getcell = 1 it can be that ig exceeds mpw, the bound on kp_small
4151 : !here is a workaround:
4152 1787939 : if (mpw*np_band > 0 .and. ig > alloc_size) then
4153 132 : npw = mpw*np_band
4154 : else
4155 1787807 : npw=ig
4156 : end if
4157 1787939 : alloc_size = max(alloc_size,npw)
4158 :
4159 1787939 : ABI_FREE(ig1arr)
4160 1787939 : ABI_FREE(ig2arr)
4161 1787939 : ABI_FREE(ig3arr)
4162 1787939 : ABI_FREE(kg1arr)
4163 1787939 : ABI_FREE(kg2arr)
4164 1787939 : ABI_FREE(kg3arr)
4165 :
4166 : !BandFFT: plane-wave load balancing
4167 1787939 : if (mpi_enreg%paral_kgb==1.and.mpi_enreg%nproc_fft>1.and. mpi_enreg%pw_unbal_thresh>zero.and. istwf_k==1) then
4168 : ! Check for reequilibration
4169 2018 : np_fft=max(1,mpi_enreg%nproc_fft)
4170 6054 : ABI_MALLOC(npw_gather,(np_fft)) ! Count pw before balancing
4171 2018 : call xmpi_allgather(npw,npw_gather,mpi_enreg%comm_fft,ierr)
4172 16046 : gap_pw = 100._dp*(maxval(npw_gather(:))-minval(npw_gather))/(1.*sum(npw_gather(:))/np_fft)
4173 2018 : write(msg,'(a,f5.2)' ) ' Relative gap for number of plane waves between process (%): ',gap_pw
4174 2018 : call wrtout(std_out,msg)
4175 2018 : if(gap_pw > mpi_enreg%pw_unbal_thresh) then ! Effective reequilibration
4176 : write(msg,'(a,f5.2,a,i4,a,f5.2,a)') &
4177 0 : 'Plane-wave unbalancing (',gap_pw,'%) for kpt ',ikpt,' is higher than threshold (',&
4178 0 : mpi_enreg%pw_unbal_thresh,'%); a plane-wave balancing procedure is activated!'
4179 0 : call wrtout(std_out,msg)
4180 : !Get optimal number
4181 0 : npw_split=sum(npw_gather(:))
4182 0 : npw=npw_split/np_fft
4183 0 : npw_remain=modulo(npw_split,np_fft)
4184 0 : if(mpi_enreg%me_fft < npw_remain) npw=npw+1
4185 0 : ig=npw
4186 : !write(msg,*) 'New npw_fft = ', npw
4187 : !call wrtout(std_out,msg)
4188 0 : alloc_size = max(alloc_size,npw)
4189 0 : if(mpw>0 ) then !Step for requilibration between fft process
4190 0 : ABI_MALLOC(npw_disp,(np_fft))
4191 0 : npw_disp=0
4192 0 : do i1=2,np_fft
4193 0 : npw_disp(i1) = npw_disp(i1-1) + npw_gather(i1-1)
4194 : end do
4195 0 : ABI_MALLOC(kg_ind_gather,(npw_split))
4196 0 : ABI_MALLOC(kg_small_gather,(3,npw_split))
4197 : call xmpi_allgatherv(kg_ind, npw_gather(mpi_enreg%me_fft+1) , &
4198 0 : & kg_ind_gather,npw_gather,npw_disp,mpi_enreg%comm_fft,ierr)
4199 : call xmpi_allgatherv(kg_small,3*npw_gather(mpi_enreg%me_fft+1), &
4200 0 : & kg_small_gather,3*npw_gather, 3*npw_disp,mpi_enreg%comm_fft,ierr)
4201 0 : npw_before=mpi_enreg%me_fft*(npw_split/np_fft)+min(npw_remain,mpi_enreg%me_fft)
4202 0 : kg_small(:,1:npw)=kg_small_gather(:,npw_before+1:npw_before+npw)
4203 0 : kg_ind( 1:npw)=kg_ind_gather(npw_before+1:npw_before+npw)
4204 : #ifdef DEBUG_MODE
4205 : call wrtout(std_out,"keeping values done")
4206 : #endif
4207 0 : ABI_FREE(npw_disp)
4208 0 : ABI_FREE(kg_ind_gather)
4209 0 : ABI_FREE(kg_small_gather)
4210 : end if
4211 : end if!End of reequilibration step for paral KGB
4212 4036 : ABI_FREE(npw_gather)
4213 : end if
4214 :
4215 : !BandFFT: band load balancing
4216 1787939 : if(mpi_enreg%paral_kgb==1.and.mpi_enreg%nproc_band>0) then
4217 6991 : np_band=max(1,mpi_enreg%nproc_band)
4218 6991 : npw_split=ig;npw=npw_split/np_band
4219 6991 : npw_remain=modulo(npw_split,np_band)
4220 6991 : if(mpi_enreg%me_band < npw_remain) npw=npw+1
4221 6991 : if(mpw > 0) then ! This is for the case when we only compute npw and put mpw=0
4222 3003 : npw_before=mpi_enreg%me_band*(npw_split/np_band)+min(npw_remain,mpi_enreg%me_band)
4223 2501483 : kg_small(:,1:npw)=kg_small(:,npw_before+1:npw_before+npw)
4224 627623 : kg_ind ( 1:npw)=kg_ind ( npw_before+1:npw_before+npw)
4225 : end if
4226 : end if
4227 1787939 : if(mpw > 0) then
4228 312762186 : do i1=1,npw
4229 1247375932 : kg(:,i1+ikg)=kg_small(:,i1)
4230 312762186 : if (allocated(mpi_enreg%my_kgtab)) then
4231 270755 : ikpt_this_proc=mpi_enreg%my_kpttab(ikpt)
4232 270755 : mpi_enreg%my_kgtab(i1,ikpt_this_proc) = kg_ind(i1)
4233 : end if
4234 : end do
4235 918203 : ABI_FREE(kg_small)
4236 918203 : ABI_FREE(kg_ind)
4237 : end if
4238 :
4239 1787939 : ABI_FREE(array_ipw)
4240 :
4241 : !Take care of the me_g0 flag
4242 1787939 : mpi_enreg%me_g0_fft=mpi_enreg%me_g0
4243 1787939 : if(mpi_enreg%paral_kgb==1.and.mpi_enreg%nproc_band>0) then
4244 6991 : if(mpi_enreg%me_band==0.and.mpi_enreg%me_g0==1) then
4245 : ! In this case, the processors had the 0 G vector before the new distribution, and still keeps it
4246 2334 : mpi_enreg%me_g0=1
4247 : else
4248 : ! All other cases
4249 4657 : mpi_enreg%me_g0=0
4250 : end if
4251 : end if
4252 :
4253 : !Check that npw is not zero
4254 1787939 : if(mpi_enreg%paral_kgb==1.and.npw==0) then
4255 : write(msg,'(5a)' )&
4256 0 : 'Please decrease the number of npband*npfft MPI processes!',ch10,&
4257 0 : 'One of the MPI process has no plane-wave to handle.',ch10,&
4258 0 : 'Action: decrease npband and/or npfft.'
4259 0 : ABI_ERROR(msg)
4260 : endif
4261 :
4262 1787939 : call timab(23,2,tsec)
4263 :
4264 : DBG_EXIT("COLL")
4265 :
4266 1787939 : end subroutine kpgsph
4267 : !!***
4268 :
4269 : !----------------------------------------------------------------------
4270 :
4271 : !!****f* m_fftcore/kpgcount
4272 : !! NAME
4273 : !! kpgcount
4274 : !!
4275 : !! FUNCTION
4276 : !! Give the minimum and maximum number of G vectors in each direction:
4277 : !! for each k-point, compute the number of G vectors in each direction,
4278 : !! then store the min and max value over the set of k-points.
4279 : !!
4280 : !! INPUTS
4281 : !! ecut=planewave kinetic energy cutoff (hartrees)
4282 : !! exchn2n3d=if 1, n2 and n3 are exchanged
4283 : !! gmet(3,3)=reciprocal space metric (bohr^-2)
4284 : !! istwfk(nkpt)=option parameter that describes the storage of wfs
4285 : !! kpt(3,nkpt)=reduced coords of k point (in terms of recip latt vecs)
4286 : !! nkpt=number of k points
4287 : !!
4288 : !! OUTPUT
4289 : !! ngmax(3)=maximum number of G vectors in each direction (x,y,z)
4290 : !! ngmin(3)=minimum number of G vectors in each direction (x,y,z)
4291 : !!
4292 : !! NOTES
4293 : !! This routine has been extracted from kpgsph...
4294 : !!
4295 : !! SOURCE
4296 :
4297 75 : subroutine kpgcount(ecut,exchn2n3d,gmet,istwfk,kpt,ngmax,ngmin,nkpt)
4298 :
4299 : !Arguments ------------------------------------
4300 : !scalars
4301 : integer,intent(in) :: exchn2n3d,nkpt
4302 : integer,intent(out) :: ngmax(3),ngmin(3)
4303 : real(dp),intent(in) :: ecut
4304 : !arrays
4305 : integer,intent(in) :: istwfk(nkpt)
4306 : real(dp),intent(in) :: gmet(3,3),kpt(3,nkpt)
4307 :
4308 : !Local variables-------------------------------
4309 : !scalars
4310 : integer :: ii,ikpt,istwf_k,kmax,ng1,ng2,ng3,nmin
4311 : real(dp) :: gmet_trace,gscut,xx
4312 : !arrays
4313 : integer :: ngrid(3),nmax(3)
4314 : real(dp) :: minor(3),numer_(3)
4315 : ! *************************************************************************
4316 :
4317 : DBG_ENTER("COLL")
4318 :
4319 75 : gscut=0.5_dp*ecut*piinv**2
4320 75 : gmet_trace=gmet(1,1)+gmet(2,2)+gmet(3,3)
4321 75 : minor(1)=gmet(2,2)*gmet(3,3)-gmet(2,3)**2
4322 75 : minor(2)=gmet(1,1)*gmet(3,3)-gmet(1,3)**2
4323 75 : minor(3)=gmet(2,2)*gmet(1,1)-gmet(1,2)**2
4324 75 : numer_(1)=gmet(1,2)**2*gmet(3,3)-2.0_dp*gmet(1,2)*gmet(1,3)*gmet(2,3)+gmet(1,3)**2*gmet(2,2)
4325 75 : numer_(2)=gmet(2,3)**2*gmet(1,1)-2.0_dp*gmet(1,2)*gmet(1,3)*gmet(2,3)+gmet(2,1)**2*gmet(3,3)
4326 75 : numer_(3)=gmet(3,2)**2*gmet(1,1)-2.0_dp*gmet(1,2)*gmet(1,3)*gmet(2,3)+gmet(1,3)**2*gmet(2,2)
4327 :
4328 300 : ngmin(:)=1000000;ngmax(:)=0
4329 784 : do ikpt=1,nkpt
4330 709 : istwf_k=istwfk(ikpt)
4331 :
4332 2836 : do ii=1,3
4333 2127 : xx=gmet(ii,ii)*minor(ii)-numer_(ii)
4334 2127 : if(xx<tol10*gmet_trace**3.or.minor(ii)<tol10*gmet_trace**2)then
4335 0 : ABI_BUG('The metric tensor seem incorrect')
4336 : end if
4337 2127 : kmax=sqrt(gscut*minor(ii)/xx)
4338 2127 : nmax(ii)=floor(kmax-kpt(ii,ikpt)+tol10)
4339 2127 : nmin=ceiling(-kmax-kpt(ii,ikpt)-tol10)
4340 2836 : ngrid(ii)=nmax(ii)-nmin+1
4341 : end do
4342 :
4343 709 : ng1=ngrid(1);if(istwf_k==2.or.istwf_k==3) ng1=nmax(1)+1
4344 709 : if(exchn2n3d==0)then
4345 709 : ng3=ngrid(3)
4346 709 : ng2=ngrid(2);if(istwf_k>=2) ng2=nmax(2)+1
4347 4 : if(istwf_k>=2.and.istwf_k<=5) ng2=ng2-1
4348 : else
4349 0 : ng2=ngrid(2)
4350 0 : ng3=ngrid(3);if(istwf_k>=2) ng3=nmax(3)+1
4351 0 : if(istwf_k==2.or.istwf_k==3.or.istwf_k==6.or.istwf_k==7) ng3=ng3-1
4352 : end if
4353 :
4354 709 : if(ng1<ngmin(1)) ngmin(1)=ng1
4355 709 : if(ng2<ngmin(2)) ngmin(2)=ng2
4356 709 : if(ng3<ngmin(3)) ngmin(3)=ng3
4357 709 : if(ng1>ngmax(1)) ngmax(1)=ng1
4358 709 : if(ng2>ngmax(2)) ngmax(2)=ng2
4359 784 : if(ng3>ngmax(3)) ngmax(3)=ng3
4360 :
4361 : end do
4362 :
4363 : DBG_EXIT("COLL")
4364 :
4365 75 : end subroutine kpgcount
4366 : !!***
4367 :
4368 : !----------------------------------------------------------------------
4369 :
4370 : !!****f* m_fftcore/get_kg
4371 : !! NAME
4372 : !! get_kg
4373 : !!
4374 : !! FUNCTION
4375 : !! Helper function to calculate the set of G-vectors at a given kpoint.
4376 : !! without taking advantage of FFT parallelism and G-vector distributions.
4377 : !!
4378 : !! INPUTS
4379 : !! kpoint(3)=The k-point in reduced coordinates.
4380 : !! ecut=Cutoff energy for planewave basis set.
4381 : !! gmet(3,3)=reciprocal space metric ($\textrm{bohr}^{-2}$).
4382 : !! istwfk=Options defining if time-reversal is used to decrease the number of G"s.
4383 : !! [kin_sorted]=True if output g-vectors should be sorted by |k+g|^2/2. Default: False.
4384 : !!
4385 : !! OUTPUT
4386 : !! npw_k=Total number of G-vectors in the full G-sphere.
4387 : !! kg_k(3,npw_k) list of G-vectors allocated by the routine.
4388 : !!
4389 : !! SIDE EFFECTS
4390 : !! [mpw]: Used to to compute the maximum number of PWs when looping over multiple k-points.
4391 : !! [gmax(3)]: Max G-component when looping over multiple k-points.
4392 : !!
4393 : !! SOURCE
4394 :
4395 395398 : subroutine get_kg(kpoint, istwf_k, ecut, gmet, npw_k, kg_k, &
4396 : kin_sorted, mpw, gmax) ! optional
4397 :
4398 : !Arguments ------------------------------------
4399 : !scalars
4400 : integer,intent(in) :: istwf_k
4401 : integer,intent(out) :: npw_k
4402 : real(dp),intent(in) :: ecut
4403 : integer,optional,intent(inout) :: mpw
4404 : !arrays
4405 : integer,allocatable,intent(out) :: kg_k(:,:)
4406 : real(dp),intent(in) :: gmet(3,3),kpoint(3)
4407 : logical,optional,intent(in) :: kin_sorted
4408 : integer,optional,intent(inout) :: gmax(3)
4409 :
4410 : !Local variables-------------------------------
4411 : !scalars
4412 : integer,parameter :: mkmem_ = 1, exchn2n3d0 = 0, ikg0 = 0
4413 : integer :: npw_k_test, ipw, ii
4414 395398 : type(MPI_type) :: MPI_enreg_seq
4415 : !arrays
4416 : integer :: kg_dum(3, 0)
4417 395398 : integer,allocatable :: iwork(:,:)
4418 : ! *********************************************************************
4419 :
4420 395398 : call initmpi_seq(MPI_enreg_seq)
4421 :
4422 : ! Calculate the number of G-vectors for this k-point.
4423 395398 : call kpgsph(ecut, exchn2n3d0, gmet, ikg0, 0, istwf_k, kg_dum, kpoint, 0, MPI_enreg_seq, 0, npw_k)
4424 :
4425 : ! Allocate and calculate the set of G-vectors.
4426 1186194 : ABI_MALLOC(kg_k,(3,npw_k))
4427 395398 : call kpgsph(ecut, exchn2n3d0, gmet, ikg0, 0, istwf_k, kg_k, kpoint, mkmem_, MPI_enreg_seq, npw_k, npw_k_test)
4428 :
4429 395398 : call destroy_mpi_enreg(MPI_enreg_seq)
4430 :
4431 395398 : if (present(kin_sorted)) then
4432 0 : if (kin_sorted) then
4433 0 : call sort_gvecs(npw_k, kpoint, gmet, kg_k, out_gvec=iwork)
4434 0 : kg_k = iwork
4435 0 : ABI_FREE(iwork)
4436 : end if
4437 : end if
4438 :
4439 395398 : if (present(mpw)) mpw = max(mpw, npw_k)
4440 :
4441 395398 : if (present(gmax)) then
4442 71743650 : do ipw=1,npw_k
4443 286738737 : do ii=1,3
4444 286660116 : gmax(ii) = max(gmax(ii), abs(kg_k(ii,ipw)))
4445 : end do
4446 : end do
4447 : end if
4448 :
4449 395398 : end subroutine get_kg
4450 : !!***
4451 :
4452 : !!****f* m_fftcore/kgindex
4453 : !! NAME
4454 : !! kgindex
4455 : !!
4456 : !! FUNCTION
4457 : !! Compute the index of each plane wave on a FFT grid.
4458 : !!
4459 : !! INPUTS
4460 : !! kg_k(3,npw_k)=dimensionless coords of G vecs (integer)
4461 : !! mpi_enreg=information about MPI parallelization
4462 : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
4463 : !! npw_k=number of planewaves
4464 : !!
4465 : !! OUTPUT
4466 : !! indpw_k(npw_k)=linear list number (in fft box) of given G vector for the current processor (local address)
4467 : !! =0 if kg_k(ipw) is not treated by this processor
4468 : !! mask(npw_k)=True if kg_k(ipw) belongs to this processor, false otherwise.
4469 : !!
4470 : !! NOTES
4471 : !! mpi_enreg is not necessary in this case (the info is also in ngfft), but much more easy to read...
4472 : !!
4473 : !! SOURCE
4474 :
4475 135620 : subroutine kgindex(indpw_k, kg_k, mask, mpi_enreg, ngfft, npw_k)
4476 :
4477 : !Arguments ------------------------------------
4478 : !scalars
4479 : integer,intent(in) :: npw_k
4480 : type(MPI_type),intent(in) :: mpi_enreg
4481 : !arrays
4482 : integer,intent(in) :: kg_k(3,npw_k),ngfft(18)
4483 : integer,intent(out) :: indpw_k(npw_k)
4484 : logical,intent(out) :: mask(npw_k)
4485 : !Local variables-------------------------------
4486 : !scalars
4487 : integer :: ig,ig1,ig2,ig3,me_fft,n1,n2,n3,nd2
4488 : character(len=500) :: msg
4489 : !arrays
4490 135620 : integer, contiguous, pointer :: fftn2_distrib(:),ffti2_local(:)
4491 : !integer, contiguous, pointer :: fftn3_distrib(:),ffti3_local(:)
4492 : ! *************************************************************************
4493 :
4494 135620 : n1=ngfft(1); n2=ngfft(2); n3=ngfft(3)
4495 :
4496 : ! Use the following indexing (N means ngfft of the adequate direction)
4497 : ! 0 1 2 3 ... N/2 -(N-1)/2 ... -1 <= kg
4498 : ! 1 2 3 4 ....N/2+1 N/2+2 ... N <= index
4499 :
4500 135620 : me_fft=mpi_enreg%me_fft
4501 135620 : nd2=(n2-1)/mpi_enreg%nproc_fft+1
4502 :
4503 135620 : if (n2== mpi_enreg%distribfft%n2_coarse) then
4504 135620 : fftn2_distrib => mpi_enreg%distribfft%tab_fftdp2_distrib
4505 135620 : ffti2_local => mpi_enreg%distribfft%tab_fftdp2_local
4506 0 : else if (n2 == mpi_enreg%distribfft%n2_fine) then
4507 0 : fftn2_distrib => mpi_enreg%distribfft%tab_fftdp2dg_distrib
4508 0 : ffti2_local => mpi_enreg%distribfft%tab_fftdp2dg_local
4509 : else
4510 0 : ABI_BUG("Unable to find an allocated distrib for this fft grid")
4511 : end if
4512 :
4513 : !call ptabs_fourwf(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
4514 :
4515 10269551 : do ig=1,npw_k
4516 10133931 : ig1=modulo(kg_k(1,ig),n1)
4517 10133931 : ig2=modulo(kg_k(2,ig),n2)
4518 10133931 : ig3=modulo(kg_k(3,ig),n3)
4519 10133931 : if(me_fft==fftn2_distrib(ig2+1)) then
4520 10133931 : ig2=ffti2_local(ig2+1) - 1
4521 10133931 : indpw_k(ig)=ig1+1+n1*(ig2+nd2*ig3)
4522 10133931 : mask(ig)=.true.
4523 : else
4524 0 : indpw_k(ig)=0
4525 0 : mask(ig)=.false.
4526 : end if
4527 81207068 : if (any(kg_k(:,ig) > ngfft(1:3)/2) .or. any(kg_k(:,ig) < -(ngfft(1:3)-1)/2) ) then
4528 0 : write(msg,'(a,3(i0,1x),a)')" The G-vector: ",kg_k(:, ig)," falls outside the FFT box. Increase boxcutmin (?)"
4529 0 : ABI_ERROR(msg)
4530 : end if
4531 : end do
4532 :
4533 135620 : end subroutine kgindex
4534 : !!***
4535 :
4536 : !----------------------------------------------------------------------
4537 :
4538 : !!****f* m_fftcore/addrho
4539 : !! NAME
4540 : !! addrho
4541 : !!
4542 : !! FUNCTION
4543 : !! Add the contribution to the density generated by n1dfft x-y planes
4544 : !!
4545 : !! INPUTS
4546 : !! icplexwf=1 if u(r) is real, 2 otherwise.
4547 : !! includelast
4548 : !! nd1,nd2=Leading dimensions of rhopart.
4549 : !! n2=FFT dimension along y.
4550 : !! lot=2nd Leading dimension of zw (cache blocking factor).
4551 : !! n1dfft=Number of 1D FFTs along y performed.
4552 : !! zw(2,lot,n2)=Array with the x-y planes (wavefunction in real space).
4553 : !! weight=Weight factor for the density.
4554 : !!
4555 : !! SIDE EFFECTS
4556 : !! rhopart(nd1,nd2)=density in the x-y plane, accumulated in output.
4557 : !!
4558 : !! SOURCE
4559 :
4560 53744 : pure subroutine addrho(icplexwf,includelast,nd1,nd2,n2,lot,n1dfft,zw,rhopart,weight_r,weight_i)
4561 :
4562 :
4563 : !Arguments ------------------------------------
4564 : integer,intent(in) :: icplexwf,includelast,nd1,nd2,n2,lot,n1dfft
4565 : real(dp),intent(in) :: zw(2,lot,n2)
4566 : real(dp),intent(inout) :: rhopart(nd1,nd2)
4567 : real(dp),intent(in) :: weight_i,weight_r
4568 :
4569 : !Local variables-------------------------------
4570 : integer :: i2,j
4571 : ! *************************************************************************
4572 :
4573 53744 : if (icplexwf==2) then
4574 : ! Complex wavefunction in real space.
4575 2326428 : do i2=1,n2-1,2
4576 25289120 : do j=1,n1dfft
4577 22962692 : rhopart(j,i2) = rhopart(j,i2) + weight_r*zw(1,j,i2)**2+weight_i*zw(2,j,i2)**2
4578 25239232 : rhopart(j,i2+1) = rhopart(j,i2+1) + weight_r*zw(1,j,i2+1)**2+weight_i*zw(2,j,i2+1)**2
4579 : end do
4580 : end do
4581 :
4582 49888 : if (2*(n2/2)/=n2) then
4583 6720 : do j=1,n1dfft
4584 6720 : rhopart(j,n2 )=rhopart(j,n2 )+weight_r*zw(1,j,n2 )**2+weight_i*zw(2,j,n2 )**2
4585 : end do
4586 : end if
4587 : else
4588 : ! The wavefunction is real, in real space
4589 3856 : if (includelast==1) then
4590 314800 : do i2=1,n2
4591 3670448 : do j=1,n1dfft
4592 3355648 : rhopart(2*j-1,i2)=rhopart(2*j-1,i2)+zw(1,j,i2)**2*weight_r
4593 3666992 : rhopart(2*j ,i2)=rhopart(2*j ,i2)+zw(2,j,i2)**2*weight_i
4594 : end do
4595 : end do
4596 : else
4597 29200 : do i2=1,n2
4598 288000 : do j=1,n1dfft-1
4599 259200 : rhopart(2*j-1,i2)=rhopart(2*j-1,i2)+zw(1,j,i2)**2*weight_r
4600 288000 : rhopart(2*j ,i2)=rhopart(2*j ,i2)+zw(2,j,i2)**2*weight_i
4601 : end do
4602 29200 : rhopart(2*n1dfft-1,i2)=rhopart(2*n1dfft-1,i2)+zw(1,n1dfft,i2)**2*weight_r
4603 : end do
4604 : end if
4605 :
4606 : end if
4607 :
4608 53744 : end subroutine addrho
4609 : !!***
4610 :
4611 : !----------------------------------------------------------------------
4612 :
4613 : !!****f* m_fftcore/multpot
4614 : !! NAME
4615 : !! multpot
4616 : !!
4617 : !! FUNCTION
4618 : !!
4619 : !! INPUTS
4620 : !! icplexwf=1 if u(r) is real, 2 otherwise.
4621 : !! icplex=1 if v(r) is real, 2 otherwise.
4622 : !! includelast
4623 : !! nd1,nd2=Leading dimensions of pot(icplex*nd1,nd2)
4624 : !! n2
4625 : !! lot
4626 : !! n1dfft
4627 : !!
4628 : !! OUTPUT
4629 : !!
4630 : !! SOURCE
4631 :
4632 134610 : subroutine multpot(icplexwf,icplex,includelast,nd1,nd2,n2,lot,n1dfft,pot,zw)
4633 :
4634 : !Arguments ------------------------------------
4635 : integer,intent(in) :: icplexwf,icplex,includelast,nd1,nd2,n2,lot,n1dfft
4636 : real(dp),intent(in) :: pot(icplex*nd1,nd2)
4637 : real(dp),intent(inout) :: zw(2,lot,n2)
4638 :
4639 : !Local variables-------------------------------
4640 : integer :: i2,j
4641 : real(dp) :: rew,imw
4642 : ! *************************************************************************
4643 :
4644 134610 : if (icplexwf==1) then
4645 : ! Real u(r)
4646 :
4647 3826 : if (icplex==2) then
4648 0 : ABI_BUG('multpot: icplexwf=1 and icplex=2')
4649 : else
4650 : ! TO BE SPEEDED UP : should use the same trick as Stefan
4651 3826 : if(includelast==1)then
4652 314050 : do i2=1,n2
4653 3658898 : do j=1,n1dfft
4654 3344848 : zw(1,j,i2)=zw(1,j,i2)*pot(2*j-1,i2)
4655 3655472 : zw(2,j,i2)=zw(2,j,i2)*pot(2*j ,i2)
4656 : end do
4657 : end do
4658 : else
4659 29200 : do i2=1,n2
4660 288000 : do j=1,n1dfft-1
4661 259200 : zw(1,j,i2)=zw(1,j,i2)*pot(2*j-1,i2)
4662 288000 : zw(2,j,i2)=zw(2,j,i2)*pot(2*j ,i2)
4663 : end do
4664 29200 : zw(1,n1dfft,i2)=zw(1,n1dfft,i2)*pot(2*n1dfft-1,i2)
4665 : end do
4666 : end if
4667 : end if
4668 :
4669 130784 : else if (icplexwf==2) then
4670 : ! Complex u(r)
4671 :
4672 130784 : if (icplex==1) then
4673 :
4674 4235358 : do i2=1,n2-1,2
4675 47725952 : do j=1,n1dfft
4676 43490594 : zw(1,j,i2)=zw(1,j,i2)*pot(j,i2)
4677 43490594 : zw(2,j,i2)=zw(2,j,i2)*pot(j,i2)
4678 43490594 : zw(1,j,i2+1)=zw(1,j,i2+1)*pot(j,i2+1)
4679 47608168 : zw(2,j,i2+1)=zw(2,j,i2+1)*pot(j,i2+1)
4680 : end do
4681 : end do
4682 :
4683 117784 : if (2*(n2/2)/=n2) then
4684 7200 : do j=1,n1dfft
4685 6750 : zw(1,j,n2)=zw(1,j,n2)*pot(j,n2)
4686 7200 : zw(2,j,n2)=zw(2,j,n2)*pot(j,n2)
4687 : end do
4688 : end if
4689 :
4690 : else
4691 :
4692 663000 : do i2=1,n2-1,2
4693 7163000 : do j=1,n1dfft
4694 6500000 : rew = zw(1,j,i2); imw = zw(2,j,i2)
4695 6500000 : zw(1,j,i2) = rew*pot(2*j-1,i2) - imw*pot(2*j,i2)
4696 6500000 : zw(2,j,i2) = imw*pot(2*j-1,i2) + rew*pot(2*j,i2)
4697 :
4698 6500000 : rew = zw(1,j,i2+1); imw = zw(2,j,i2+1)
4699 6500000 : zw(1,j,i2+1) = rew*pot(2*j-1,i2+1) - imw*pot(2*j,i2+1)
4700 7150000 : zw(2,j,i2+1) = imw*pot(2*j-1,i2+1) + rew*pot(2*j,i2+1)
4701 : end do
4702 : end do
4703 :
4704 13000 : if (2*(n2/2)/=n2) then
4705 0 : do j=1,n1dfft
4706 0 : rew = zw(1,j,n2); imw = zw(2,j,n2)
4707 0 : zw(1,j,n2) = rew*pot(2*j-1,n2) - imw*pot(2*j,n2)
4708 0 : zw(2,j,n2) = imw*pot(2*j-1,n2) + rew*pot(2*j,n2)
4709 : end do
4710 : end if
4711 :
4712 : end if
4713 : end if
4714 :
4715 134610 : end subroutine multpot
4716 : !!***
4717 :
4718 : !----------------------------------------------------------------------
4719 :
4720 : !!****f* m_fftcore/mpifft_collect_datar
4721 : !! NAME
4722 : !! mpifft_collect_datar
4723 : !!
4724 : !! FUNCTION
4725 : !! Collect a real-space MPI-FFT distributed array on each proc.
4726 : !!
4727 : !! INPUTS
4728 : !! ngfft(18)=contain all needed information about 3D FFT (see NOTES at beginning of scfcv)
4729 : !! cplex=1 if real array, 2 for complex
4730 : !! nfft=Number of FFT points treated by this MPI proc
4731 : !! nspden=Second dimension of rhor
4732 : !! rhor(cplex*nfft,nspden)=Array in real space (MPI-FFT distributed)
4733 : !! fftn3_distrib(n3)=rank of the processors which own fft planes in 3rd dimension.
4734 : !! fftn3_local(n3)=local i3 indices
4735 : !! comm_fft=MPI-FFT communicator
4736 : !! [master]=MPI rank, Optional. If present, the global array is available only on master node.
4737 : !!
4738 : !! OUTPUT
4739 : !! rhor_glob(cplex*nfft_tot,nspden)=Global array
4740 : !!
4741 : !! SOURCE
4742 :
4743 0 : subroutine mpifft_collect_datar(ngfft,cplex,nfft,nspden,rhor,comm_fft,fftn3_distrib,ffti3_local,rhor_glob,master)
4744 :
4745 : !Arguments ------------------------------------
4746 : !scalars
4747 : integer,intent(in) :: cplex,nfft,nspden,comm_fft
4748 : integer,optional,intent(in) :: master
4749 : !arrays
4750 : integer,intent(in) :: ngfft(18),fftn3_distrib(ngfft(3)),ffti3_local(ngfft(3))
4751 : real(dp),intent(in) :: rhor(cplex*nfft,nspden)
4752 : real(dp),intent(out) :: rhor_glob(cplex*product(ngfft(1:3)),nspden)
4753 :
4754 : !Local variables-------------------------------
4755 : integer :: ispden,i1,i2,i3,me_fft,i3_local,my_fftbase,glob_fftbase
4756 : integer :: n1,n2,n3,ierr,nfft_tot
4757 : ! *************************************************************************
4758 :
4759 0 : nfft_tot = product(ngfft(1:3)); me_fft = xmpi_comm_rank(comm_fft)
4760 0 : n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3)
4761 :
4762 0 : if (nfft_tot == nfft) then
4763 : ! full rhor on each node, just do a copy
4764 0 : rhor_glob = rhor
4765 : else
4766 : ! if MPI-FFT we have to gather the full rhor on each node.
4767 0 : rhor_glob = zero
4768 0 : do ispden=1,nspden
4769 0 : do i3=1,n3
4770 0 : if (me_fft == fftn3_distrib(i3)) then
4771 0 : i3_local = ffti3_local(i3)
4772 0 : do i2=1,n2
4773 0 : my_fftbase = cplex * ( (i2-1)*n1 + (i3_local-1)*n1*n2 )
4774 0 : glob_fftbase = cplex * ( (i2-1)*n1 + (i3-1)*n1*n2 )
4775 0 : do i1=1,cplex * n1
4776 0 : rhor_glob(i1+glob_fftbase,ispden) = rhor(i1+my_fftbase,ispden)
4777 : end do
4778 : end do
4779 : end if
4780 : end do
4781 : end do
4782 0 : if (present(master)) then
4783 0 : call xmpi_sum_master(rhor_glob,master,comm_fft,ierr)
4784 : else
4785 0 : call xmpi_sum(rhor_glob,comm_fft,ierr)
4786 : end if
4787 : end if
4788 :
4789 0 : end subroutine mpifft_collect_datar
4790 : !!***
4791 :
4792 : END MODULE m_fftcore
4793 : !!***
|