LCOV - code coverage report
Current view: top level - src/52_fft_mpi_noabirule - m_fftw3.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 1.3 % 226 3
Test Date: 2026-09-20 18:56:22 Functions: 2.6 % 38 1

            Line data    Source code
       1              : !!****m* ABINIT/m_fftw3
       2              : !! NAME
       3              : !! m_fftw3
       4              : !!
       5              : !! FUNCTION
       6              : !!  This module provides wrappers for the FFTW3 routines: in-place and out-of-place version.
       7              : !!
       8              : !! COPYRIGHT
       9              : !! Copyright (C) 2009-2026 ABINIT group (MG, FD)
      10              : !! This file is distributed under the terms of the
      11              : !! GNU General Public License, see ~abinit/COPYING
      12              : !! or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! NOTES
      15              : !!  1) MPI parallelism is in testing stage
      16              : !!  2) For better performance the FFT divisions should contain small factors  [2, 3, 5, 7, 11]
      17              : !!
      18              : !! SOURCE
      19              : 
      20              : #if defined HAVE_CONFIG_H
      21              : #include "config.h"
      22              : #endif
      23              : 
      24              : #include "abi_common.h"
      25              : 
      26              : ! It seems that MKL wrappers do not like the advanced interfaces for
      27              : ! r2c and c2r transforms although they work fine if the true FFTW3 library is used.
      28              : !#define DEV_RC_BUG
      29              : #undef DEV_RC_BUG
      30              : 
      31              : #define FFTLIB "FFTW3"
      32              : ! do not use FFT_PREF(name) since not working with NAG compiler
      33              : #define FFT_PREF_fftrisc fftw3_fftrisc
      34              : #define FFT_PREF_fftrisc_mixprec fftw3_fftrisc_mixprec
      35              : #define FFT_PREF_fftpad fftw3_fftpad
      36              : #define FFT_PREF_fftug_dp fftw3_fftug_dp
      37              : #define FFT_PREF_fftur_dp fftw3_fftur_dp
      38              : #define FFT_PREF_fftug fftw3_fftug
      39              : #define FFT_PREF_fftur fftw3_fftur
      40              : 
      41              : 
      42              : 
      43              : #define SPAWN_THREADS_HERE(ndat, nthreads) fftw3_spawn_threads_here(ndat, nthreads)
      44              : #define FFT_DOUBLE 1
      45              : #define FFT_SINGLE 2
      46              : #define FFT_MIXPREC 3
      47              : 
      48              : MODULE m_fftw3
      49              : 
      50              :  use defs_basis
      51              :  use m_abicore
      52              :  use m_errors
      53              :  use m_xomp
      54              :  use m_xmpi
      55              :  use m_hide_blas
      56              :  use m_cgtools
      57              :  use m_cplxtools
      58              :  use m_distribfft
      59              :  use m_fftcore
      60              :  use, intrinsic :: iso_c_binding
      61              : 
      62              :  use m_time,           only : timab
      63              :  use m_numeric_tools,  only : imax_loc
      64              :  use defs_abitypes,    only : MPI_type
      65              :  use m_mpinfo,         only : ptabs_fourwf
      66              :  use m_fstrings,       only : strcat, itoa, sjoin
      67              :  use m_fft_mesh,       only : zpad_t
      68              : 
      69              :  implicit none
      70              : 
      71              : #ifdef HAVE_FFTW3_MPI
      72              :  include 'fftw3-mpi.f03'
      73              : #endif
      74              : 
      75              : !This should be done but MKL fftw hasn't always this include file
      76              : !#ifdef HAVE_FFT_FFTW3
      77              : ! include 'fftw3.f03'
      78              : !#endif
      79              : 
      80              :  private
      81              : 
      82              : ! Entry points for client code
      83              :  public :: fftw3_seqfourdp      ! 3D FFT of lengths nx, ny, nz. Mainly used for densities or potentials.
      84              :  public :: fftw3_seqfourwf      ! FFT transform of wavefunctions (high-level interface).
      85              :  public :: fftw3_fftrisc
      86              :  public :: fftw3_fftrisc_mixprec ! Mixed precision version of fftrisc: input/output in dp, computation done in sp.
      87              :  public :: fftw3_fftug          ! G-->R. 3D zero-padded FFT of lengths nx, ny, nz. Mainly used for wavefunctions
      88              :  public :: fftw3_fftur          ! R-->G, 3D zero-padded FFT of lengths nx, ny, nz. Mainly used for wavefunctions
      89              :  public :: fftw3_use_lib_threads
      90              :  public :: fftw3_spawn_threads_here
      91              : 
      92              :  public :: fftw3_mpifourdp
      93              : 
      94              : ! Low-level routines.
      95              :  public :: fftw3_cleanup        ! Reset FFTW to the pristine state it was in when you started your program,
      96              :  public :: fftw3_init_threads   ! one-time initialization required to use FFTW3 threads.
      97              :  public :: fftw3_set_nthreads   ! Set the number of threads you want FFTW3 to use when HAVE_FFT_FFTW3_THREADS is defined.
      98              :  public :: fftw3_r2c_op         ! Real to complex transform (out-of-place version).
      99              :  public :: fftw3_c2r_op         ! Complex to real transform (out-of-place version).
     100              :  public :: fftw3_c2c_op         ! complex to complex transform (out-of-place version).
     101              :  public :: fftw3_c2c_ip         ! complex to complex transform (in-place version).
     102              :  public :: fftw3_many_dft_op    ! Driver routine for many out-of-place 3D complex-to-complex FFTs.
     103              :  public :: fftw3_many_dft_ip    ! Driver routine for many in-place 3D complex-to-complex FFTs.
     104              :  public :: fftw3_fftpad         ! Driver routines for zero-padded FFT of wavefunctions.
     105              :  public :: fftw3_fftpad_dp      ! Driver routines for zero-padded FFT of wavefunctions.
     106              :  public :: fftw3_fftug_dp       ! Driver routines for zero-padded FFT of wavefunctions.
     107              :  public :: fftw3_poisson        ! Solve the poisson equation in G-space starting from n(r).
     108              : 
     109              :  ! MPI version
     110              :  public :: fftw3_mpiback_wf
     111              :  public :: fftw3_mpiback_manywf
     112              :  public :: fftw3_mpiforw_wf
     113              :  public :: fftw3_mpiforw_manywf
     114              :  public :: fftw3_mpiback
     115              :  public :: fftw3_mpiforw
     116              :  public :: fftw3_applypot
     117              :  public :: fftw3_applypot_many
     118              :  public :: fftw3_accrho
     119              : 
     120              : #ifdef HAVE_FFTW3_MPI
     121              : ! flags copied from fftw3.f
     122              :  integer,public,parameter :: ABI_FFTW_FORWARD = FFTW_FORWARD
     123              :  integer,public,parameter :: ABI_FFTW_BACKWARD = FFTW_BACKWARD
     124              :  integer,public,parameter :: ABI_FFTW_ESTIMATE = FFTW_ESTIMATE
     125              :  integer,public,parameter :: ABI_FFTW_MEASURE = FFTW_MEASURE
     126              :  ! end flags copied from fftw3.f
     127              :  integer,public,parameter :: ABI_FFTW_MPI_TRANSPOSED_IN = FFTW_MPI_TRANSPOSED_IN
     128              :  integer,public,parameter :: ABI_FFTW_MPI_TRANSPOSED_OUT = FFTW_MPI_TRANSPOSED_OUT
     129              :  ! end flags copies from fftw3-mpi.f03
     130              : #else
     131              :  integer,public,parameter :: ABI_FFTW_FORWARD = -1
     132              :  integer,public,parameter :: ABI_FFTW_BACKWARD = +1
     133              :  integer,public,parameter :: ABI_FFTW_ESTIMATE = 64
     134              :  integer,public,parameter :: ABI_FFTW_MEASURE = 0
     135              : ! end flags copied from fftw3.f
     136              :  integer,public,parameter :: ABI_FFTW_MPI_TRANSPOSED_IN = 536870912
     137              :  integer,public,parameter :: ABI_FFTW_MPI_TRANSPOSED_OUT = 1073741824
     138              : ! end flags copies from fftw3-mpi.f03
     139              : #endif
     140              : 
     141              : ! ==========================================================================================
     142              : ! ==== Variables introduced for the FFTW3 interface in abinit. Not belonging to fftw3.f ====
     143              : ! ==========================================================================================
     144              : 
     145              :  integer,public,parameter :: NULL_PLAN = 0
     146              :  ! MKL wrappers might return NULL_PLAN if a particular FFTW3 feature is not available
     147              : 
     148              :  integer,public,parameter :: KIND_FFTW_PLAN = 8
     149              :  ! It should be at least integer*@SIZEOF_INT_P@
     150              :  ! MKL wrappers requires it to be integer*8, so do _not_ use C_INTPTR_T.
     151              : 
     152              : #ifdef HAVE_FFTW3_THREADS
     153              :  integer,private,save :: THREADS_INITED = 0
     154              :  ! 1 if treads have been initialized. 0 otherwise.
     155              : #endif
     156              : 
     157              :  logical,private,save :: USE_LIB_THREADS = .FALSE.
     158              : !!***
     159              : 
     160              : !----------------------------------------------------------------------
     161              : 
     162              : !!****t* m_fftw3/fftw3_plan3_t
     163              : !! NAME
     164              : !! fftw3_plan3_t
     165              : !!
     166              : !! FUNCTION
     167              : !!  Structure storing the pointer to the FFTW plan as well as the options used to generate it.
     168              : !!
     169              : !! SOURCE
     170              : 
     171              :  type,private :: fftw3_plan3_t
     172              :    integer :: isign=0                           ! Sign of the exponential in the FFT
     173              :    integer :: ndat=-1                           ! Number of FFTs associated to the plan
     174              :    integer :: flags=-HUGE(0)                    ! FFTW3 flags used to construct the plan.
     175              :    integer(KIND_FFTW_PLAN) :: plan=NULL_PLAN    ! FFTW3 plan.
     176              :    integer :: nthreads=1                        ! The number of threads associated to the plan.
     177              :    integer :: idist=-1
     178              :    integer :: odist=-1
     179              :    integer :: istride=-1
     180              :    integer :: ostride=-1
     181              :    integer :: n(3)=-1                           ! The number of FFT divisions.
     182              :    integer :: inembed(3)=-1
     183              :    integer :: onembed(3)=-1
     184              :    !integer(C_INT) :: alignment(2)              ! The alignment of the arrays used to construct the plan.
     185              :  end type fftw3_plan3_t
     186              : !!***
     187              : 
     188              :  interface fftw3_fftrisc
     189              :    module procedure fftw3_fftrisc_sp
     190              :    module procedure fftw3_fftrisc_dp
     191              :  end interface fftw3_fftrisc
     192              : 
     193              :  interface fftw3_fftug
     194              :    module procedure fftw3_fftug_dp
     195              :    module procedure fftw3_fftug_spc
     196              :    module procedure fftw3_fftug_dpc
     197              :  end interface fftw3_fftug
     198              : 
     199              :  interface fftw3_fftur
     200              :    module procedure fftw3_fftur_dp
     201              :    module procedure fftw3_fftur_spc
     202              :    module procedure fftw3_fftur_dpc
     203              :  end interface fftw3_fftur
     204              : 
     205              :  interface fftw3_c2c_op
     206              :    module procedure fftw3_c2c_op_spc
     207              :    module procedure fftw3_c2c_op_dpc
     208              :  end interface fftw3_c2c_op
     209              : 
     210              :  interface fftw3_c2c_ip
     211              :    module procedure fftw3_c2c_ip_spc
     212              :    module procedure fftw3_c2c_ip_dpc
     213              :  end interface fftw3_c2c_ip
     214              : 
     215              :  interface fftw3_fftpad
     216              :    module procedure fftw3_fftpad_dp
     217              :    module procedure fftw3_fftpad_spc
     218              :    module procedure fftw3_fftpad_dpc
     219              :  end interface fftw3_fftpad
     220              : 
     221              : #ifdef HAVE_FFTW3
     222              :   ! Overloaded planner.
     223              :  interface fftw3_plan_many_dft
     224              :    module procedure dplan_many_dft_1D
     225              :    !module procedure dplan_many_dft_2D
     226              :    module procedure cplan_many_dft
     227              :    module procedure zplan_many_dft
     228              :  end interface fftw3_plan_many_dft
     229              : 
     230              :  interface fftw3_execute_dft
     231              :    module procedure fftw3_execute_dft_dp
     232              :    module procedure fftw3_execute_dft_spc
     233              :    module procedure fftw3_execute_dft_dpc
     234              :  end interface fftw3_execute_dft
     235              : 
     236              :  interface fftw3_alloc_real
     237              :    module procedure fftw3_alloc_real1d_dp
     238              :    module procedure fftw3_alloc_real2d_dp
     239              :    !module procedure fftw3_alloc_real3d_dp
     240              :  end interface fftw3_alloc_real
     241              : 
     242              :  interface fftw3_alloc_complex
     243              :    module procedure fftw3_alloc_complex1d_spc
     244              :    module procedure fftw3_alloc_complex1d_dpc
     245              :  end interface fftw3_alloc_complex
     246              : 
     247              : !!   FDahm :In case of ffw3-mpi flavor, one must include fftw3-mpi.F03 so
     248              : !! the next few lines cause compiler errors because of name redefinition
     249              : !! In deed, i think this should be avoid and replace by 'include fftw3.f03'
     250              : !! MG: These bindings are needed when we use the FFTW3 wrappers provided by
     251              : !!     the MKL library. I agree that we should use the include file fftw3.F03
     252              : !!     but this implies that
     253              : !!     1) we cannot use the procedures defined in this module to call the MKL wrappers
     254              : !!     2) we drop support for FFTW3 versions < 3.2 since these version do not provide
     255              : !!        the F2003 interface
     256              : !!     I don't have any problem in dropping support for old versions of FFTW3
     257              : !!     We just have to handle the migration on the different slaves of the test farm
     258              : !!     builders with MKL should use m_dfti.F90
     259              : !!     builders with FFTW3 should provide a recent version of the library
     260              : !!
     261              : #ifndef HAVE_FFTW3_MPI
     262              :  ! Fortran binding for fftw_malloc
     263              :  interface fftw_malloc
     264              :    type(C_PTR) function fftw_malloc(alloc_size) bind(C, name='fftw_malloc')
     265              :      import
     266              :      integer(C_SIZE_T), value :: alloc_size
     267              :    end function fftw_malloc
     268              :  end interface fftw_malloc
     269              :  ! Fortran binding for fftw_free
     270              :  interface fftw_free
     271              :     subroutine fftw_free(cptr) bind(C, name='fftw_free')
     272              :      import
     273              :      type(C_PTR), value :: cptr
     274              :    end subroutine fftw_free
     275              : end interface
     276              : #endif
     277              : #endif
     278              : 
     279              : CONTAINS  !===========================================================
     280              : 
     281              : !!****f* m_fftw3/fftw3_seqfourdp
     282              : !! NAME
     283              : !!  fftw3_seqfourdp
     284              : !!
     285              : !! FUNCTION
     286              : !! Driver routine for 3D FFT of lengths nx, ny, nz. Mainly used for densities or potentials.
     287              : !! FFT Transform is out-of-place
     288              : !!
     289              : !! INPUTS
     290              : !! cplex=1 if fofr is real, 2 if fofr is complex
     291              : !! nx,ny,nz=Number of point along the three directions.
     292              : !! ldx,ldy,ldz=Leading dimension of the array.
     293              : !! ndat = Number of FFTS
     294              : !! isign= +1 : fofg(G) => fofr(R);
     295              : !!        -1 : fofr(R) => fofg(G)
     296              : !! fofg(2,ldx*ldy*ldz*ndat)=The array to be transformed.
     297              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator. Defaults to FFTW_ESTIMATE.
     298              : !!
     299              : !! OUTPUT
     300              : !! fofr(cplex,ldx*ldy*ldz*ndat)=The FFT of fofg
     301              : !!
     302              : !! SOURCE
     303              : 
     304            0 : subroutine fftw3_seqfourdp(cplex,nx,ny,nz,ldx,ldy,ldz,ndat,isign,fofg,fofr,fftw_flags)
     305              : 
     306              : !Arguments ------------------------------------
     307              : !scalars
     308              :  integer,intent(in) :: cplex,nx,ny,nz,ldx,ldy,ldz,ndat,isign
     309              :  integer,optional,intent(in) :: fftw_flags
     310              : !arrays
     311              :  real(dp),intent(inout) :: fofg(2*ldx*ldy*ldz*ndat)
     312              :  real(dp),intent(inout) :: fofr(cplex*ldx*ldy*ldz*ndat)
     313              : 
     314              : !Local variables-------------------------------
     315              : !scalars
     316              :  integer,parameter :: iscale1 = 1
     317              :  integer :: my_flags,ii,jj
     318            0 :  complex(sp), allocatable :: work_sp(:)
     319              : ! *************************************************************************
     320              : 
     321            0 :  my_flags = ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
     322              : 
     323            0 :  select case (cplex)
     324              :  case (2)
     325              :    ! Complex to Complex.
     326            0 :    if (fftcore_mixprec == 1) then
     327              :      ! Mixed precision: copy in + in-place + copyout
     328            0 :      ABI_MALLOC(work_sp, (ldx*ldy*ldz*ndat))
     329            0 :      if (isign == ABI_FFTW_BACKWARD) then ! +1
     330            0 :        work_sp(:) = cmplx(fofg(1::2), fofg(2::2), kind=sp)
     331            0 :      else if (isign == ABI_FFTW_FORWARD) then ! -1
     332            0 :        work_sp(:) = cmplx(fofr(1::2), fofr(2::2), kind=sp)
     333              :      else
     334            0 :        ABI_BUG("Wrong isign")
     335              :      end if
     336              : 
     337            0 :      call fftw3_c2c_ip_spc(nx, ny, nz, ldx, ldy, ldz, ndat, iscale1, isign, work_sp, fftw_flags=my_flags)
     338              : 
     339            0 :      if (isign == ABI_FFTW_BACKWARD) then ! +1
     340              :        jj = 1
     341            0 :        do ii=1,ldx*ldy*ldz*ndat
     342            0 :          fofr(jj) = real(work_sp(ii), kind=dp)
     343            0 :          fofr(jj+1) = aimag(work_sp(ii))
     344            0 :          jj = jj + 2
     345              :        end do
     346            0 :      else if (isign == ABI_FFTW_FORWARD) then ! -1
     347              :        jj = 1
     348            0 :        do ii=1,ldx*ldy*ldz*ndat
     349            0 :          fofg(jj) = real(work_sp(ii), kind=dp)
     350            0 :          fofg(jj+1) = aimag(work_sp(ii))
     351            0 :          jj = jj + 2
     352              :        end do
     353              :      end if
     354            0 :      ABI_FREE(work_sp)
     355              : 
     356              :    else
     357              :      ! double precision version.
     358            0 :      select case (isign)
     359              :      case (ABI_FFTW_BACKWARD) ! +1
     360            0 :        call fftw3_many_dft_op(nx,ny,nz,ldx,ldy,ldz,ndat,isign,fofg,fofr,fftw_flags=my_flags)
     361              :      case (ABI_FFTW_FORWARD)  ! -1
     362            0 :        call fftw3_many_dft_op(nx,ny,nz,ldx,ldy,ldz,ndat,isign,fofr,fofg,fftw_flags=my_flags)
     363              :      case default
     364            0 :        ABI_BUG("Wrong isign")
     365              :      end select
     366              :    end if
     367              : 
     368              :  case (1)
     369              :    ! Real case.
     370            0 :    select case (isign)
     371              :    case (ABI_FFTW_FORWARD)
     372              :      ! -1; R --> G
     373            0 :      call fftw3_r2c_op(nx,ny,nz,ldx,ldy,ldz,ndat,fofr,fofg,fftw_flags=my_flags)
     374              :    case (ABI_FFTW_BACKWARD)
     375              :      ! +1; G --> R
     376            0 :      call fftw3_c2r_op(nx,ny,nz,ldx,ldy,ldz,ndat,fofg,fofr,fftw_flags=my_flags)
     377              :    case default
     378            0 :      ABI_BUG("Wrong isign")
     379              :    end select
     380              : 
     381              :  case default
     382            0 :    ABI_BUG(" Wrong value for cplex")
     383              :  end select
     384              : 
     385            0 : end subroutine fftw3_seqfourdp
     386              : !!***
     387              : 
     388              : !----------------------------------------------------------------------
     389              : 
     390              : !!****f* m_fftw3/fftw3_seqfourwf
     391              : !! NAME
     392              : !! fftw3_seqfourwf
     393              : !!
     394              : !! FUNCTION
     395              : !! Carry out composite Fourier transforms between real and reciprocal (G) space.
     396              : !! Wavefunctions, contained in a sphere in reciprocal space,
     397              : !! can be FFT to real space. They can also be FFT from real space
     398              : !! to a sphere. Also, the density maybe accumulated, and a local potential can be applied.
     399              : !!
     400              : !! The different options are :
     401              : !! - option=0 --> reciprocal to real space and output the result.
     402              : !! - option=1 --> reciprocal to real space and accumulate the density.
     403              : !! - option=2 --> reciprocal to real space, apply the local potential to the wavefunction
     404              : !!                in real space and produce the result in reciprocal space.
     405              : !! - option=3 --> real space to reciprocal space.
     406              : !!                NOTE that in this case, fftalg=1x1 MUST be used. This may be changed in the future.
     407              : !!
     408              : !! INPUTS
     409              : !! cplex= if 1 , denpot is real, if 2 , denpot is complex
     410              : !!    (cplex=2 only allowed for option=2, and istwf_k=1)
     411              : !!    not relevant if option=0 or option=3, so cplex=0 can be used to minimize memory
     412              : !! fofgin(2,npwin)=holds input wavefunction in G vector basis sphere.
     413              : !!                 (intent(in) but the routine sphere can modify it for another iflag)
     414              : !! gboundin(2*mgfft+8,2)=sphere boundary info for reciprocal to real space
     415              : !! gboundout(2*mgfft+8,2)=sphere boundary info for real to reciprocal space
     416              : !! istwf_k=option parameter that describes the storage of wfs
     417              : !! kg_kin(3,npwin)=reduced planewave coordinates, input
     418              : !! kg_kout(3,npwout)=reduced planewave coordinates, output
     419              : !! mgfft=maximum size of 1D FFTs
     420              : !! ndat=number of FFT to do in //
     421              : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
     422              : !! npwin=number of elements in fofgin array (for option 0, 1 and 2)
     423              : !! npwout=number of elements in fofgout array (for option 2 and 3)
     424              : !! ldx,ldy,ldz=ngfft(4),ngfft(5),ngfft(6), dimensions of fofr.
     425              : !! option= if 0: do direct FFT
     426              : !!         if 1: do direct FFT, then sum the density
     427              : !!         if 2: do direct FFT, multiply by the potential, then do reverse FFT
     428              : !!         if 3: do reverse FFT only
     429              : !! weight_r=weight to be used for the accumulation of the density in real space
     430              : !!         (needed only when option=1)
     431              : !!
     432              : !! OUTPUT
     433              : !!  (see side effects)
     434              : !!
     435              : !! SIDE EFFECTS
     436              : !! Input/Output
     437              : !! for option==0, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
     438              : !!                fofr(2,ldx*ldy*ldz) contains the output Fourier Transform of fofgin;
     439              : !!                no use of denpot, fofgout and npwout.
     440              : !! for option==1, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
     441              : !!                denpot(cplex*ldx,ldy,ldz) contains the input density at input,
     442              : !!                and the updated density at output (accumulated);
     443              : !!                no use of fofgout and npwout.
     444              : !! for option==2, fofgin(2,npwin*ndat)=holds input wavefunction in G sphere;
     445              : !!                denpot(cplex*ldx,ldy,ldz) contains the input local potential;
     446              : !!                fofgout(2,npwout*ndat) contains the output function;
     447              : !! for option==3, fofr(2,ldx*ldy*ldz*ndat) contains the input real space wavefunction;
     448              : !!                fofgout(2,npwout*ndat) contains its output Fourier transform;
     449              : !!                no use of fofgin and npwin.
     450              : !!
     451              : !! SOURCE
     452              : 
     453            0 : subroutine fftw3_seqfourwf(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k, &
     454            0 :                           kg_kin,kg_kout,mgfft,ndat,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     455              : 
     456              : !Arguments ------------------------------------
     457              : !scalars
     458              :  integer,intent(in) :: cplex,istwf_k,ldx,ldy,ldz,ndat,npwin,npwout,option,mgfft
     459              :  real(dp),intent(in) :: weight_i,weight_r
     460              : !arrays
     461              :  integer,intent(in) :: gboundin(2*mgfft+8,2),gboundout(2*mgfft+8,2)
     462              :  integer,intent(in) :: kg_kin(3,npwin),kg_kout(3,npwout),ngfft(18)
     463              :  real(dp),intent(inout) :: denpot(cplex*ldx,ldy,ldz),fofgin(2,npwin*ndat)
     464              :  real(dp),intent(inout) :: fofr(2,ldx*ldy*ldz*ndat)
     465              :  real(dp),intent(out) :: fofgout(2,npwout*ndat)
     466              : 
     467              : !Local variables-------------------------------
     468              : !scalars
     469              :  integer,parameter :: me_g0=1,ndat1=1
     470              :  integer :: nx,ny,nz,fftalg,fftalga,fftalgc,fftcache,dat,ptg,ptr,ptgin,ptgout,nthreads
     471              :  character(len=500) :: msg
     472              :  logical :: use_fftrisc
     473              : !arrays
     474              :  !real(dp),allocatable :: saveden(:,:,:)
     475              : #if 0
     476              :  logical :: use_fftbox
     477              :  integer,parameter :: shiftg(3)=(/0,0,0/)
     478              :  integer :: symm(3,3)
     479              : #endif
     480              : ! *************************************************************************
     481              : 
     482            0 :  if (all(option /= [0, 1, 2, 3])) then
     483            0 :    write(msg,'(a,i0,a)')' Option:',option,' is not allowed. Only option=0, 1, 2 or 3 are allowed presently.'
     484            0 :    ABI_ERROR(msg)
     485              :  end if
     486              : 
     487            0 :  if (option == 1 .and. cplex /= 1) then
     488            0 :    ABI_ERROR(sjoin("With option number 1, cplex must be 1 but it is cplex:", itoa(cplex)))
     489              :  end if
     490              : 
     491            0 :  if (option==2 .and. (cplex/=1 .and. cplex/=2)) then
     492            0 :    ABI_ERROR(sjoin("With the option number 2, cplex must be 1 or 2, but it is cplex:", itoa(cplex)))
     493              :  end if
     494              : 
     495            0 :  nx=ngfft(1); ny=ngfft(2); nz=ngfft(3)
     496            0 :  fftalg=ngfft(7); fftalga=fftalg/100; fftalgc=mod(fftalg,10)
     497            0 :  fftcache=ngfft(8)
     498              : 
     499            0 :  use_fftrisc = (fftalgc==2)
     500            0 :  if (istwf_k==2.and.option==3) use_fftrisc = .FALSE.
     501            0 :  if (istwf_k>2.and.ANY(option==(/0,3/))) use_fftrisc = .FALSE.
     502              : 
     503              :  nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
     504              : 
     505            0 :  if (use_fftrisc) then
     506              :    !call wrtout(std_out, calling fftw3_fftrisc")
     507              : 
     508            0 :    if (ndat == 1) then
     509            0 :      if (fftcore_mixprec == 0) then
     510              :        call fftw3_fftrisc_dp(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     511            0 :          mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     512              :      else
     513              :        call fftw3_fftrisc_mixprec(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     514            0 :          mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     515              :      end if
     516              : 
     517              :    else
     518              :      ! All this boilerplate code is needed because the caller might pass zero-sized arrays
     519              :      ! for the arguments that are not referenced and we don't want to have problems at run-time.
     520              :      ! Moreover option 1 requires a special treatment when threads are started at this level.
     521              : 
     522              :      SELECT CASE (option)
     523              :      CASE (0)
     524              :        !
     525              :        ! fofgin -> fofr, no use of denpot, fofgout and npwout.
     526              :        if (.not.fftw3_spawn_threads_here(ndat,nthreads)) then
     527            0 :          do dat=1,ndat
     528            0 :            ptg = 1 + (dat-1)*npwin
     529            0 :            ptr = 1 + (dat-1)*ldx*ldy*ldz
     530              :            call fftw3_fftrisc_dp(cplex,denpot,fofgin(1,ptg),fofgout,fofr(1,ptr),gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     531            0 :              mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     532              :          end do
     533              :        else
     534              :          !$OMP PARALLEL DO PRIVATE(ptg,ptr)
     535              :          do dat=1,ndat
     536              :            ptg = 1 + (dat-1)*npwin
     537              :            ptr = 1 + (dat-1)*ldx*ldy*ldz
     538              :            call fftw3_fftrisc_dp(cplex,denpot,fofgin(1,ptg),fofgout,fofr(1,ptr),gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     539              :              mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     540              :          end do
     541              :        end if
     542              : 
     543              :      CASE (1)
     544              :        !fofgin -> local ur and accumulate density in denpot
     545              :        ! TODO this is delicate part to do in parallel, as one should OMP reduce denpot.
     546              :        ! but this causes problems with the stack.
     547              : 
     548            0 :        do dat=1,ndat
     549            0 :          ptg = 1 + (dat-1)*npwin
     550            0 :          ptr = 1 + (dat-1)*ldx*ldy*ldz
     551              :          call fftw3_fftrisc_dp(cplex,denpot,fofgin(1,ptg),fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     552            0 :            mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     553              :        end do
     554              : 
     555              :        ! This version doesn't seem efficient
     556              :        !!!  !$OMP PARALLEL PRIVATE(ptg,ptr,saveden)
     557              :        !!!         ABI_MALLOC(saveden, (ldx,ldy,ldz))
     558              :        !!!         saveden = zero
     559              :        !!!  !$OMP DO
     560              :        !!!         do dat=1,ndat
     561              :        !!!           ptg = 1 + (dat-1)*npwin
     562              :        !!!           ptr = 1 + (dat-1)*ldx*ldy*ldz
     563              :        !!!           call fftw3_fftrisc_dp(cplex,saveden,fofgin(1,ptg),fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     564              :        !!!  &          mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r)
     565              :        !!!         end do
     566              :        !!!  !$OMP END DO NOWAIT
     567              :        !!!  !$OMP CRITICAL (OMPC_addrho)
     568              :        !!!         denpot = denpot + saveden
     569              :        !!!  !$OMP END CRITICAL (OMPC_addrho)
     570              :        !!!         ABI_FREE(saveden)
     571              :        !!!  !$OMP END PARALLEL
     572              : 
     573              :      CASE (2)
     574              :        ! <G|vloc(r)|fofgin(r)> in fofgout
     575              :        if (.not.fftw3_spawn_threads_here(ndat,nthreads)) then
     576            0 :          do dat=1,ndat
     577            0 :            ptgin  = 1 + (dat-1)*npwin
     578            0 :            ptgout = 1 + (dat-1)*npwout
     579            0 :            if (fftcore_mixprec == 0) then
     580              :              call fftw3_fftrisc_dp(cplex,denpot,fofgin(1,ptgin),fofgout(1,ptgout),fofr,gboundin,gboundout,&
     581            0 :                  istwf_k,kg_kin,kg_kout,mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     582              :            else
     583              :              call fftw3_fftrisc_mixprec(cplex,denpot,fofgin(1,ptgin),fofgout(1,ptgout),fofr,gboundin,gboundout,&
     584            0 :                  istwf_k,kg_kin,kg_kout,mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     585              :            end if
     586              :          end do
     587              :        else
     588              :          !$OMP PARALLEL DO PRIVATE(ptgin,ptgout)
     589              :          do dat=1,ndat
     590              :            ptgin  = 1 + (dat-1)*npwin
     591              :            ptgout = 1 + (dat-1)*npwout
     592              :            call fftw3_fftrisc_dp(cplex,denpot,fofgin(1,ptgin),fofgout(1,ptgout),fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     593              :              mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     594              :          end do
     595              :        end if
     596              : 
     597              :      CASE (3)
     598              :        ! fofr -> fofgout
     599            0 :        if (.not.fftw3_spawn_threads_here(ndat,nthreads)) then
     600            0 :          do dat=1,ndat
     601            0 :            ptr    = 1 + (dat-1)*ldx*ldy*ldz
     602            0 :            ptgout = 1 + (dat-1)*npwout
     603              :            call fftw3_fftrisc_dp(cplex,denpot,fofgin,fofgout(1,ptgout),fofr(1,ptr),gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     604            0 :               mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     605              :          end do
     606              :        else
     607              :          !$OMP PARALLEL DO PRIVATE(ptr,ptgout)
     608              :          do dat=1,ndat
     609              :            ptr    = 1 + (dat-1)*ldx*ldy*ldz
     610              :            ptgout = 1 + (dat-1)*npwout
     611              :            call fftw3_fftrisc_dp(cplex,denpot,fofgin,fofgout(1,ptgout),fofr(1,ptr),gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     612              :              mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     613              :          end do
     614              :        end if
     615              : 
     616              :      CASE DEFAULT
     617            0 :        write(msg,'(a,i0,a)')'Option',option,' is not allowed. Only option=0, 1, 2 or 3 are allowed presently.'
     618            0 :        ABI_ERROR(msg)
     619              :      END SELECT
     620              : 
     621              :    end if
     622              : 
     623              :  else
     624              : 
     625              : #if 1
     626            0 :    SELECT CASE (option)
     627              :    CASE (0)
     628              :      !
     629              :      ! FFT u(g) --> u(r)
     630            0 :      if (.not.fftw3_spawn_threads_here(ndat,nthreads)) then
     631            0 :        call fftw3_fftug_dp(fftalg,fftcache,npwin,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_kin,gboundin,fofgin,fofr)
     632              :      else
     633              :        !$OMP PARALLEL DO PRIVATE(ptg, ptr)
     634              :        do dat=1,ndat
     635              :          ptg = 1 + (dat-1)*npwin
     636              :          ptr = 1 + (dat-1)*ldx*ldy*ldz
     637              :          call fftw3_fftug_dp(fftalg,fftcache,npwin,nx,ny,nz,ldx,ldy,ldz,ndat1,&
     638              : &          istwf_k,mgfft,kg_kin,gboundin,fofgin(1,ptg),fofr(1,ptr))
     639              :        end do
     640              :      end if
     641              : 
     642              :    CASE (1)
     643              :      ! TODO this is delicate part to do in parallel, as one should OMP reduce denpot.
     644            0 :      call fftw3_fftug_dp(fftalg,fftcache,npwin,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_kin,gboundin,fofgin,fofr)
     645            0 :      call cg_addtorho(nx,ny,nz,ldx,ldy,ldz,ndat,weight_r,weight_i,fofr,denpot)
     646              : 
     647              :    CASE (2)
     648              : 
     649            0 :      if (.not.fftw3_spawn_threads_here(ndat,nthreads)) then
     650            0 :        call fftw3_fftug_dp(fftalg,fftcache,npwin,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_kin,gboundin,fofgin,fofr)
     651            0 :        call cg_vlocpsi(nx,ny,nz,ldx,ldy,ldz,ndat,cplex,denpot,fofr)
     652              : 
     653              :        !  The data for option==2 is now in fofr.
     654            0 :        call fftw3_fftpad_dp(fofr,nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,-1,gboundout)
     655              : 
     656            0 :        call cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat,npwout,kg_kout,fofr,fofgout)
     657              :      else
     658              : 
     659              :        !$OMP PARALLEL DO PRIVATE(ptg, ptr)
     660              :        do dat=1,ndat
     661              :          ptg = 1 + (dat-1)*npwin
     662              :          ptr = 1 + (dat-1)*ldx*ldy*ldz
     663              :          call fftw3_fftug_dp(fftalg,fftcache,npwin,nx,ny,nz,ldx,ldy,ldz,ndat1,&
     664              :            istwf_k,mgfft,kg_kin,gboundin,fofgin(1,ptg),fofr(1,ptr))
     665              : 
     666              :          call cg_vlocpsi(nx,ny,nz,ldx,ldy,ldz,ndat1,cplex,denpot,fofr(1,ptr))
     667              : 
     668              :          !  The data for option==2 is now in fofr.
     669              :          call fftw3_fftpad_dp(fofr(1,ptr),nx,ny,nz,ldx,ldy,ldz,ndat1,mgfft,-1,gboundout)
     670              : 
     671              :          ptg = 1 + (dat-1)*npwout
     672              :          call cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat1,npwout,kg_kout,fofr(1,ptr),fofgout(1,ptg))
     673              :        end do
     674              :      end if
     675              : 
     676              :    CASE (3)
     677              :      !  The data for option==3 is already in fofr.
     678            0 :      if (.not.fftw3_spawn_threads_here(ndat,nthreads)) then
     679            0 :        call fftw3_fftpad_dp(fofr,nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,-1,gboundout)
     680            0 :        call cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat,npwout,kg_kout,fofr,fofgout)
     681              :      else
     682              :        !$OMP PARALLEL DO PRIVATE(ptg, ptr)
     683              :        do dat=1,ndat
     684              :          ptg = 1 + (dat-1)*npwout
     685              :          ptr = 1 + (dat-1)*ldx*ldy*ldz
     686              :          call fftw3_fftpad_dp(fofr(1,ptr),nx,ny,nz,ldx,ldy,ldz,ndat1,mgfft,-1,gboundout)
     687              :          call cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat1,npwout,kg_kout,fofr(1,ptr),fofgout(1,ptg))
     688              :        end do
     689              :      end if
     690              : 
     691              :    CASE DEFAULT
     692            0 :      write(msg,'(a,i0,a)')'Option',option,' is not allowed. Only option=0, 1, 2 or 3 are allowed presently.'
     693            0 :      ABI_ERROR(msg)
     694              :    END SELECT
     695              : 
     696              : #else
     697              :    symm=0; symm(1,1)=1; symm(2,2)=1; symm(3,3)=1
     698              :    use_fftbox = .FALSE.
     699              : #ifdef HAVE_OPENMP
     700              :    use_fftbox = (ndat>1)
     701              : #endif
     702              :    !use_fftbox = .TRUE.
     703              : 
     704              :    SELECT CASE (option)
     705              :    CASE (0)
     706              :      !
     707              :      ! FFT u(g) --> u(r)
     708              :      call sphere(fofgin,ndat,npwin,fofr,nx,ny,nz,ldx,ldy,ldz,kg_kin,istwf_k,1,me_g0,shiftg,symm,one)
     709              : 
     710              :      if (use_fftbox) then
     711              :        call fftw3_many_dft_ip(nx,ny,nz,ldx,ldy,ldz,ndat,ABI_FFTW_BACKWARD,fofr)
     712              :      else
     713              :        call fftw3_fftpad_dp(fofr,nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,ABI_FFTW_BACKWARD,gboundin)
     714              :      end if
     715              : 
     716              :    CASE (1)
     717              :      ! TODO this is delicate part to do in parallel, as one should OMP reduce denpot.
     718              : 
     719              :      call sphere(fofgin,ndat,npwin,fofr,nx,ny,nz,ldx,ldy,ldz,kg_kin,istwf_k,1,me_g0,shiftg,symm,one)
     720              : 
     721              :      if (use_fftbox) then
     722              :        call fftw3_many_dft_ip(nx,ny,nz,ldx,ldy,ldz,ndat,ABI_FFTW_BACKWARD,fofr)
     723              :      else
     724              :        call fftw3_fftpad_dp(fofr,nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,ABI_FFTW_BACKWARD,gboundin)
     725              :      end if
     726              : 
     727              :      call cg_addtorho(nx,ny,nz,ldx,ldy,ldz,ndat,weight_r,weight_i,fofr,denpot)
     728              : 
     729              :    CASE (2)
     730              : 
     731              :      call sphere(fofgin,ndat,npwin,fofr,nx,ny,nz,ldx,ldy,ldz,kg_kin,istwf_k,1,me_g0,shiftg,symm,one)
     732              : 
     733              :      if (use_fftbox) then
     734              :        call fftw3_many_dft_ip(nx,ny,nz,ldx,ldy,ldz,ndat,ABI_FFTW_BACKWARD,fofr)
     735              :      else
     736              :        call fftw3_fftpad_dp(fofr,nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,ABI_FFTW_BACKWARD,gboundin)
     737              :      end if
     738              : 
     739              :      call cg_vlocpsi(nx,ny,nz,ldx,ldy,ldz,ndat,cplex,denpot,fofr)
     740              : 
     741              :      ! The data for option==2 is now in fofr.
     742              :      if (use_fftbox) then
     743              :        call fftw3_many_dft_ip(nx,ny,nz,ldx,ldy,ldz,ndat,ABI_FFTW_FORWARD,fofr)
     744              :      else
     745              :        call fftw3_fftpad_dp(fofr,nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,ABI_FFTW_FORWARD,gboundout)
     746              :      end if
     747              : 
     748              :      call cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat,npwout,kg_kout,fofr,fofgout)
     749              : 
     750              :    CASE (3)
     751              :      !  The data for option==3 is already in fofr.
     752              :      call fftw3_fftpad_dp(fofr,nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,ABI_FFTW_FORWARD,gboundout)
     753              : 
     754              :      call cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat,npwout,kg_kout,fofr,fofgout)
     755              : 
     756              :    CASE DEFAULT
     757              :      write(msg,'(a,i0,a)')'Option',option,' is not allowed. Only option=0, 1, 2 or 3 are allowed presently.'
     758              :      ABI_ERROR(msg)
     759              :    END SELECT
     760              : #endif
     761              :  end if
     762              : 
     763            0 : end subroutine fftw3_seqfourwf
     764              : !!***
     765              : 
     766              : !----------------------------------------------------------------------
     767              : 
     768              : !!****f* m_fftw3/fftw3_fftrisc_sp
     769              : !! NAME
     770              : !! fftw3_fftrisc_sp
     771              : !!
     772              : !! FUNCTION
     773              : !! Carry out Fourier transforms between real and reciprocal (G) space,
     774              : !! for wavefunctions, contained in a sphere in reciprocal space,
     775              : !! in both directions. Also accomplish some post-processing.
     776              : !! See fftw3_fftrisc_dp for API doc.
     777              : !!
     778              : !! SOURCE
     779              : 
     780            0 : subroutine fftw3_fftrisc_sp(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     781              :                             mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option, &
     782              :                             weight_r,weight_i, abi_convention, iscale)
     783              : 
     784              : !Arguments ------------------------------------
     785              : !scalars
     786              :  integer,intent(in) :: cplex,istwf_k,mgfft,ldx,ldy,ldz,npwin,npwout,option
     787              :  real(dp),intent(in) :: weight_i,weight_r
     788              : !arrays
     789              :  integer,intent(in) :: gboundin(2*mgfft+8,2),gboundout(2*mgfft+8,2)
     790              :  integer,intent(in) :: kg_kin(3,npwin),kg_kout(3,npwout),ngfft(18)
     791              :  real(sp),intent(in) :: fofgin(2,npwin)
     792              :  real(dp),intent(inout) :: denpot(cplex*ldx,ldy,ldz)
     793              :  real(sp),intent(inout) :: fofr(2,ldx*ldy*ldz)
     794              :  real(sp),intent(inout) :: fofgout(2,npwout)
     795              :  logical,optional,intent(in) :: abi_convention
     796              :  integer,optional,intent(in) :: iscale
     797              : ! *************************************************************************
     798              : 
     799              : #ifdef HAVE_FFTW3
     800              : 
     801              : #undef  FFT_PRECISION
     802              : #undef  MYKIND
     803              : #undef  MYCZERO
     804              : #undef  MYCMPLX
     805              : #undef  MYCONJG
     806              : 
     807              : #define FFT_PRECISION FFT_SINGLE
     808              : #define MYKIND SP
     809              : #define MYCZERO (0._sp,0._sp)
     810              : #define MYCMPLX  CMPLX
     811              : #define MYCONJG  CONJG
     812              : 
     813              : #include "fftw3_fftrisc.finc"
     814              : 
     815              : #else
     816            0 :  ABI_ERROR("FFTW3 support not activated")
     817              :  ABI_UNUSED((/cplex,gboundin(1,1),gboundout(1,1),istwf_k,kg_kin(1,1),kg_kout(1,1)/))
     818              :  ABI_UNUSED((/mgfft,ngfft(1),npwin,npwout,ldx,ldy,ldz,option/))
     819              :  ABI_UNUSED((/denpot(1,1,1),weight_r,weight_i/))
     820              :  ABI_UNUSED((/fofgin(1,1),fofgout(1,1),fofr(1,1)/))
     821              : #endif
     822              : 
     823            0 : end subroutine fftw3_fftrisc_sp
     824              : !!***
     825              : 
     826              : !----------------------------------------------------------------------
     827              : 
     828              : !!****f* m_fftw3/fftw3_fftrisc_dp
     829              : !! NAME
     830              : !! fftw3_fftrisc_dp
     831              : !!
     832              : !! FUNCTION
     833              : !! Carry out Fourier transforms between real and reciprocal (G) space,
     834              : !! for wavefunctions, contained in a sphere in reciprocal space,
     835              : !! in both directions. Also accomplish some post-processing.
     836              : !!
     837              : !! NOTES
     838              : !! Specifically uses rather sophisticated algorithms, based on S Goedecker
     839              : !! routines, specialized for superscalar RISC architecture.
     840              : !! Zero padding : saves 7/12 execution time
     841              : !! Bi-dimensional data locality in most of the routine : cache reuse
     842              : !! For k-point (0 0 0) : takes advantage of symmetry of data.
     843              : !! Note however that no blocking is used, in both 1D z-transform
     844              : !! or subsequent 2D transform. This should be improved.
     845              : !!
     846              : !! INPUTS
     847              : !!  cplex= if 1 , denpot is real, if 2 , denpot is complex
     848              : !!     (cplex=2 only allowed for option=2 when istwf_k=1)
     849              : !!     one can also use cplex=0 if option=0 or option=3
     850              : !!  fofgin(2,npwin)=holds input wavefunction in G vector basis sphere.
     851              : !!  gboundin(2*mgfft+8,2)=sphere boundary info for reciprocal to real space
     852              : !!  gboundout(2*mgfft+8,2)=sphere boundary info for real to reciprocal space
     853              : !!  istwf_k=option parameter that describes the storage of wfs
     854              : !!  kg_kin(3,npwin)=reduced planewave coordinates, input
     855              : !!  kg_kout(3,npwout)=reduced planewave coordinates, output
     856              : !!  mgfft=maximum size of 1D FFTs
     857              : !!  ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
     858              : !!  npwin=number of elements in fofgin array (for option 0, 1 and 2)
     859              : !!  npwout=number of elements in fofgout array (for option 2 and 3)
     860              : !!  ldx,ldy,ldz=ngfft(4),ngfft(5),ngfft(6), dimensions of fofr.
     861              : !!  option= if 0: do direct FFT
     862              : !!          if 1: do direct FFT, then sum the density
     863              : !!          if 2: do direct FFT, multiply by the potential, then do reverse FFT
     864              : !!          if 3: do reverse FFT only
     865              : !!  weight=weight to be used for the accumulation of the density in real space
     866              : !!          (needed only when option=1)
     867              : !!
     868              : !! OUTPUT
     869              : !!  (see side effects)
     870              : !!
     871              : !! OPTIONS
     872              : !!  The different options are:
     873              : !!  - reciprocal to real space and output the result (when option=0),
     874              : !!  - reciprocal to real space and accumulate the density (when option=1) or
     875              : !!  - reciprocal to real space, apply the local potential to the wavefunction
     876              : !!    in real space and produce the result in reciprocal space (when option=2)
     877              : !!  - real space to reciprocal space (when option=3).
     878              : !!  option=0 IS NOT ALLOWED when istwf_k>2
     879              : !!  option=3 IS NOT ALLOWED when istwf_k>=2
     880              : !!
     881              : !! SIDE EFFECTS
     882              : !!  for option==0, fofgin(2,npwin)=holds input wavefunction in G sphere;
     883              : !!                 fofr(2,ldx,ldy,ldz) contains the Fourier Transform of fofgin;
     884              : !!                 no use of denpot, fofgout and npwout.
     885              : !!  for option==1, fofgin(2,npwin)=holds input wavefunction in G sphere;
     886              : !!                 denpot(cplex*ldx,ldy,ldz) contains the input density at input,
     887              : !!                 and the updated density at output;
     888              : !!                 no use of fofgout and npwout.
     889              : !!  for option==2, fofgin(2,npwin)=holds input wavefunction in G sphere;
     890              : !!                 denpot(cplex*ldx,ldy,ldz) contains the input local potential;
     891              : !!                 fofgout(2,npwout) contains the output function;
     892              : !!  for option==3, fofr(2,ldx,ldy,ldz) contains the real space wavefunction;
     893              : !!                 fofgout(2,npwout) contains its Fourier transform;
     894              : !!                 no use of fofgin and npwin.
     895              : !!
     896              : !! SOURCE
     897              : 
     898            0 : subroutine fftw3_fftrisc_dp(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     899              :                             mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option, &
     900              :                             weight_r, weight_i, abi_convention, iscale)
     901              : 
     902              : !Arguments ------------------------------------
     903              : !scalars
     904              :  integer,intent(in) :: cplex,istwf_k,mgfft,ldx,ldy,ldz,npwin,npwout,option
     905              :  real(dp),intent(in) :: weight_r,weight_i
     906              : !arrays
     907              :  integer,intent(in) :: gboundin(2*mgfft+8,2),gboundout(2*mgfft+8,2)
     908              :  integer,intent(in) :: kg_kin(3,npwin),kg_kout(3,npwout),ngfft(18)
     909              :  real(dp),intent(in) :: fofgin(2,npwin)
     910              :  real(dp),intent(inout) :: denpot(cplex*ldx,ldy,ldz),fofr(2,ldx*ldy*ldz)
     911              :  real(dp),intent(inout) :: fofgout(2,npwout)
     912              :  logical,optional,intent(in) :: abi_convention
     913              :  integer,optional,intent(in) :: iscale
     914              : ! *************************************************************************
     915              : 
     916              : #ifdef HAVE_FFTW3
     917              : 
     918              : #undef  FFT_PRECISION
     919              : #undef  MYKIND
     920              : #undef  MYCZERO
     921              : #undef  MYCMPLX
     922              : #undef  MYCONJG
     923              : 
     924              : #define FFT_PRECISION FFT_DOUBLE
     925              : #define MYKIND DP
     926              : #define MYCZERO (0._dp,0._dp)
     927              : #define MYCMPLX  DCMPLX
     928              : #define MYCONJG  DCONJG
     929              : 
     930              : #include "fftw3_fftrisc.finc"
     931              : 
     932              : #else
     933            0 :  ABI_ERROR("FFTW3 support not activated")
     934              :  ABI_UNUSED((/cplex,gboundin(1,1),gboundout(1,1),istwf_k,kg_kin(1,1),kg_kout(1,1)/))
     935              :  ABI_UNUSED((/mgfft,ngfft(1),npwin,npwout,ldx,ldy,ldz,option/))
     936              :  ABI_UNUSED((/denpot(1,1,1),fofgin(1,1),fofgout(1,1),fofr(1,1),weight_r,weight_i/))
     937              : #endif
     938              : 
     939            0 : end subroutine fftw3_fftrisc_dp
     940              : !!***
     941              : 
     942              : !----------------------------------------------------------------------
     943              : 
     944              : !!****f* m_fftw3/fftw3_fftrisc_mixprec
     945              : !! NAME
     946              : !! fftw3_fftrisc_mixprec
     947              : !!
     948              : !! FUNCTION
     949              : !!  Mixed precision version of fftrisc: input/output in dp, computation done in sp.
     950              : !!  See fftw3_fftrisc_dp for API docs.
     951              : !!
     952              : !! SOURCE
     953              : 
     954            0 : subroutine fftw3_fftrisc_mixprec(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,kg_kin,kg_kout,&
     955              :                                  mgfft,ngfft,npwin,npwout,ldx,ldy,ldz,option, &
     956              :                                  weight_r,weight_i, abi_convention, iscale) ! optional
     957              : 
     958              : !Arguments ------------------------------------
     959              : !scalars
     960              :  integer,intent(in) :: cplex,istwf_k,mgfft,ldx,ldy,ldz,npwin,npwout,option
     961              :  real(dp),intent(in) :: weight_r,weight_i
     962              : !arrays
     963              :  integer,intent(in) :: gboundin(2*mgfft+8,2),gboundout(2*mgfft+8,2)
     964              :  integer,intent(in) :: kg_kin(3,npwin),kg_kout(3,npwout),ngfft(18)
     965              :  real(dp),intent(in) :: fofgin(2,npwin)
     966              :  real(dp),intent(inout) :: denpot(cplex*ldx,ldy,ldz),fofr(2,ldx*ldy*ldz)
     967              :  real(dp),intent(inout) :: fofgout(2,npwout)
     968              :  logical,optional,intent(in) :: abi_convention
     969              :  integer,optional,intent(in) :: iscale
     970              : ! *************************************************************************
     971              : 
     972              : #ifdef HAVE_FFTW3
     973              : 
     974              : #undef  FFT_PRECISION
     975              : #undef  MYKIND
     976              : #undef  MYCZERO
     977              : #undef  MYCMPLX
     978              : #undef  MYCONJG
     979              : 
     980              : #define FFT_PRECISION FFT_MIXPREC
     981              : #define MYKIND SP
     982              : #define MYCZERO (0._sp,0._sp)
     983              : #define MYCMPLX  CMPLX
     984              : #define MYCONJG  CONJG
     985              : 
     986              : #include "fftw3_fftrisc.finc"
     987              : 
     988              : #else
     989            0 :  ABI_ERROR("FFTW3 support not activated")
     990              :  ABI_UNUSED((/cplex,gboundin(1,1),gboundout(1,1),istwf_k,kg_kin(1,1),kg_kout(1,1)/))
     991              :  ABI_UNUSED((/mgfft,ngfft(1),npwin,npwout,ldx,ldy,ldz,option/))
     992              :  ABI_UNUSED((/denpot(1,1,1),fofgin(1,1),fofgout(1,1),fofr(1,1),weight_r,weight_i/))
     993              : #endif
     994              : 
     995            0 : end subroutine fftw3_fftrisc_mixprec
     996              : !!***
     997              : 
     998              : !----------------------------------------------------------------------
     999              : 
    1000              : !!****f* m_fftw3/fftw3_fftug_dp
    1001              : !! NAME
    1002              : !! fftw3_fftug_dp
    1003              : !!
    1004              : !! FUNCTION
    1005              : !! Compute ndat zero-padded FFTs from G to R space.
    1006              : !! Mainly used for the transform of wavefunctions.
    1007              : !! TARGET: dp arrays with real and imaginary part
    1008              : !!
    1009              : !! INPUTS
    1010              : !! fftalg=FFT algorithm (see input variable)
    1011              : !! fftcache=size of the cache (kB)
    1012              : !! npw_k=number of plane waves for this k-point.
    1013              : !! nx,ny,nz=Number of point along the three directions.
    1014              : !! ldx,ldy,ldz=Leading dimensions of the array.
    1015              : !! ndat=Number of transforms
    1016              : !! istwf_k=Option describing the storage of the wavefunction.
    1017              : !! mgfft=Max number of FFT divisions (used to dimension gbound)
    1018              : !! kg_k(3,npw_k)=G-vectors in reduced coordinates
    1019              : !! gbound(2*mgfft+8,2)=Table for zero-padded FFT. See sphereboundary.
    1020              : !! ug(npw_k*ndat)=wavefunctions in reciprocal space.
    1021              : !!
    1022              : !! OUTPUT
    1023              : !!  ur(ldx*ldy*ldz*ndat)=wavefunctions in real space.
    1024              : !!
    1025              : !! SOURCE
    1026              : 
    1027            0 : subroutine fftw3_fftug_dp(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
    1028            0 :                           istwf_k, mgfft, kg_k,gbound, ug, ur, &
    1029              :                           isign, iscale)  ! optional
    1030              : 
    1031              : !Arguments ------------------------------------
    1032              : !scalars
    1033              :  integer,intent(in) :: fftalg,fftcache
    1034              :  integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
    1035              : !arrays
    1036              :  integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
    1037              :  real(dp),target,intent(in) :: ug(2*npw_k*ndat)
    1038              :  real(dp),target,intent(inout) :: ur(2*ldx*ldy*ldz*ndat)
    1039              :  integer,optional,intent(in) :: isign, iscale
    1040              : 
    1041              : #ifdef HAVE_FFTW3
    1042              : !Local variables-------------------------------
    1043              : !scalars
    1044              :  integer,parameter :: dist=2
    1045              :  integer :: iscale__, isign__
    1046              :  real(dp) :: fofgout(2,0)
    1047              :  real(dp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
    1048              : ! *************************************************************************
    1049              : 
    1050              :  iscale__ = 0; if (present(iscale)) iscale__ = iscale
    1051              :  isign__ = +1; if (present(isign)) isign__ = isign
    1052              : 
    1053              : #undef TK_PREF
    1054              : #define TK_PREF(name) CONCAT(cg_,name)
    1055              : #undef TK_PREF_box2gsph
    1056              : #define TK_PREF_box2gsph cg_box2gsph
    1057              : #undef TK_PREF_gsph2box
    1058              : #define TK_PREF_gsph2box cg_gsph2box
    1059              : 
    1060              : #undef  FFT_PRECISION
    1061              : #define FFT_PRECISION FFT_DOUBLE
    1062              : 
    1063              : #include "fftug.finc"
    1064              : 
    1065              : #undef  FFT_PRECISION
    1066              : 
    1067              : #else
    1068              :  ! Silence compiler warning
    1069            0 :  ABI_ERROR("FFT_FFTW3 support not activated")
    1070              :  ABI_UNUSED((/fftalg,fftcache,npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1),iscale,isign/))
    1071              :  ABI_UNUSED((/ug(1),ur(1)/))
    1072              : #endif
    1073              : 
    1074            0 : end subroutine fftw3_fftug_dp
    1075              : !!***
    1076              : 
    1077              : !----------------------------------------------------------------------
    1078              : 
    1079              : !!****f* m_fftw3/fftw3_fftug_spc
    1080              : !! NAME
    1081              : !! fftw3_fftug_spc
    1082              : !!
    1083              : !! FUNCTION
    1084              : !! Compute ndat zero-padded FFTs from G-->R.
    1085              : !! Mainly used for the transform of wavefunctions.
    1086              : !! TARGET: spc arrays
    1087              : !! See fftw3_fftug_dp for API docs.
    1088              : !!
    1089              : !! SOURCE
    1090              : 
    1091            0 : subroutine fftw3_fftug_spc(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
    1092            0 :                            istwf_k, mgfft, kg_k, gbound, ug, ur, &
    1093              :                            isign, iscale) ! optional
    1094              : 
    1095              : !Arguments ------------------------------------
    1096              : !scalars
    1097              :  integer,intent(in) :: fftalg,fftcache
    1098              :  integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
    1099              :  integer,optional,intent(in) :: isign, iscale
    1100              : !arrays
    1101              :  integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
    1102              :  complex(sp),target,intent(in) :: ug(npw_k*ndat)
    1103              :  complex(sp),target,intent(inout) :: ur(ldx*ldy*ldz*ndat)
    1104              : 
    1105              : #ifdef HAVE_FFTW3
    1106              : !Local variables-------------------------------
    1107              : !scalars
    1108              :  integer,parameter :: dist=1
    1109              :  integer :: iscale__, isign__
    1110              : !arrays
    1111              :  real(sp) :: fofgout(2,0)
    1112              :  real(sp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
    1113              : ! *************************************************************************
    1114              : 
    1115              :  iscale__ = 0; if (present(iscale)) iscale__ = iscale
    1116              :  isign__ = +1; if (present(isign)) isign__ = isign
    1117              : 
    1118              : #undef TK_PREF
    1119              : #define TK_PREF(name) CONCAT(cplx_,name)
    1120              : #undef TK_PREF_box2gsph
    1121              : #define TK_PREF_box2gsph cplx_box2gsph
    1122              : #undef TK_PREF_gsph2box
    1123              : #define TK_PREF_gsph2box cplx_gsph2box
    1124              : 
    1125              : #undef  FFT_PRECISION
    1126              : #define FFT_PRECISION FFT_SINGLE
    1127              : 
    1128              : #include "fftug.finc"
    1129              : 
    1130              : #undef  FFT_PRECISION
    1131              : 
    1132              : #else
    1133              :  ! Silence compiler warning
    1134            0 :  ABI_ERROR("FFTW3 support not activated")
    1135              :  ABI_UNUSED((/fftalg,fftcache,npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1)/))
    1136              :  ABI_UNUSED((/ug(1),ur(1)/))
    1137              : #endif
    1138              : 
    1139            0 : end subroutine fftw3_fftug_spc
    1140              : !!***
    1141              : 
    1142              : !----------------------------------------------------------------------
    1143              : 
    1144              : !!****f* m_fftw3/fftw3_fftug_dpc
    1145              : !! NAME
    1146              : !! fftw3_fftug_dpc
    1147              : !!
    1148              : !! FUNCTION
    1149              : !! Compute ndat zero-padded FFTs.
    1150              : !! Mainly used for the transform of wavefunctions.
    1151              : !! TARGET: DP arrays
    1152              : !! See fftw3_fftug_dp for API docs.
    1153              : !!
    1154              : !! SOURCE
    1155              : 
    1156            0 : subroutine fftw3_fftug_dpc(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
    1157            0 :                            istwf_k, mgfft, kg_k, gbound, ug, ur, &
    1158              :                            isign, iscale)  ! optional
    1159              : 
    1160              : !Arguments ------------------------------------
    1161              : !scalars
    1162              :  integer,intent(in) :: fftalg,fftcache
    1163              :  integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
    1164              : !arrays
    1165              :  integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
    1166              :  complex(dp),target,intent(in) :: ug(npw_k*ndat)
    1167              :  complex(dp),target,intent(inout) :: ur(ldx*ldy*ldz*ndat)
    1168              :  integer,optional,intent(in) :: isign, iscale
    1169              : 
    1170              : #ifdef HAVE_FFTW3
    1171              : !Local variables-------------------------------
    1172              : !scalars
    1173              :  integer,parameter :: dist=1
    1174              :  integer :: iscale__, isign__
    1175              : !arrays
    1176              :  real(dp) :: fofgout(2,0)
    1177              :  real(dp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
    1178              : ! *************************************************************************
    1179              : 
    1180              :  iscale__ = 0; if (present(iscale)) iscale__ = iscale
    1181              :  isign__ = +1; if (present(isign)) isign__ = isign
    1182              : 
    1183              : #undef TK_PREF
    1184              : #define TK_PREF(name) CONCAT(cplx_,name)
    1185              : #undef TK_PREF_box2gsph
    1186              : #define TK_PREF_box2gsph cplx_box2gsph
    1187              : #undef TK_PREF_gsph2box
    1188              : #define TK_PREF_gsph2box cplx_gsph2box
    1189              : 
    1190              : #undef  FFT_PRECISION
    1191              : #define FFT_PRECISION FFT_DOUBLE
    1192              : 
    1193              : #include "fftug.finc"
    1194              : 
    1195              : #undef  FFT_PRECISION
    1196              : 
    1197              : #else
    1198              :  ! Silence compiler warning
    1199            0 :  ABI_ERROR("FFTW3 support not activated")
    1200              :  ABI_UNUSED((/fftalg,fftcache,npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1)/))
    1201              :  ABI_UNUSED((/ug(1),ur(1)/))
    1202              : #endif
    1203              : 
    1204            0 : end subroutine fftw3_fftug_dpc
    1205              : !!***
    1206              : 
    1207              : !----------------------------------------------------------------------
    1208              : 
    1209              : !!****f* m_fftw3/fftw3_fftur_dp
    1210              : !! NAME
    1211              : !! fftw3_fftur_dp
    1212              : !!
    1213              : !! FUNCTION
    1214              : !! Compute ndat zero-padded FFTs from R- to G-space .
    1215              : !! Mainly used for the transform of wavefunctions.
    1216              : !! TARGET: dp arrays
    1217              : !!
    1218              : !! INPUTS
    1219              : !! fftalg=FFT algorithm (see input variable)
    1220              : !! fftcache=size of the cache (kB)
    1221              : !! npw_k=number of plane waves for this k-point.
    1222              : !! nx,ny,nz=Number of point along the three directions.
    1223              : !! ldx,ldy,ldz=Leading dimensions of the array.
    1224              : !! ndat=Number of transforms
    1225              : !! istwf_k=Option describing the storage of the wavefunction.
    1226              : !! mgfft=Max number of FFT divisions (used to dimension gbound)
    1227              : !! kg_k(3,npw_k)=G-vectors in reduced coordinates
    1228              : !! gbound(2*mgfft+8,2)=Table for padded-FFT. See sphereboundary.
    1229              : !!
    1230              : !! SIDE EFFECT
    1231              : !! ur(ldx*ldy*ldz*ndat)= In input: wavefunctions in real space.
    1232              : !!                       Destroyed in output. Do not use it anymore!
    1233              : !! OUTPUT
    1234              : !! ug(npw_k*ndat)=wavefunctions in reciprocal space.
    1235              : !!
    1236              : !! SOURCE
    1237              : 
    1238            0 : subroutine fftw3_fftur_dp(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
    1239            0 :                           istwf_k, mgfft, kg_k, gbound, ur, ug, &
    1240              :                           isign, iscale) ! optional
    1241              : 
    1242              : !Arguments ------------------------------------
    1243              : !scalars
    1244              :  integer,intent(in) :: fftalg,fftcache
    1245              :  integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
    1246              :  integer,optional,intent(in) :: isign, iscale
    1247              : !arrays
    1248              :  integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
    1249              :  real(dp),target,intent(inout) :: ur(2*ldx*ldy*ldz*ndat)
    1250              :  real(dp),target,intent(inout) :: ug(2*npw_k*ndat)
    1251              : 
    1252              : #ifdef HAVE_FFTW3
    1253              : !Local variables-------------------------------
    1254              : !scalars
    1255              :  integer,parameter :: dist=2
    1256              :  integer :: iscale__, isign__
    1257              : !arrays
    1258              :  real(dp) :: dum_ugin(2,0)
    1259              :  real(dp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
    1260              : ! *************************************************************************
    1261              : 
    1262              :  iscale__ = 1; if (present(iscale)) iscale__ = iscale
    1263              :  isign__ = -1; if (present(isign)) isign__ = isign
    1264              : 
    1265              : #undef TK_PREF
    1266              : #define TK_PREF(name) CONCAT(cg_,name)
    1267              : #undef TK_PREF_box2gsph
    1268              : #define TK_PREF_box2gsph cg_box2gsph
    1269              : #undef TK_PREF_gsph2box
    1270              : #define TK_PREF_gsph2box cg_gsph2box
    1271              : 
    1272              : #undef  FFT_PRECISION
    1273              : #define FFT_PRECISION FFT_DOUBLE
    1274              : 
    1275              : #include "fftur.finc"
    1276              : 
    1277              : #undef  FFT_PRECISION
    1278              : 
    1279              : #else
    1280              :  ! Silence compiler warning
    1281            0 :  ABI_ERROR("FFTW3 support not activated")
    1282              :  ABI_UNUSED((/fftalg,fftcache/))
    1283              :  ABI_UNUSED((/npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1)/))
    1284              :  ABI_UNUSED((/ug(1),ur(1)/))
    1285              : #endif
    1286              : 
    1287            0 : end subroutine fftw3_fftur_dp
    1288              : !!***
    1289              : 
    1290              : !----------------------------------------------------------------------
    1291              : 
    1292              : !!****f* m_fftw3/fftw3_fftur_spc
    1293              : !! NAME
    1294              : !! fftw3_fftur_spc
    1295              : !!
    1296              : !! FUNCTION
    1297              : !! Compute ndat zero-padded FFTs from R- to G-space .
    1298              : !! Mainly used for the transform of wavefunctions.
    1299              : !! TARGET: spc arrays
    1300              : !! See fftw3_fftur_dp for API doc.
    1301              : !!
    1302              : !! SOURCE
    1303              : 
    1304            0 : subroutine fftw3_fftur_spc(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
    1305            0 :                            istwf_k, mgfft, kg_k, gbound, ur, ug, &
    1306              :                            isign, iscale) ! optional
    1307              : 
    1308              : !Arguments ------------------------------------
    1309              : !scalars
    1310              :  integer,intent(in) :: fftalg,fftcache
    1311              :  integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
    1312              :  integer,optional,intent(in) :: isign, iscale
    1313              : !arrays
    1314              :  integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
    1315              :  complex(sp),target,intent(inout) :: ur(ldx*ldy*ldz*ndat)
    1316              :  complex(sp),target,intent(inout) :: ug(npw_k*ndat)
    1317              : 
    1318              : #ifdef HAVE_FFTW3
    1319              : !Local variables-------------------------------
    1320              : !scalars
    1321              :  integer,parameter :: dist=1
    1322              :  integer :: iscale__, isign__
    1323              : !arrays
    1324              :  real(sp) :: dum_ugin(2,0)
    1325              :  real(sp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
    1326              : ! *************************************************************************
    1327              : 
    1328              :  iscale__ = 1; if (present(iscale)) iscale__ = iscale
    1329              :  isign__ = -1; if (present(isign)) isign__ = isign
    1330              : 
    1331              : #undef TK_PREF
    1332              : #define TK_PREF(name) CONCAT(cplx_,name)
    1333              : #undef TK_PREF_box2gsph
    1334              : #define TK_PREF_box2gsph cplx_box2gsph
    1335              : #undef TK_PREF_gsph2box
    1336              : #define TK_PREF_gsph2box cplx_gsph2box
    1337              : 
    1338              : #undef  FFT_PRECISION
    1339              : #define FFT_PRECISION FFT_SINGLE
    1340              : 
    1341              : #include "fftur.finc"
    1342              : 
    1343              : #undef  FFT_PRECISION
    1344              : 
    1345              : #else
    1346              :  ! Silence compiler warning
    1347            0 :  ABI_ERROR("FFTW3 support not activated")
    1348              :  ABI_UNUSED((/fftalg,fftcache/))
    1349              :  ABI_UNUSED((/npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1)/))
    1350              :  ABI_UNUSED((/ug(1),ur(1)/))
    1351              : #endif
    1352              : 
    1353            0 : end subroutine fftw3_fftur_spc
    1354              : !!***
    1355              : 
    1356              : !----------------------------------------------------------------------
    1357              : 
    1358              : !!****f* m_fftw3/fftw3_fftur_dpc
    1359              : !! NAME
    1360              : !! fftw3_fftur_dpc
    1361              : !!
    1362              : !! FUNCTION
    1363              : !! Compute ndat zero-padded FFTs from R ro G.
    1364              : !! Mainly used for the transform of wavefunctions.
    1365              : !! TARGET: DP arrays
    1366              : !! See fftw3_fftur_dp for API doc.
    1367              : !!
    1368              : !! SOURCE
    1369              : 
    1370            0 : subroutine fftw3_fftur_dpc(fftalg, fftcache, npw_k, nx, ny, nz, ldx, ldy, ldz, ndat, &
    1371            0 :                            istwf_k, mgfft, kg_k, gbound, ur, ug, &
    1372              :                            isign, iscale) ! optional
    1373              : 
    1374              : !Arguments ------------------------------------
    1375              : !scalars
    1376              :  integer,intent(in) :: fftalg,fftcache
    1377              :  integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft
    1378              :  integer,optional,intent(in) :: isign, iscale
    1379              : !arrays
    1380              :  integer,intent(in) :: gbound(2*mgfft+8,2),kg_k(3,npw_k)
    1381              :  complex(dp),target,intent(inout) :: ur(ldx*ldy*ldz*ndat)
    1382              :  complex(dp),target,intent(inout) :: ug(npw_k*ndat)
    1383              : 
    1384              : #ifdef HAVE_FFTW3
    1385              : !Local variables-------------------------------
    1386              : !scalars
    1387              :  integer,parameter :: dist=1
    1388              :  integer :: iscale__, isign__
    1389              : !arrays
    1390              :  real(dp) :: dum_ugin(2,0)
    1391              :  real(dp),contiguous, pointer :: real_ug(:,:),real_ur(:,:)
    1392              : ! *************************************************************************
    1393              : 
    1394              :  iscale__ = 1; if (present(iscale)) iscale__ = iscale
    1395              :  isign__ = -1; if (present(isign)) isign__ = isign
    1396              : 
    1397              : #undef TK_PREF
    1398              : #define TK_PREF(name) CONCAT(cplx_,name)
    1399              : #undef TK_PREF_box2gsph
    1400              : #define TK_PREF_box2gsph cplx_box2gsph
    1401              : #undef TK_PREF_gsph2box
    1402              : #define TK_PREF_gsph2box cplx_gsph2box
    1403              : 
    1404              : #undef  FFT_PRECISION
    1405              : #define FFT_PRECISION FFT_DOUBLE
    1406              : 
    1407              : #include "fftur.finc"
    1408              : 
    1409              : #undef  FFT_PRECISION
    1410              : 
    1411              : #else
    1412              :  ! Silence compiler warning
    1413            0 :  ABI_ERROR("FFTW3 support not activated")
    1414              :  ABI_UNUSED((/fftalg,fftcache/))
    1415              :  ABI_UNUSED((/npw_k,nx,ny,nz,ldx,ldy,ldz,ndat,istwf_k,mgfft,kg_k(1,1),gbound(1,1)/))
    1416              :  ABI_UNUSED((/ug(1),ur(1)/))
    1417              : #endif
    1418              : 
    1419            0 : end subroutine fftw3_fftur_dpc
    1420              : !!***
    1421              : 
    1422              : !----------------------------------------------------------------------
    1423              : 
    1424              : !!****f* m_fftw3/fftw3_c2c_ip_spc
    1425              : !! NAME
    1426              : !!  fftw3_c2c_ip_spc
    1427              : !!
    1428              : !! FUNCTION
    1429              : !! Driver routine for in-place 3D complex-complex FFT.
    1430              : !! TARGET: Simple precision complex arrays.
    1431              : !!
    1432              : !! INPUTS
    1433              : !! nx,ny,nz=Number of points along the three directions.
    1434              : !! ldx,ldy,ldz=Physical dimensions of the array.
    1435              : !! ndat=Number of FFTs to be done.
    1436              : !! iscale=0 if G --> R FFT should not be scaled.
    1437              : !! isign= +1 : ff(G) => ff(R); -1 : ff(R) => ff(G)
    1438              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    1439              : !!   Defaults to ABI_FFTW_ESTIMATE.
    1440              : !!
    1441              : !! SIDE EFFECTS
    1442              : !!  ff(ldx*ldy*ldz*ndat)=
    1443              : !!    In input: the complex array to be transformed.
    1444              : !!    In output: the Fourier transformed in the space specified by isign.
    1445              : !!
    1446              : !! SOURCE
    1447              : 
    1448            0 : subroutine fftw3_c2c_ip_spc(nx, ny, nz, ldx, ldy, ldz, ndat, iscale, isign, ff, fftw_flags)
    1449              : 
    1450              : !Arguments ------------------------------------
    1451              : !scalars
    1452              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,iscale,isign
    1453              :  integer,optional,intent(in) :: fftw_flags
    1454              : !arrays
    1455              :  complex(sp),intent(inout) :: ff(ldx*ldy*ldz*ndat)
    1456              : 
    1457              : #ifdef HAVE_FFTW3
    1458              : !Local variables-------------------------------
    1459              : !scalars
    1460              :  integer,parameter :: rank3=3,nt_all=-1
    1461              :  integer :: my_flags,dist,stride
    1462              :  integer(KIND_FFTW_PLAN) :: my_plan
    1463              : !arrays
    1464              :  integer :: embed(rank3),n(rank3)
    1465              : ! *************************************************************************
    1466              : 
    1467              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags=fftw_flags
    1468              : 
    1469              :  stride = 1
    1470              :  dist   = ldx*ldy*ldz
    1471              :  embed  = [ldx, ldy, ldz]
    1472              :  n      = [nx, ny, nz]
    1473              : 
    1474              :  my_plan = fftw3_plan_many_dft(rank3, n, ndat, ff, embed, stride, dist, ff, embed, stride, dist, isign, my_flags, nt_all)
    1475              : 
    1476              :  ! Now perform the 3D FFT via FFTW.
    1477              :  call sfftw_execute_dft(my_plan, ff, ff)
    1478              : 
    1479              :  call fftw3_destroy_plan(my_plan)
    1480              : 
    1481              :  if (isign == ABI_FFTW_FORWARD .and. iscale /= 0) then ! -1, FFTW returns not normalized FTs
    1482              :    call xscal(ldx*ldy*ldz*ndat, REAL(one/(nx*ny*nz),KIND=sp), ff, 1)
    1483              :  end if
    1484              : 
    1485              : #else
    1486            0 :  ABI_ERROR("FFTW3 support not activated")
    1487              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,isign/))
    1488              :  ABI_UNUSED(ff)
    1489              :  if (PRESENT(fftw_flags)) then
    1490              :    ABI_UNUSED(fftw_flags)
    1491              :  end if
    1492              : #endif
    1493              : 
    1494            0 : end subroutine fftw3_c2c_ip_spc
    1495              : !!***
    1496              : 
    1497              : !----------------------------------------------------------------------
    1498              : 
    1499              : !!****f* m_fftw3/fftw3_fftpad_spc
    1500              : !! NAME
    1501              : !!  fftw3_fftpad_spc
    1502              : !!
    1503              : !! FUNCTION
    1504              : !!  This routine transforms wavefunctions using 3D zero-padded FFTs with FFTW3.
    1505              : !!  The 3D ffts are computed only on lines and planes which have non zero elements.
    1506              : !!  These lines and planes are defined by the two vectors do_fft_x(ldy*nz) and do_fft_y(nz)
    1507              : !!  FFT transform is in-place. Target: complex arrays.
    1508              : !!
    1509              : !! INPUTS
    1510              : !!   nx,ny,nz=Logical dimensions of the FFT mesh.
    1511              : !!   ldx,ldy,ldz=Physical dimension of the f array (to avoid cache conflicts).
    1512              : !!   ndat=Number of FFT transforms.
    1513              : !!   mgfft=MAX(nx,ny,nz), only used to dimension gbound.
    1514              : !!   isign=The sign of the transform.
    1515              : !!   gbound(2*mgfft+8,2)= The boundaries of the basis sphere of G vectors at a given k-point.
    1516              : !!     See sphereboundary for more info.
    1517              : !!
    1518              : !! SIDE EFFECTS
    1519              : !!  ff(ldx*ldy*ldz*ndat)=
    1520              : !!    input: The array with the data to be transformed.
    1521              : !!    output: The results of the FFT.
    1522              : !!
    1523              : !! SOURCE
    1524              : 
    1525            0 : subroutine fftw3_fftpad_spc(ff, nx, ny, nz, ldx, ldy, ldz, ndat, mgfft, isign, gbound, iscale)
    1526              : 
    1527              : !Arguments ------------------------------------
    1528              : !scalars
    1529              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign
    1530              : !arrays
    1531              :  integer,intent(in) :: gbound(2*mgfft+8,2)
    1532              :  complex(sp),intent(inout) :: ff(ldx*ldy*ldz*ndat)
    1533              :  integer,optional,intent(in) :: iscale
    1534              : 
    1535              : #ifdef HAVE_FFTW3
    1536              : !Local variables-------------------------------
    1537              :  integer,parameter :: dst=1
    1538              :  integer :: iscale__
    1539              :  real(sp) :: fact
    1540              : ! *************************************************************************
    1541              : 
    1542              :  iscale__ = merge(1, 0, isign == -1); if (present(iscale)) iscale__ = iscale
    1543              : 
    1544              : #include "fftw3_fftpad.finc"
    1545              : 
    1546              : #else
    1547            0 :  ABI_ERROR("FFTW3 support not activated")
    1548              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign/))
    1549              :  ABI_UNUSED(gbound(1,1))
    1550              :  ABI_UNUSED(ff(1))
    1551              : #endif
    1552              : 
    1553            0 : end subroutine fftw3_fftpad_spc
    1554              : !!***
    1555              : 
    1556              : !----------------------------------------------------------------------
    1557              : 
    1558              : !!****f* m_fftw3/fftw3_c2c_ip_dpc
    1559              : !! NAME
    1560              : !!  fftw3_c2c_ip_dpc
    1561              : !!
    1562              : !! FUNCTION
    1563              : !! Driver routine for in-place 3D complex-complex FFT.
    1564              : !!
    1565              : !! INPUTS
    1566              : !! nx,ny,nz=Number of points along the three directions.
    1567              : !! ldx,ldy,ldz=Physical dimensions of the array.
    1568              : !! ndat=Number of FFTs to be done.
    1569              : !! iscale=0 if G --> R FFT should not be scaled.
    1570              : !! isign= +1 : ff(G) => ff(R); -1 : ff(R) => ff(G)
    1571              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    1572              : !!   Defaults to ABI_FFTW_ESTIMATE.
    1573              : !!
    1574              : !! SIDE EFFECTS
    1575              : !!  ff(ldx*ldy*ldz*ndat)=
    1576              : !!    In input: the complex array to be transformed.
    1577              : !!    In output: the Fourier transformed in the space specified by isign.
    1578              : !!
    1579              : !! SOURCE
    1580              : 
    1581            0 : subroutine fftw3_c2c_ip_dpc(nx, ny, nz, ldx, ldy, ldz, ndat, iscale, isign, ff, fftw_flags)
    1582              : 
    1583              : !Arguments ------------------------------------
    1584              : !scalars
    1585              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,iscale,isign
    1586              :  integer,optional,intent(in) :: fftw_flags
    1587              : !arrays
    1588              :  complex(dp),intent(inout) :: ff(ldx*ldy*ldz*ndat)
    1589              : 
    1590              : #ifdef HAVE_FFTW3
    1591              : !Local variables-------------------------------
    1592              : !scalars
    1593              :  integer,parameter :: rank3=3,nt_all=-1
    1594              :  integer :: my_flags,dist,stride
    1595              :  integer(KIND_FFTW_PLAN) :: my_plan
    1596              : !arrays
    1597              :  integer :: embed(rank3),n(rank3)
    1598              : ! *************************************************************************
    1599              : 
    1600              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags=fftw_flags
    1601              : 
    1602              :  stride = 1
    1603              :  dist   = ldx*ldy*ldz
    1604              :  embed  = [ldx, ldy, ldz]
    1605              :  n      = [nx, ny, nz]
    1606              : 
    1607              :  my_plan = fftw3_plan_many_dft(rank3, n, ndat, ff, embed, stride, dist, ff, embed, stride, dist, isign, my_flags, nt_all)
    1608              : 
    1609              :  ! Now perform the 3D FFT via FFTW.
    1610              :  call dfftw_execute_dft(my_plan, ff, ff)
    1611              : 
    1612              :  call fftw3_destroy_plan(my_plan)
    1613              : 
    1614              :  ! -1, FFTW returns not normalized FTs
    1615              :  if (isign == ABI_FFTW_FORWARD .and. iscale /= 0) then
    1616              :    call ZDSCAL(ldx*ldy*ldz*ndat, one/(nx*ny*nz), ff, 1)
    1617              :  end if
    1618              : 
    1619              : #else
    1620            0 :  ABI_ERROR("FFTW3 support not activated")
    1621              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,isign/))
    1622              :  ABI_UNUSED(ff)
    1623              :  if (PRESENT(fftw_flags)) then
    1624              :    ABI_UNUSED(fftw_flags)
    1625              :  end if
    1626              : #endif
    1627              : 
    1628            0 : end subroutine fftw3_c2c_ip_dpc
    1629              : !!***
    1630              : 
    1631              : !----------------------------------------------------------------------
    1632              : 
    1633              : !!****f* m_fftw3/fftw3_c2c_op_spc
    1634              : !! NAME
    1635              : !!  fftw3_c2c_op_spc
    1636              : !!
    1637              : !! FUNCTION
    1638              : !! Driver routine for out-of-place 3D complex-complex FFT of lengths nx, ny, nz.
    1639              : !! TARGET: single precision complex arrays
    1640              : !!
    1641              : !! INPUTS
    1642              : !! nx,ny,nz=Number of points along the three directions.
    1643              : !! ldx,ldy,ldz=Physical dimensions of the array.
    1644              : !! ndat=Number of FFTs to be done.
    1645              : !! iscale=0 if G --> R FFT should not be scaled.
    1646              : !! isign= +1 : ff(G) => gg(R); -1 : ff(R) => gg(G)
    1647              : !! ff(ldx*ldy*ldz*ndat)=The array to be transformed.
    1648              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    1649              : !!   Defaults to ABI_FFTW_ESTIMATE.
    1650              : !!
    1651              : !! OUTPUT
    1652              : !! gg(ldx*ldy*ldz*ndat)=The FFT of ff.
    1653              : !!
    1654              : !! SOURCE
    1655              : 
    1656            0 : subroutine fftw3_c2c_op_spc(nx, ny, nz, ldx, ldy, ldz, ndat, iscale, isign, ff, gg, fftw_flags)
    1657              : 
    1658              : !Arguments ------------------------------------
    1659              : !scalars
    1660              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,iscale,isign,ndat
    1661              :  integer,optional,intent(in) :: fftw_flags
    1662              : !arrays
    1663              :  complex(sp),intent(in) :: ff(ldx*ldy*ldz*ndat)
    1664              :  complex(sp),intent(out) :: gg(ldx*ldy*ldz*ndat)
    1665              : 
    1666              : #ifdef HAVE_FFTW3
    1667              : !Local variables-------------------------------
    1668              : !scalars
    1669              :  integer,parameter :: rank3=3,nt_all=-1
    1670              :  integer :: my_flags,dist,stride
    1671              :  integer(KIND_FFTW_PLAN) :: my_plan
    1672              : !arrays
    1673              :  integer :: embed(rank3),n(rank3)
    1674              : ! *************************************************************************
    1675              : 
    1676              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    1677              : 
    1678              :  stride = 1
    1679              :  dist   = ldx*ldy*ldz
    1680              :  embed  = [ldx, ldy, ldz]
    1681              :  n      = [nx, ny, nz]
    1682              : 
    1683              :  my_plan = fftw3_plan_many_dft(rank3, n, ndat, ff, embed, stride, dist, gg, embed, stride, dist, isign, my_flags, nt_all)
    1684              : 
    1685              :  ! Now perform the 3D FFT via FFTW.
    1686              :  call sfftw_execute_dft(my_plan, ff, gg)
    1687              : 
    1688              :  call fftw3_destroy_plan(my_plan)
    1689              : 
    1690              :  if (isign == ABI_FFTW_FORWARD .and. iscale /= 0) then ! -1, FFTW returns not normalized FTs
    1691              :    call xscal(ldx*ldy*ldz*ndat, REAL(one/(nx*ny*nz), KIND=sp), gg, 1)
    1692              :  end if
    1693              : 
    1694              : #else
    1695            0 :  ABI_ERROR("FFTW3 support not activated")
    1696              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,isign/))
    1697              :  ABI_UNUSED(ff)
    1698              :  ABI_UNUSED(gg)
    1699              :  if (PRESENT(fftw_flags)) then
    1700              :    ABI_UNUSED(fftw_flags)
    1701              :  end if
    1702              : #endif
    1703              : 
    1704            0 : end subroutine fftw3_c2c_op_spc
    1705              : !!***
    1706              : 
    1707              : !----------------------------------------------------------------------
    1708              : 
    1709              : !!****f* m_fftw3/fftw3_c2c_op_dpc
    1710              : !! NAME
    1711              : !!  fftw3_c2c_op_dpc
    1712              : !!
    1713              : !! FUNCTION
    1714              : !! Driver routine for out-of-place 3D complex-complex FFT of lengths nx, ny, nz.
    1715              : !! TARGET: single precision complex arrays
    1716              : !!
    1717              : !! INPUTS
    1718              : !! nx,ny,nz=Number of points along the three directions.
    1719              : !! ldx,ldy,ldz=Physical dimensions of the array.
    1720              : !! ndat=Number of FFTs to be done.
    1721              : !! iscale=0 if G --> R FFT should not be scaled.
    1722              : !! isign= +1 : ff(G) => gg(R); -1 : ff(R) => gg(G)
    1723              : !! ff(ldx*ldy*ldz*ndat)=The array to be transformed.
    1724              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    1725              : !!   Defaults to ABI_FFTW_ESTIMATE.
    1726              : !!
    1727              : !! OUTPUT
    1728              : !! gg(ldx*ldy*ldz*ndat)=The FFT of ff.
    1729              : !!
    1730              : !! SOURCE
    1731              : 
    1732            0 : subroutine fftw3_c2c_op_dpc(nx, ny, nz, ldx, ldy, ldz, ndat, iscale, isign, ff, gg, fftw_flags)
    1733              : 
    1734              : !Arguments ------------------------------------
    1735              : !scalars
    1736              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,isign,ndat,iscale
    1737              :  integer,optional,intent(in) :: fftw_flags
    1738              : !arrays
    1739              :  complex(dp),intent(in) :: ff(ldx*ldy*ldz*ndat)
    1740              :  complex(dp),intent(out) :: gg(ldx*ldy*ldz*ndat)
    1741              : 
    1742              : #ifdef HAVE_FFTW3
    1743              : !Local variables-------------------------------
    1744              : !scalars
    1745              :  integer,parameter :: rank3=3,nt_all=-1
    1746              :  integer :: my_flags,dist,stride
    1747              :  integer(KIND_FFTW_PLAN) :: my_plan
    1748              : !arrays
    1749              :  integer :: embed(rank3),n(rank3)
    1750              : ! *************************************************************************
    1751              : 
    1752              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    1753              : 
    1754              :  stride = 1
    1755              :  dist   = ldx*ldy*ldz
    1756              :  embed  = [ldx, ldy, ldz]
    1757              :  n      = [nx, ny, nz]
    1758              : 
    1759              :  my_plan = fftw3_plan_many_dft(rank3, n, ndat, ff, embed, stride, dist, gg, embed, stride, dist, isign, my_flags, nt_all)
    1760              : 
    1761              :  ! Now perform the 3D FFT via FFTW.
    1762              :  call dfftw_execute_dft(my_plan, ff, gg)
    1763              : 
    1764              :  call fftw3_destroy_plan(my_plan)
    1765              : 
    1766              :  if (isign == ABI_FFTW_FORWARD .and. iscale /= 0) then ! -1, FFTW returns not normalized FTs
    1767              :    call xscal(ldx*ldy*ldz*ndat, one/(nx*ny*nz), gg, 1)
    1768              :  end if
    1769              : 
    1770              : #else
    1771            0 :  ABI_ERROR("FFTW3 support not activated")
    1772              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,isign/))
    1773              :  ABI_UNUSED(ff)
    1774              :  ABI_UNUSED(gg)
    1775              :  if (PRESENT(fftw_flags)) then
    1776              :    ABI_UNUSED(fftw_flags)
    1777              :  end if
    1778              : #endif
    1779              : 
    1780            0 : end subroutine fftw3_c2c_op_dpc
    1781              : !!***
    1782              : 
    1783              : !----------------------------------------------------------------------
    1784              : 
    1785              : !!****f* m_fftw3/fftw3_r2c_op
    1786              : !! NAME
    1787              : !!  fftw3_r2c_op
    1788              : !!
    1789              : !! FUNCTION
    1790              : !! Driver routine for out-of-place 3D real-to-complex FFT of lengths nx, ny, nz.
    1791              : !!
    1792              : !! INPUTS
    1793              : !! nx,ny,nz=Number of points along the three directions.
    1794              : !! ldx,ldy,ldz=Physical dimensions of the f array (to avoid cache conflicts).
    1795              : !! ff(ldx*ldy*ldz*ndat)=The real array to be transformed.
    1796              : !! ndat=Number of FFTs to be done.
    1797              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    1798              : !!   Defaults to ABI_FFTW_ESTIMATE.
    1799              : !!
    1800              : !! OUTPUT
    1801              : !! gg(2,nx*ny*nz*ndat)=The forward FFT of ff.
    1802              : !!
    1803              : !! NOTES
    1804              : !!  FIXME For the time-being. No augmentation of the mesh to reduce memory conflicts, as MKL crashes
    1805              : !!  if the advanced interface is used.
    1806              : !!
    1807              : !! SOURCE
    1808              : 
    1809            0 : subroutine fftw3_r2c_op(nx,ny,nz,ldx,ldy,ldz,ndat,ff,gg,fftw_flags)
    1810              : 
    1811              : !Arguments ------------------------------------
    1812              : !scalars
    1813              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat
    1814              :  integer,optional,intent(in) :: fftw_flags
    1815              : !arrays
    1816              :  real(dp),intent(in) :: ff(ldx*ldy*ldz*ndat)
    1817              :  real(dp),intent(out) :: gg(2,ldx*ldy*ldz*ndat)
    1818              : 
    1819              : #ifdef HAVE_FFTW3
    1820              : !Local variables-------------------------------
    1821              : !scalars
    1822              :  integer,parameter :: rank3=3,nt_all=-1
    1823              :  integer :: nhp,my_flags,idist,odist,padx,i1,i2,i3,igp,igf,imgf,stride
    1824              :  integer :: i1inv,i2inv,i3inv,idat,padatf
    1825              :  integer(KIND_FFTW_PLAN) :: my_plan
    1826              : !arrays
    1827              :  integer :: inembed(rank3),onembed(rank3),n(rank3)
    1828              :  integer,allocatable :: i1inver(:),i2inver(:),i3inver(:)
    1829              :  real(dp),allocatable :: gg_hp(:,:)
    1830              : ! *************************************************************************
    1831              : 
    1832              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    1833              : 
    1834              :  idist = ldx*ldy*ldz
    1835              :  nhp = (nx/2+1)*ny*nz
    1836              :  odist = nhp
    1837              : 
    1838              :  stride = 1
    1839              :  n      = (/nx,ny,nz/)
    1840              :  inembed= (/ldx,ldy,ldz/)
    1841              :  onembed= (/(nx/2+1),ny,nz/)
    1842              : 
    1843              :  ABI_MALLOC(gg_hp,(2,nhp*ndat))
    1844              : 
    1845              : #ifdef DEV_RC_BUG
    1846              :  if (ndat/=1) ABI_ERROR("ndat/=1 + MKL not coded")
    1847              : 
    1848              :  if (ANY( n /= inembed )) then
    1849              :    ABI_ERROR("Augmentation not supported")
    1850              :  end if
    1851              : 
    1852              :  call dfftw_plan_dft_r2c_3d(my_plan, nx, ny, nz, ff, gg_hp, my_flags)
    1853              :  if (my_plan==NULL_PLAN) then
    1854              :    ABI_ERROR("dfftw_plan_dft_r2c_3d returned NULL_PLAN")
    1855              :  end if
    1856              : 
    1857              :  !fftw_plan fftw_plan_many_dft_r2c(int rank3, const int *n, int howmany,
    1858              :  !  double *in, const int *inembed, int istride, int idist,
    1859              :  !  fftw_complex *out, const int *onembed, int ostride, int odist, unsigned flags);
    1860              : #else
    1861              :  my_plan = dplan_many_dft_r2c(rank3, n, ndat, ff, inembed, stride, idist, gg_hp, onembed, stride, odist, my_flags, nt_all)
    1862              : #endif
    1863              : 
    1864              :  ! Now perform the 3D FFT via FFTW. r2c are always ABI_FFTW_FORWARD
    1865              :  call dfftw_execute_dft_r2c(my_plan, ff, gg_hp)
    1866              : 
    1867              :  call fftw3_destroy_plan(my_plan)
    1868              : 
    1869              :  ! FFTW returns not normalized FTs
    1870              :  call ZDSCAL(nhp*ndat, one/(nx*ny*nz), gg_hp, 1)
    1871              : 
    1872              :  ! Reconstruct full FFT: Hermitian redundancy: out[i] is the conjugate of out[n-i]
    1873              :  padx = (nx/2+1)
    1874              :  ABI_MALLOC(i1inver,(padx))
    1875              :  ABI_MALLOC(i2inver,(ny))
    1876              :  ABI_MALLOC(i3inver,(nz))
    1877              : 
    1878              :  i1inver(1)=1
    1879              :  do i1=2,padx
    1880              :    i1inver(i1)=nx+2-i1
    1881              :  end do
    1882              : 
    1883              :  i2inver(1)=1
    1884              :  do i2=2,ny
    1885              :    i2inver(i2)=ny+2-i2
    1886              :  end do
    1887              : 
    1888              :  i3inver(1)=1
    1889              :  do i3=2,nz
    1890              :    i3inver(i3)=nz+2-i3
    1891              :  end do
    1892              : 
    1893              :  igp=0
    1894              :  do idat=1,ndat
    1895              :    padatf = (idat-1)*ldx*ldy*ldz
    1896              :    do i3=1,nz
    1897              :      i3inv = i3inver(i3)
    1898              :      do i2=1,ny
    1899              :        i2inv = i2inver(i2)
    1900              :        do i1=1,padx
    1901              :          igp = igp+1
    1902              :          igf = i1 + (i3-1)*ldx*ldy + (i2-1)*ldx + padatf
    1903              :          gg(:,igf) =  gg_hp(:,igp)
    1904              :          i1inv = i1inver(i1)
    1905              :          if (i1inv/=i1) then
    1906              :            imgf = i1inv + (i3inv-1)*ldx*ldy + (i2inv-1)*ldx + padatf
    1907              :            gg(1,imgf) =  gg_hp(1,igp)
    1908              :            gg(2,imgf) = -gg_hp(2,igp)
    1909              :          end if
    1910              :        end do
    1911              :      end do
    1912              :    end do
    1913              :  end do
    1914              : 
    1915              :  ABI_FREE(i1inver)
    1916              :  ABI_FREE(i2inver)
    1917              :  ABI_FREE(i3inver)
    1918              :  ABI_FREE(gg_hp)
    1919              : 
    1920              : #else
    1921            0 :  ABI_ERROR("FFTW3 support not activated")
    1922              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz/))
    1923              :  ABI_UNUSED(ff)
    1924              :  ABI_UNUSED(gg(1,1))
    1925              :  if (PRESENT(fftw_flags)) then
    1926              :    ABI_UNUSED(fftw_flags)
    1927              :  end if
    1928              : #endif
    1929              : 
    1930            0 : end subroutine fftw3_r2c_op
    1931              : !!***
    1932              : 
    1933              : !----------------------------------------------------------------------
    1934              : 
    1935              : !!****f* m_fftw3/fftw3_c2r_op
    1936              : !! NAME
    1937              : !!  fftw3_c2r_op
    1938              : !!
    1939              : !! FUNCTION
    1940              : !! Driver routine for out-of-place 3D complex-to-real FFT of lengths nx, ny, nz.
    1941              : !!
    1942              : !! INPUTS
    1943              : !! nx,ny,nz=Number of point along the three directions.
    1944              : !! ldx,ldy,ldz=Physical dimension of the f array (to avoid cache conflicts).
    1945              : !! ndat=Number of FFTs to be done.
    1946              : !! ff(2*ldx*ldy*ldz*ndat)=The complex array to be transformed.
    1947              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    1948              : !!   Defaults to ABI_FFTW_ESTIMATE.
    1949              : !!
    1950              : !! OUTPUT
    1951              : !! gg(ldx*ldy*ldz*ndat)=The backwards real FFT of ff.
    1952              : !!
    1953              : !! NOTES
    1954              : !!  FIXME For the time-being. No augmentation of the mesh to reduce memory conflicts, as MKL crashes
    1955              : !!  if the advanced interface is used.
    1956              : !!
    1957              : !! SOURCE
    1958              : 
    1959            0 : subroutine fftw3_c2r_op(nx,ny,nz,ldx,ldy,ldz,ndat,ff,gg,fftw_flags)
    1960              : 
    1961              : !Arguments ------------------------------------
    1962              : !scalars
    1963              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat
    1964              :  integer,optional,intent(in) :: fftw_flags
    1965              : !arrays
    1966              :  real(dp),intent(in) :: ff(2,ldx*ldy*ldz*ndat)
    1967              :  real(dp),intent(out) :: gg(ldx*ldy*ldz*ndat)
    1968              : 
    1969              : #ifdef HAVE_FFTW3
    1970              : !Local variables-------------------------------
    1971              : !scalars
    1972              :  integer,parameter :: rank3=3,nt_all=-1
    1973              :  integer :: nhp,my_flags,padx,i2,i3,igp,igf,idat,padatf,padatp,idist,odist,stride
    1974              :  integer(KIND_FFTW_PLAN) :: my_plan
    1975              : !arrays
    1976              :  integer :: inembed(rank3),onembed(rank3),n(rank3)
    1977              :  real(dp),allocatable :: ff_hp(:,:)
    1978              : ! *************************************************************************
    1979              : 
    1980              : #ifdef DEV_RC_BUG
    1981              :  if (ANY( (/nx,ny,nz/) /= (/ldx,ldy,ldz/) )) then
    1982              :    ABI_ERROR("Augmentation not supported")
    1983              :  end if
    1984              : #endif
    1985              : 
    1986              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    1987              : 
    1988              :  stride  = 1
    1989              :  nhp     = (nx/2+1)*ny*nz
    1990              :  idist   = nhp
    1991              :  odist   = ldx*ldy*ldz
    1992              :  n       = (/nx,ny,nz/)
    1993              :  inembed = (/(nx/2+1),ny,nz/)
    1994              :  onembed = (/ldx,ldy,ldz/)
    1995              : 
    1996              :  ! Fill the Hermitian part: Hermitian redundancy: out[i] is the conjugate of out[n-i]
    1997              :  ABI_MALLOC(ff_hp,(2,nhp*ndat))
    1998              : 
    1999              :  padx = (nx/2+1)
    2000              :  do idat=1,ndat
    2001              :    padatf=(idat-1)*ldx*ldy*ldz
    2002              :    padatp=(idat-1)*padx*ny*nz
    2003              :    !$OMP PARALLEL DO PRIVATE(igf,igp)
    2004              :    do i3=1,nz
    2005              :      do i2=1,ny
    2006              :        igf = (i3-1)*ldx*ldy + (i2-1)*ldx   + padatf
    2007              :        igp = (i3-1)*padx*ny + (i2-1)*padx  + padatp
    2008              :        ff_hp(:,igp+1:igp+padx) = ff(:,igf+1:igf+padx)
    2009              :      end do
    2010              :    end do
    2011              :  end do
    2012              : 
    2013              :  ! NOTE: The c2r transform destroys its input array even for out-of-place transforms.
    2014              : #ifdef DEV_RC_BUG
    2015              :  if (ndat/=1) ABI_ERROR("ndat/=1 + MKL not coded")
    2016              :  call dfftw_plan_dft_c2r_3d(my_plan, nx, ny, nz, ff_hp, gg, my_flags)
    2017              :  if (my_plan==NULL_PLAN) then
    2018              :    ABI_ERROR("dfftw_plan_dft_c2r_3d returned NULL_PLAN")
    2019              :  end if
    2020              : #else
    2021              :  my_plan = dplan_many_dft_c2r(rank3, n, ndat, ff_hp, inembed, stride, idist, gg, onembed, stride, odist, my_flags, nt_all)
    2022              : #endif
    2023              : 
    2024              :  ! Now perform the 3D FFT via FFTW. c2r are always ABI_FFTW_BACKWARD
    2025              :  call dfftw_execute_dft_c2r(my_plan, ff_hp, gg)
    2026              : 
    2027              :  call fftw3_destroy_plan(my_plan)
    2028              :  ABI_FREE(ff_hp)
    2029              : 
    2030              : #else
    2031            0 :  ABI_ERROR("FFTW3 support not activated")
    2032              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz/))
    2033              :  ABI_UNUSED(ff(1,1))
    2034              :  ABI_UNUSED(gg(1))
    2035              :  if (PRESENT(fftw_flags)) then
    2036              :    ABI_UNUSED(fftw_flags)
    2037              :  end if
    2038              : #endif
    2039              : 
    2040            0 : end subroutine fftw3_c2r_op
    2041              : !!***
    2042              : 
    2043              : !----------------------------------------------------------------------
    2044              : 
    2045              : !!****f* m_fftw3/fftw3_many_dft_op
    2046              : !! NAME
    2047              : !!  fftw3_many_dft_op
    2048              : !!
    2049              : !! FUNCTION
    2050              : !! Driver routine for many out-of-place 3D complex-to-complex FFTs of lengths nx, ny, nz.
    2051              : !!
    2052              : !! INPUTS
    2053              : !! nx,ny,nz=Number of points along the three directions.
    2054              : !! ldx,ldy,ldz=Physical dimension of the fin and fout arrays (to avoid cache conflicts).
    2055              : !! ndat=Number of FFTs to be done.
    2056              : !! fin(2*ldx*ldy*ldz*ndat)=The complex array to be transformed.
    2057              : !! isign=sign of Fourier transform exponent: current convention uses
    2058              : !!   +1 for transforming from G to r,
    2059              : !!   -1 for transforming from r to G.
    2060              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    2061              : !!   Defaults to ABI_FFTW_ESTIMATE.
    2062              : !!
    2063              : !! OUTPUT
    2064              : !! fout(2,ldx*ldy*ldz*ndat)=The Fourier transform of fin.
    2065              : !!
    2066              : !! SOURCE
    2067              : 
    2068            0 : subroutine fftw3_many_dft_op(nx,ny,nz,ldx,ldy,ldz,ndat,isign,fin,fout,fftw_flags)
    2069              : 
    2070              : !Arguments ------------------------------------
    2071              : !scalars
    2072              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,isign
    2073              :  integer,optional,intent(in) :: fftw_flags
    2074              : !arrays
    2075              :  real(dp),intent(in) :: fin(2*ldx*ldy*ldz*ndat)
    2076              :  real(dp),intent(out) :: fout(2*ldx*ldy*ldz*ndat)
    2077              : 
    2078              : #ifdef HAVE_FFTW3
    2079              : !Local variables-------------------------------
    2080              : !scalars
    2081              :  integer,parameter :: rank3=3,nt_all=-1
    2082              :  integer :: my_flags,dist,stride
    2083              :  integer(KIND_FFTW_PLAN) :: my_plan
    2084              : !arrays
    2085              :  integer :: embed(rank3),n(rank3)
    2086              : ! *************************************************************************
    2087              : 
    2088              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    2089              : 
    2090              :  stride = 1
    2091              :  dist   = ldx*ldy*ldz
    2092              :  embed  = [ldx, ldy, ldz]
    2093              :  n      = [nx, ny, nz]
    2094              : 
    2095              :  my_plan = fftw3_plan_many_dft(rank3, n, ndat, fin, embed, stride, dist, fout, embed, stride, dist, isign, my_flags, nt_all)
    2096              : 
    2097              :  ! Now perform the 3D FFT via FFTW.
    2098              :  call dfftw_execute_dft(my_plan, fin, fout)
    2099              : 
    2100              :  call fftw3_destroy_plan(my_plan)
    2101              : 
    2102              :  ! -1, FFTW returns not normalized FTs
    2103              :  if (isign == ABI_FFTW_FORWARD) then
    2104              :   call ZDSCAL(ldx*ldy*ldz*ndat, one/(nx*ny*nz), fout, 1)
    2105              :  end if
    2106              : 
    2107              : #else
    2108            0 :  ABI_ERROR("FFTW3 support not activated")
    2109              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,ndat,isign/))
    2110              :  if (PRESENT(fftw_flags)) then
    2111              :    ABI_UNUSED(fftw_flags)
    2112              :  end if
    2113              :  ABI_UNUSED(fin(1))
    2114              :  ABI_UNUSED(fout(1))
    2115              : #endif
    2116              : 
    2117            0 : end subroutine fftw3_many_dft_op
    2118              : !!***
    2119              : 
    2120              : !----------------------------------------------------------------------
    2121              : 
    2122              : !!****f* m_fftw3/fftw3_many_dft_ip
    2123              : !! NAME
    2124              : !!  fftw3_many_dft_ip
    2125              : !!
    2126              : !! FUNCTION
    2127              : !! Driver routine for many in-place 3D complex-to-complex FFTs of lengths nx, ny, nz.
    2128              : !!
    2129              : !! INPUTS
    2130              : !! nx,ny,nz=Number of points along the three directions.
    2131              : !! ldx,ldy,ldz=Physical dimension of the finout array (to avoid cache conflicts).
    2132              : !! ndat=Number of FFTs to be done.
    2133              : !! isign=sign of Fourier transform exponent: current convention uses
    2134              : !!   +1 for transforming from G to r,
    2135              : !!   -1 for transforming from r to G.
    2136              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    2137              : !!   Defaults to ABI_FFTW_ESTIMATE.
    2138              : !!
    2139              : !! OUTPUT
    2140              : !! finout(2,ldx*ldy*ldz*ndat)=
    2141              : !!   In input: The complex array to be transformed.
    2142              : !!   In output: The FFT results.
    2143              : !!
    2144              : !! SOURCE
    2145              : 
    2146            0 : subroutine fftw3_many_dft_ip(nx,ny,nz,ldx,ldy,ldz,ndat,isign,finout,fftw_flags)
    2147              : 
    2148              : !Arguments ------------------------------------
    2149              : !scalars
    2150              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,isign
    2151              :  integer,optional,intent(in) :: fftw_flags
    2152              : !arrays
    2153              :  real(dp),intent(inout) :: finout(2*ldx*ldy*ldz*ndat)
    2154              : 
    2155              : #ifdef HAVE_FFTW3
    2156              : !Local variables-------------------------------
    2157              : !scalars
    2158              :  integer,parameter :: rank3=3,nt_all=-1
    2159              :  integer :: my_flags,dist,stride
    2160              :  integer(KIND_FFTW_PLAN) :: my_plan
    2161              : !arrays
    2162              :  integer :: embed(rank3),n(rank3)
    2163              : ! *************************************************************************
    2164              : 
    2165              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    2166              : 
    2167              :  stride = 1
    2168              :  dist   = ldx*ldy*ldz
    2169              :  embed  = [ldx, ldy, ldz]
    2170              :  n      = [nx, ny, nz]
    2171              : 
    2172              :  my_plan = fftw3_plan_many_dft(rank3, n, ndat, finout, embed, stride, dist, finout, embed, stride, dist, isign, my_flags, nt_all)
    2173              : 
    2174              :  ! Now perform the 3D FFT via FFTW.
    2175              :  call dfftw_execute_dft(my_plan, finout, finout)
    2176              :  call fftw3_destroy_plan(my_plan)
    2177              : 
    2178              :  ! -1, FFTW returns not normalized FTs
    2179              :  if (isign == ABI_FFTW_FORWARD) then
    2180              :   call ZDSCAL(ldx*ldy*ldz*ndat, one/(nx*ny*nz), finout, 1)
    2181              :  end if
    2182              : 
    2183              : #else
    2184            0 :  ABI_ERROR("FFTW3 support not activated")
    2185              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,ndat,isign/))
    2186              :  if (PRESENT(fftw_flags)) then
    2187              :    ABI_UNUSED(fftw_flags)
    2188              :  end if
    2189              :  ABI_UNUSED(finout(1))
    2190              : #endif
    2191              : 
    2192            0 : end subroutine fftw3_many_dft_ip
    2193              : !!***
    2194              : 
    2195              : !----------------------------------------------------------------------
    2196              : 
    2197              : !!****f* m_fftw3/fftw3_cleanup
    2198              : !! NAME
    2199              : !!  fftw3_cleanup
    2200              : !!
    2201              : !! FUNCTION
    2202              : !!  Reset FFTW to the pristine state it was in when you started your program,
    2203              : !!  All existing plans become undefined.
    2204              : !!
    2205              : !! NOTES
    2206              : !!  FFTW planner saves some other persistent data, such as the accumulated wisdom and a list of
    2207              : !!  algorithms available in the current configuration. If you want to deallocate all of that and reset
    2208              : !!  FFTW to the pristine state it was in when you started your program, you can call fftw3_cleanup();
    2209              : !!  After calling fftw3_cleanup, all existing plans become undefined, and you should not attempt to
    2210              : !!  execute them nor to destroy them. You can however create and execute/destroy new plans, in which case
    2211              : !!  FFTW starts accumulating wisdom information again.
    2212              : !!  fftw3_cleanup does not deallocate your plans, however. To prevent memory leaks, you must still call
    2213              : !!  fftw_destroy_plan before executing fftw3_cleanup
    2214              : !!
    2215              : !! SOURCE
    2216              : 
    2217            0 : subroutine fftw3_cleanup()
    2218              : 
    2219              : #ifdef HAVE_FFTW3_MPI
    2220              :  call fftw_mpi_cleanup()
    2221              : #endif
    2222              : #ifdef HAVE_FFTW3_THREADS
    2223              :  if (THREADS_INITED==1) then
    2224              :    call dfftw_cleanup_threads()
    2225              :    THREADS_INITED = 0
    2226              :  end if
    2227              : #elif defined HAVE_FFTW3
    2228              :  call dfftw_cleanup()
    2229              : #else
    2230            0 :  ABI_ERROR("FFTW3 support not activated")
    2231              : #endif
    2232              : 
    2233            0 : end subroutine fftw3_cleanup
    2234              : !!***
    2235              : 
    2236              : !----------------------------------------------------------------------
    2237              : 
    2238              : !!****f* m_fftw3/fftw3_destroy_plan
    2239              : !! NAME
    2240              : !!  fftw3_destroy_plan
    2241              : !!
    2242              : !! FUNCTION
    2243              : !!  Release the memory allocate for the plan.
    2244              : !!
    2245              : !! INPUTS
    2246              : !!
    2247              : !! SOURCE
    2248              : 
    2249              : subroutine fftw3_destroy_plan(plan)
    2250              : 
    2251              : !Arguments ------------------------------------
    2252              : !scalars
    2253              :  integer(KIND_FFTW_PLAN),intent(in) :: plan
    2254              : ! *************************************************************************
    2255              : 
    2256              : #ifdef HAVE_FFTW3
    2257              : !$OMP CRITICAL (OMPC_fftw3_destroy_plan)
    2258              :  call dfftw_destroy_plan(plan)
    2259              : !$OMP END CRITICAL (OMPC_fftw3_destroy_plan)
    2260              : 
    2261              : #else
    2262              :  if (.FALSE.) write(std_out,*)plan
    2263              : #endif
    2264              : 
    2265              : end subroutine fftw3_destroy_plan
    2266              : !!***
    2267              : 
    2268              : !----------------------------------------------------------------------
    2269              : 
    2270              : !!****f* m_fftw3/fftw3_init_threads
    2271              : !! NAME
    2272              : !!  fftw3_init_threads
    2273              : !!
    2274              : !! FUNCTION
    2275              : !!  This function performs the one-time initialization required to use FFTW3 threads.
    2276              : !!  It does nothing if HAVE_FFT_FFTW3_THREADS is not defined.
    2277              : !!
    2278              : !! INPUTS
    2279              : !!
    2280              : !! SIDE EFFECTS
    2281              : !!  The one-time initialization required to use FFTW3 threads is performed when the routine
    2282              : !!  is called for the first time.
    2283              : !!
    2284              : !! SOURCE
    2285              : 
    2286            0 : subroutine fftw3_init_threads()
    2287              : 
    2288              : !Local variables ------------------------------
    2289              : !scalars
    2290              : #ifdef HAVE_FFTW3_THREADS
    2291              :  integer :: iret
    2292              : #endif
    2293              : ! *************************************************************************
    2294              : 
    2295              : #ifdef HAVE_FFTW3_THREADS
    2296              :  if (THREADS_INITED==0) then
    2297              :    !call wrtout(std_out,"Calling dfftw_init_threads()")
    2298              :    call dfftw_init_threads(iret)
    2299              : 
    2300              :    if (iret==0) then
    2301              :      ABI_WARNING(" dfftw_init_threads returned 0; threaded FFTW3 is not being used!")
    2302              :    else
    2303              :      THREADS_INITED=1
    2304              :    end if
    2305              :    call fftw3_set_nthreads()
    2306              :  end if
    2307              : 
    2308              : #ifndef HAVE_OPENMP
    2309              :   ABI_WARNING("Using FFTW3 with threads but HAVE_OPENMP is not defined!")
    2310              : #endif
    2311              : #endif
    2312              : 
    2313              : #ifdef HAVE_FFTW3_MPI
    2314              :   !call wrtout(std_out,"Calling fftw_mpi_init()")
    2315              :   call fftw_mpi_init()
    2316              : #endif
    2317              : 
    2318            0 : end subroutine fftw3_init_threads
    2319              : !!***
    2320              : 
    2321              : !----------------------------------------------------------------------
    2322              : 
    2323              : !!****f* m_fftw3/fftw3_set_nthreads
    2324              : !! NAME
    2325              : !!  fftw3_set_nthreads
    2326              : !!
    2327              : !! FUNCTION
    2328              : !!  This function sets the number of threads you want FFTW3 to use (or actually, the maximum number).
    2329              : !!  It also performs any one-time initialization required to use FFTW3 threads.
    2330              : !!  All plans subsequently created with any planner routine will use nthreads threads.
    2331              : !!  If you pass an nthreads argument of 1 (the default), threads are disabled for subsequent plans.
    2332              : !!  It does nothing if HAVE_FFT_FFTW3_THREADS is not defined.
    2333              : !!
    2334              : !! INPUTS
    2335              : !!  [nthreads]=The number of threads you want FFTW3 to use.  Default xomp_get_max_threads()
    2336              : !!
    2337              : !! SOURCE
    2338              : 
    2339            0 : subroutine fftw3_set_nthreads(nthreads)
    2340              : 
    2341              : !Arguments ------------------------------------
    2342              :  integer,optional,intent(in) :: nthreads
    2343              : 
    2344              : !Local variables ------------------------------
    2345              : !scalars
    2346              : #ifdef HAVE_FFTW3_THREADS
    2347              :  integer :: istat,nt
    2348              :  integer,parameter :: enough=1
    2349              :  integer,save :: nwarns=0
    2350              : #endif
    2351              : ! *************************************************************************
    2352              : 
    2353              : #ifdef HAVE_FFTW3_THREADS
    2354              :  if (THREADS_INITED==0) then
    2355              :    ABI_WARNING("Threads are not initialized")
    2356              :  end if
    2357              : 
    2358              :  if (PRESENT(nthreads)) then
    2359              :    if (nthreads<=0) then
    2360              :      nt = xomp_get_max_threads()
    2361              :    else
    2362              :      nt = nthreads
    2363              :    end if
    2364              :  else
    2365              :    nt = xomp_get_max_threads()
    2366              :  end if
    2367              : 
    2368              :  call dfftw_plan_with_nthreads(nt)
    2369              : 
    2370              : #ifndef HAVE_OPENMP
    2371              :   if (nwarns <= enough) then
    2372              :     nwarns = nwarns + 1
    2373              :     ABI_WARNING("Using FFTW3 with threads but HAVE_OPENMP is not defined!")
    2374              :   end if
    2375              : #endif
    2376              : 
    2377              : #else
    2378              :  if (PRESENT(nthreads)) then
    2379              :    ABI_UNUSED(nthreads)
    2380              :  end if
    2381              : #endif
    2382              : 
    2383            0 : end subroutine fftw3_set_nthreads
    2384              : !!***
    2385              : 
    2386              : !----------------------------------------------------------------------
    2387              : 
    2388              : !!****f* m_fftw3/fftw3_fftpad_dp
    2389              : !! NAME
    2390              : !!  fftw3_fftpad_dp
    2391              : !!
    2392              : !! FUNCTION
    2393              : !!  This routine transforms wavefunctions using 3D zero-padded FFTs with FFTW3.
    2394              : !!  The 3D ffts are computed only on lines and planes which have non zero elements.
    2395              : !!  These lines and planes are defined by the two vectors do_fft_x(ldy*nz) and do_fft_y(nz)
    2396              : !!  FFT transform is in-place.
    2397              : !!
    2398              : !! INPUTS
    2399              : !!   nx,ny,nz=Logical dimensions of the FFT mesh.
    2400              : !!   ldx,ldy,ldz=Physical dimension of the f array (to avoid cache conflicts).
    2401              : !!   ndat=Number of FFT transforms.
    2402              : !!   mgfft=MAX(nx,ny,nz), only used to dimension gbound
    2403              : !!   isign=The sign of the transform.
    2404              : !!   gbound(2*mgfft+8,2)= The boundaries of the basis sphere of G vectors at a given k-point.
    2405              : !!     See sphereboundary for more info.
    2406              : !!
    2407              : !! SIDE EFFECTS
    2408              : !!   ff(2*ldx*ldy*ldz*ndat)=
    2409              : !!     input: The array with the data to be transformed.
    2410              : !!     output: The results of the FFT.
    2411              : !!
    2412              : !! SOURCE
    2413              : 
    2414            0 : subroutine fftw3_fftpad_dp(ff, nx, ny, nz, ldx, ldy, ldz, ndat, mgfft, isign, gbound, iscale)
    2415              : 
    2416              : !Arguments ------------------------------------
    2417              : !scalars
    2418              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign
    2419              : !arrays
    2420              :  integer,intent(in) :: gbound(2*mgfft+8,2)
    2421              :  real(dp),intent(inout) :: ff(2*ldx*ldy*ldz*ndat)
    2422              :  integer,optional,intent(in) :: iscale
    2423              : 
    2424              : !Local variables-------------------------------
    2425              : !scalars
    2426              : #ifdef HAVE_FFTW3
    2427              :  integer,parameter :: dst=2
    2428              :  integer :: iscale__
    2429              :  real(dp) :: fact
    2430              : ! *************************************************************************
    2431              : 
    2432              :  iscale__ = merge(1, 0, isign == -1); if (present(iscale)) iscale__ = iscale
    2433              : 
    2434              : #include "fftw3_fftpad.finc"
    2435              : 
    2436              : #else
    2437            0 :  ABI_ERROR("FFTW3 support not activated")
    2438              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,mgfft,isign/))
    2439              :  ABI_UNUSED(gbound(1,1))
    2440              :  ABI_UNUSED(ff(1))
    2441              : #endif
    2442              : 
    2443            0 : end subroutine fftw3_fftpad_dp
    2444              : !!***
    2445              : 
    2446              : !----------------------------------------------------------------------
    2447              : 
    2448              : !!****f* m_fftw3/fftw3_fftpad_dpc
    2449              : !! NAME
    2450              : !!  fftw3_fftpad_dpc
    2451              : !!
    2452              : !! FUNCTION
    2453              : !!  This routine transforms wavefunctions using 3D zero-padded FFTs with FFTW3.
    2454              : !!  The 3D ffts are computed only on lines and planes which have non zero elements.
    2455              : !!  These lines and planes are defined by the two vectors do_fft_x(ldy*nz) and do_fft_y(nz)
    2456              : !!  FFT transform is in-place. Target: complex arrays.
    2457              : !!
    2458              : !! INPUTS
    2459              : !!   nx,ny,nz=Logical dimensions of the FFT mesh.
    2460              : !!   ldx,ldy,ldz=Physical dimension of the f array (to avoid cache conflicts).
    2461              : !!   ndat=Number of FFT transforms.
    2462              : !!   mgfft=MAX(nx,ny,nz), only used to dimension gbound.
    2463              : !!   isign=The sign of the transform.
    2464              : !!   gbound(2*mgfft+8,2)= The boundaries of the basis sphere of G vectors at a given k-point.
    2465              : !!     See sphereboundary for more info.
    2466              : !!
    2467              : !! SIDE EFFECTS
    2468              : !!  ff(ldx*ldy*ldz*ndat)=
    2469              : !!    input: The array with the data to be transformed.
    2470              : !!    output: The results of the FFT.
    2471              : !!
    2472              : !! SOURCE
    2473              : 
    2474            0 : subroutine fftw3_fftpad_dpc(ff, nx, ny, nz, ldx, ldy, ldz, ndat, mgfft, isign, gbound, iscale)
    2475              : 
    2476              : !Arguments ------------------------------------
    2477              : !scalars
    2478              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign
    2479              :  integer,optional,intent(in) :: iscale
    2480              : !arrays
    2481              :  integer,intent(in) :: gbound(2*mgfft+8,2)
    2482              :  complex(dp),intent(inout) :: ff(ldx*ldy*ldz*ndat)
    2483              : 
    2484              : #ifdef HAVE_FFTW3
    2485              : !Local variables-------------------------------
    2486              :  integer,parameter :: dst=1
    2487              :  integer :: iscale__
    2488              :  real(dp) :: fact
    2489              : ! *************************************************************************
    2490              : 
    2491              :  iscale__ = merge(1, 0, isign == -1); if (present(iscale)) iscale__ = iscale
    2492              : 
    2493              : #include "fftw3_fftpad.finc"
    2494              : 
    2495              : #else
    2496            0 :  ABI_ERROR("FFTW3 support not activated")
    2497              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,ndat,mgfft,isign/))
    2498              :  ABI_UNUSED(gbound(1,1))
    2499              :  ABI_UNUSED(ff(1))
    2500              : #endif
    2501              : 
    2502            0 : end subroutine fftw3_fftpad_dpc
    2503              : !!***
    2504              : 
    2505              : #ifdef HAVE_FFTW3
    2506              : 
    2507              : !----------------------------------------------------------------------
    2508              : 
    2509              : !!****f* m_fftw3/dplan_many_dft_1D
    2510              : !! NAME
    2511              : !!
    2512              : !! FUNCTION
    2513              : !!
    2514              : !! INPUTS
    2515              : !!
    2516              : !! SIDE EFFECTS
    2517              : !!
    2518              : !! SOURCE
    2519              : 
    2520              : function dplan_many_dft_1D(rank,n,howmany,fin,inembed,istride,idist,fout,onembed,ostride,odist,sign,flags,nthreads) result(plan)
    2521              : 
    2522              : !Arguments ------------------------------------
    2523              : !scalars
    2524              :  integer,intent(in) :: rank,howmany,istride,ostride, sign,flags,idist,odist,nthreads
    2525              :  integer,intent(in) :: n(rank),inembed(rank),onembed(rank)
    2526              :  integer(KIND_FFTW_PLAN) :: plan
    2527              : !arrays
    2528              :  real(dp) :: fin(*),fout(*)
    2529              : 
    2530              : !Local variables-------------------------------
    2531              :  character(len=500) :: msg,frmt
    2532              : ! *************************************************************************
    2533              : 
    2534              :  !$OMP CRITICAL (OMPC_dfftw_plan_many_dft_1D)
    2535              :  call fftw3_set_nthreads(nthreads)
    2536              : 
    2537              :  call dfftw_plan_many_dft(plan, rank, n, howmany, &
    2538              :    fin, inembed, istride, idist, fout, onembed, ostride, odist, sign, flags)
    2539              :  !$OMP END CRITICAL (OMPC_dfftw_plan_many_dft_1D)
    2540              : 
    2541              :  if (plan==NULL_PLAN) then
    2542              :    call wrtout(std_out, "dfftw_plan_many_dft returned NULL_PLAN!")
    2543              :    write(frmt,*)"(a,",rank,"(1x,i0),3(a,i0),a,2(a,",rank,"(1x,i0),2(a,i0),a))"
    2544              :    write(msg,frmt)&
    2545              :     " n= ",n," howmany= ",howmany," sign= ",sign," flags= ",flags,ch10,&
    2546              :     " inembed= ",inembed," istride= ",istride," idist=",idist,ch10,    &
    2547              :     " onembed= ",onembed," ostride= ",ostride," odist=",idist,ch10
    2548              :    call wrtout(std_out, msg)
    2549              :    ABI_ERROR("Check FFTW library and/or abinit code")
    2550              :  end if
    2551              : 
    2552              : end function dplan_many_dft_1D
    2553              : !!***
    2554              : 
    2555              : !----------------------------------------------------------------------
    2556              : 
    2557              : !!****f* m_fftw3/dplan_many_dft_2D
    2558              : !! NAME
    2559              : !!
    2560              : !! FUNCTION
    2561              : !!
    2562              : !! INPUTS
    2563              : !!
    2564              : !! SOURCE
    2565              : 
    2566              : function dplan_many_dft_2D(rank,n,howmany,fin,inembed,istride,idist,fout,onembed,ostride,odist,sign,flags,nthreads) result(plan)
    2567              : 
    2568              : !Arguments ------------------------------------
    2569              : !scalars
    2570              :  integer,intent(in) :: rank,howmany,istride,ostride, sign,flags,idist,odist,nthreads
    2571              :  integer,intent(in) :: n(rank),inembed(rank),onembed(rank)
    2572              :  integer(KIND_FFTW_PLAN) :: plan
    2573              : !arrays
    2574              :  real(dp) :: fin(2,*),fout(2,*)
    2575              : 
    2576              : !Local variables-------------------------------
    2577              :  character(len=500) :: msg,frmt
    2578              : ! *************************************************************************
    2579              : 
    2580              :  !$OMP CRITICAL (OMPC_dfftw_plan_many_dft_2D)
    2581              :  call fftw3_set_nthreads(nthreads)
    2582              : 
    2583              :  call dfftw_plan_many_dft(plan, rank, n, howmany, &
    2584              :    fin, inembed, istride, idist, fout, onembed, ostride, odist, sign, flags)
    2585              :  !$OMP END CRITICAL (OMPC_dfftw_plan_many_dft_2D)
    2586              : 
    2587              :  if (plan==NULL_PLAN) then
    2588              :    call wrtout(std_out, "dfftw_plan_many_dft returned NULL_PLAN!")
    2589              :    write(frmt,*)"(a,",rank,"(1x,i0),3(a,i0),a,2(a,",rank,"(1x,i0),2(a,i0),a))"
    2590              :    write(msg,frmt)&
    2591              :      " n= ",n," howmany= ",howmany," sign= ",sign," flags= ",flags,ch10,&
    2592              :      " inembed= ",inembed," istride= ",istride," idist=",idist,ch10,    &
    2593              :      " onembed= ",onembed," ostride= ",ostride," odist=",idist,ch10
    2594              :    call wrtout(std_out, msg)
    2595              :    ABI_ERROR("Check FFTW library and/or abinit code")
    2596              :  end if
    2597              : 
    2598              : end function dplan_many_dft_2D
    2599              : !!***
    2600              : 
    2601              : !----------------------------------------------------------------------
    2602              : 
    2603              : !!****f* m_fftw3/cplan_many_dft
    2604              : !! NAME
    2605              : !!
    2606              : !! FUNCTION
    2607              : !!
    2608              : !! INPUTS
    2609              : !!
    2610              : !! SIDE EFFECTS
    2611              : !!
    2612              : !! SOURCE
    2613              : !! FIXME  technically it should be intent(inout) since FFTW3 can destroy the input for particular flags.
    2614              : 
    2615              : function cplan_many_dft(rank,n,howmany,fin,inembed,istride,idist,fout,onembed,ostride,odist,sign,flags,nthreads) result(plan)
    2616              : 
    2617              : !Arguments ------------------------------------
    2618              : !scalars
    2619              :  integer,intent(in) :: rank,howmany,istride,ostride, sign,flags,idist,odist,nthreads
    2620              :  integer,intent(in) :: n(rank),inembed(rank),onembed(rank)
    2621              :  integer(KIND_FFTW_PLAN) :: plan
    2622              : !arrays
    2623              :  complex(sp) :: fin(*),fout(*)
    2624              : 
    2625              : !Local variables-------------------------------
    2626              :  character(len=500) :: msg,frmt
    2627              : ! *************************************************************************
    2628              : 
    2629              :  !$OMP CRITICAL (OMPC_cplan_many_dft)
    2630              :  call fftw3_set_nthreads(nthreads)
    2631              : 
    2632              :  call sfftw_plan_many_dft(plan, rank, n, howmany, &
    2633              :    fin, inembed, istride, idist, fout, onembed, ostride, odist, sign, flags)
    2634              :  !$OMP END CRITICAL (OMPC_cplan_many_dft)
    2635              : 
    2636              :  if (plan==NULL_PLAN) then ! handle the error
    2637              :    call wrtout(std_out, "sfftw_plan_many_dft returned NULL_PLAN (complex version)")
    2638              :    write(frmt,*)"(a,",rank,"(1x,i0),3(a,i0),a,2(a,",rank,"(1x,i0),2(a,i0),a))"
    2639              :    write(msg,frmt)&
    2640              :      " n = ",n," howmany = ",howmany," sign = ",sign," flags = ",flags,ch10,&
    2641              :      " inembed = ",inembed," istride = ",istride," idist =",idist,ch10,     &
    2642              :      " onembed = ",onembed," ostride = ",ostride," odist =",idist,ch10
    2643              :    call wrtout(std_out, msg)
    2644              :    ABI_ERROR("Check FFTW library and/or abinit code")
    2645              :  end if
    2646              : 
    2647              : end function cplan_many_dft
    2648              : !!***
    2649              : 
    2650              : !----------------------------------------------------------------------
    2651              : 
    2652              : !!****f* m_fftw3/zplan_many_dft
    2653              : !! NAME
    2654              : !!
    2655              : !! FUNCTION
    2656              : !!
    2657              : !! INPUTS
    2658              : !!
    2659              : !! SIDE EFFECTS
    2660              : !!
    2661              : !! SOURCE
    2662              : !! FIXME  technically it should be intent(inout) since FFTW3 can destroy the input for particular flags.
    2663              : 
    2664              : function zplan_many_dft(rank,n,howmany,fin,inembed,istride,idist,fout,onembed,ostride,odist,sign,flags,nthreads) result(plan)
    2665              : 
    2666              : !Arguments ------------------------------------
    2667              : !scalars
    2668              :  integer,intent(in) :: rank,howmany,istride,ostride, sign,flags,idist,odist,nthreads
    2669              :  integer,intent(in) :: n(rank),inembed(rank),onembed(rank)
    2670              :  integer(KIND_FFTW_PLAN) :: plan
    2671              : !arrays
    2672              :  complex(dp) :: fin(*),fout(*)
    2673              : 
    2674              : !Local variables-------------------------------
    2675              :  character(len=500) :: msg,frmt
    2676              : ! *************************************************************************
    2677              : 
    2678              :  !$OMP CRITICAL (OMPC_zplan_many_dft)
    2679              :  call fftw3_set_nthreads(nthreads)
    2680              : 
    2681              :  call dfftw_plan_many_dft(plan, rank, n, howmany, &
    2682              :    fin, inembed, istride, idist, fout, onembed, ostride, odist, sign, flags)
    2683              :  !$OMP END CRITICAL (OMPC_zplan_many_dft)
    2684              : 
    2685              :  if (plan==NULL_PLAN) then ! handle the error
    2686              :    call wrtout(std_out, "dfftw_plan_many_dft returned NULL_PLAN (complex version)")
    2687              :    write(frmt,*)"(a,",rank,"(1x,i0),3(a,i0),a,2(a,",rank,"(1x,i0),2(a,i0),a))"
    2688              :    write(msg,frmt)&
    2689              :      " n = ",n," howmany = ",howmany," sign = ",sign," flags = ",flags,ch10,&
    2690              :      " inembed = ",inembed," istride = ",istride," idist =",idist,ch10,     &
    2691              :      " onembed = ",onembed," ostride = ",ostride," odist =",idist,ch10
    2692              :    call wrtout(std_out, msg)
    2693              :    ABI_ERROR("Check FFTW library and/or abinit code")
    2694              :  end if
    2695              : 
    2696              : end function zplan_many_dft
    2697              : !!***
    2698              : 
    2699              : !----------------------------------------------------------------------
    2700              : 
    2701              : !!****f* m_fftw3/dplan_many_dft_r2c
    2702              : !! NAME
    2703              : !!
    2704              : !! FUNCTION
    2705              : !!
    2706              : !! INPUTS
    2707              : !!
    2708              : !! SIDE EFFECTS
    2709              : !!
    2710              : !! SOURCE
    2711              : !! FIXME  technically it should be intent(inout) since FFTW3 can destroy the input
    2712              : !! for particular flags.
    2713              : 
    2714              : function dplan_many_dft_r2c(rank,n,howmany,fin,inembed,istride,idist,fout,onembed,ostride,odist,flags,nthreads) result(plan)
    2715              : 
    2716              : !Arguments ------------------------------------
    2717              : !scalars
    2718              :  integer,intent(in) :: rank,howmany,istride,ostride,flags,idist,odist,nthreads
    2719              :  integer,intent(in) :: n(rank),inembed(rank),onembed(rank)
    2720              :  integer(KIND_FFTW_PLAN) :: plan
    2721              : !arrays
    2722              :  real(dp) :: fin(*),fout(*)
    2723              : 
    2724              : !Local variables-------------------------------
    2725              :  character(len=500) :: msg,frmt
    2726              : ! *************************************************************************
    2727              : 
    2728              :  !$OMP CRITICAL (OMPC_dplan_many_dft_r2c)
    2729              :  call fftw3_set_nthreads(nthreads)
    2730              : 
    2731              :  call dfftw_plan_many_dft_r2c(plan, rank, n, howmany, &
    2732              :    fin, inembed, istride, idist, fout, onembed, ostride, odist, flags)
    2733              :  !$OMP END CRITICAL (OMPC_dplan_many_dft_r2c)
    2734              : 
    2735              :  if (plan==NULL_PLAN) then ! handle the error.
    2736              :    call wrtout(std_out, "dfftw_plan_many_dft_r2c returned NULL_PLAN")
    2737              :    write(frmt,*)"(a,",rank,"(1x,i0),2(a,i0),a,2(a,",rank,"(1x,i0),2(a,i0),a))"
    2738              :    write(msg,frmt)&
    2739              :     " n = ",n," howmany = ",howmany," flags = ",flags,ch10,&
    2740              :     " inembed = ",inembed," istride = ",istride," idist = ",idist,ch10,&
    2741              :     " onembed = ",onembed," ostride = ",ostride," odist = ",idist,ch10
    2742              :    call wrtout(std_out, msg)
    2743              :    ABI_ERROR("Check FFTW library and/or abinit code")
    2744              :  end if
    2745              : 
    2746              : end function dplan_many_dft_r2c
    2747              : !!***
    2748              : 
    2749              : !----------------------------------------------------------------------
    2750              : 
    2751              : !!****f* m_fftw3/dplan_many_dft_c2r
    2752              : !! NAME
    2753              : !!
    2754              : !! FUNCTION
    2755              : !!
    2756              : !! INPUTS
    2757              : !!
    2758              : !! SIDE EFFECTS
    2759              : !!
    2760              : !! SOURCE
    2761              : 
    2762              : function dplan_many_dft_c2r(rank,n,howmany,fin,inembed,istride,idist,fout,onembed,ostride,odist,flags, nthreads) result(plan)
    2763              : 
    2764              : !Arguments ------------------------------------
    2765              : !scalars
    2766              :  integer,intent(in) :: rank,howmany,istride,ostride,flags,idist,odist,nthreads
    2767              :  integer,intent(in) :: n(rank),inembed(rank),onembed(rank)
    2768              :  integer(KIND_FFTW_PLAN) :: plan
    2769              : !arrays
    2770              :  real(dp) :: fin(*),fout(*)
    2771              : 
    2772              : !Local variables-------------------------------
    2773              :  character(len=500) :: msg,frmt
    2774              : ! *************************************************************************
    2775              : 
    2776              :  !$OMP CRITICAL (OMPC_dplan_many_dft_c2r)
    2777              :  call fftw3_set_nthreads(nthreads)
    2778              : 
    2779              :  call dfftw_plan_many_dft_c2r(plan, rank, n, howmany, &
    2780              :   fin, inembed, istride, idist, fout, onembed, ostride, odist, flags)
    2781              :  !$OMP END CRITICAL (OMPC_dplan_many_dft_c2r)
    2782              : 
    2783              :  if (plan==NULL_PLAN) then ! handle the error.
    2784              :    call wrtout(std_out, "dfftw_plan_many_dft_c2r returned NULL_PLAN")
    2785              :    write(frmt,*)"(a,",rank,"(1x,i0),2(a,i0),a,2(a,",rank,"(1x,i0),2(a,i0),a))"
    2786              :    write(msg,frmt)&
    2787              :     " n = ",n," howmany = ",howmany," flags = ",flags,ch10,&
    2788              :     " inembed = ",inembed," istride = ",istride," idist = ",idist,ch10,&
    2789              :     " onembed = ",onembed," ostride = ",ostride," odist = ",idist,ch10
    2790              :    call wrtout(std_out, msg)
    2791              :    ABI_ERROR("Check FFTW library and/or abinit code")
    2792              :  end if
    2793              : 
    2794              : end function dplan_many_dft_c2r
    2795              : !!***
    2796              : 
    2797              : #endif
    2798              : 
    2799              : !----------------------------------------------------------------------
    2800              : 
    2801              : !!****f* m_fftw3/fftw3_execute_dft_dp
    2802              : !! NAME
    2803              : !! fftw3_execute_dft_dp
    2804              : !!
    2805              : !! FUNCTION
    2806              : !!
    2807              : !! INPUTS
    2808              : !!
    2809              : !! OUTPUT
    2810              : !!
    2811              : !! NOTES
    2812              : !!  This interface is used to perform complex to complex FFT with real arrays
    2813              : !!  containing the real and imaginary part. I have to admit that this interface
    2814              : !!  is a bit ambiguous since FFTW3 provides routines for real-to-real transforms.
    2815              : !!
    2816              : !! SOURCE
    2817              : 
    2818              : #ifdef HAVE_FFTW3
    2819              : 
    2820              : subroutine fftw3_execute_dft_dp(plan, in, out)
    2821              : 
    2822              : !Arguments ------------------------------------
    2823              : !scalars
    2824              :  integer(KIND_FFTW_PLAN),intent(in) :: plan
    2825              :  real(C_DOUBLE),intent(inout) :: in(*)
    2826              :  real(C_DOUBLE),intent(out) :: out(*)
    2827              : ! *************************************************************************
    2828              : 
    2829              :  call dfftw_execute_dft(plan, in, out)
    2830              : 
    2831              : end subroutine fftw3_execute_dft_dp
    2832              : !!***
    2833              : 
    2834              : #endif
    2835              : 
    2836              : !----------------------------------------------------------------------
    2837              : 
    2838              : !!****f* m_fftw3/fftw3_execute_dft_spc
    2839              : !! NAME
    2840              : !! fftw3_execute_dft_spc
    2841              : !!
    2842              : !! SOURCE
    2843              : 
    2844              : #ifdef HAVE_FFTW3
    2845              : 
    2846              : subroutine fftw3_execute_dft_spc(plan, in, out)
    2847              : 
    2848              : !Arguments ------------------------------------
    2849              : !scalars
    2850              :  integer(KIND_FFTW_PLAN),intent(in) :: plan
    2851              :  complex(C_FLOAT_COMPLEX),intent(inout) :: in(*)
    2852              :  complex(C_FLOAT_COMPLEX),intent(out) :: out(*)
    2853              : ! *************************************************************************
    2854              : 
    2855              :  call sfftw_execute_dft(plan, in, out)
    2856              : 
    2857              : end subroutine fftw3_execute_dft_spc
    2858              : !!***
    2859              : 
    2860              : #endif
    2861              : 
    2862              : !----------------------------------------------------------------------
    2863              : 
    2864              : !!****f* m_fftw3/fftw3_execute_dft_dpc
    2865              : !! NAME
    2866              : !! fftw3_execute_dft_dpc
    2867              : !!
    2868              : !! SOURCE
    2869              : 
    2870              : #ifdef HAVE_FFTW3
    2871              : 
    2872              : subroutine fftw3_execute_dft_dpc(plan, in, out)
    2873              : 
    2874              : !Arguments ------------------------------------
    2875              : !scalars
    2876              :  integer(KIND_FFTW_PLAN),intent(in) :: plan
    2877              :  complex(C_DOUBLE_COMPLEX),intent(inout) :: in(*)
    2878              :  complex(C_DOUBLE_COMPLEX),intent(out) :: out(*)
    2879              : ! *************************************************************************
    2880              : 
    2881              :  call dfftw_execute_dft(plan, in, out)
    2882              : 
    2883              : end subroutine fftw3_execute_dft_dpc
    2884              : !!***
    2885              : 
    2886              : #endif
    2887              : 
    2888              : !----------------------------------------------------------------------
    2889              : 
    2890              : !!****f* m_fftw3/fftw3_alloc_real1d_dp
    2891              : !! NAME
    2892              : !! fftw3_alloc_real1d_dp
    2893              : !!
    2894              : !! FUNCTION
    2895              : !!
    2896              : !! SOURCE
    2897              : 
    2898              : #ifdef HAVE_FFTW3
    2899              : 
    2900              : subroutine fftw3_alloc_real1d_dp(size,cptr,fptr)
    2901              : 
    2902              : !Arguments ------------------------------------
    2903              : !scalars
    2904              :  integer,intent(in) :: size
    2905              :  real(dp),contiguous, pointer :: fptr(:)
    2906              :  type(C_PTR),intent(out) :: cptr
    2907              : ! *************************************************************************
    2908              : 
    2909              :  cptr = fftw_malloc( INT(size*C_DOUBLE, KIND=C_SIZE_T))
    2910              :  if (.not. C_ASSOCIATED(cptr)) then
    2911              :    ABI_ERROR("fftw_malloc returned NULL!")
    2912              :  end if
    2913              : 
    2914              :  call c_f_pointer(cptr, fptr, [size])
    2915              : 
    2916              : end subroutine fftw3_alloc_real1d_dp
    2917              : !!***
    2918              : 
    2919              : #endif
    2920              : 
    2921              : !----------------------------------------------------------------------
    2922              : 
    2923              : !!****f* m_fftw3/fftw3_alloc_real2d_dp
    2924              : !! NAME
    2925              : !! fftw3_alloc_real2d_dp
    2926              : !!
    2927              : !! SOURCE
    2928              : 
    2929              : #ifdef HAVE_FFTW3
    2930              : 
    2931              : subroutine fftw3_alloc_real2d_dp(shape,cptr,fptr)
    2932              : 
    2933              : !Arguments ------------------------------------
    2934              : !scalars
    2935              :  integer,intent(in) :: shape(2)
    2936              :  real(dp),contiguous, pointer :: fptr(:,:)
    2937              :  type(C_PTR),intent(out) :: cptr
    2938              : ! *************************************************************************
    2939              : 
    2940              :  cptr = fftw_malloc( INT(product(shape)*C_DOUBLE, KIND=C_SIZE_T))
    2941              :  if (.not. C_ASSOCIATED(cptr)) then
    2942              :    ABI_ERROR("fftw_malloc returned NULL!")
    2943              :  end if
    2944              : 
    2945              :  call c_f_pointer(cptr, fptr, shape)
    2946              : 
    2947              : end subroutine fftw3_alloc_real2d_dp
    2948              : !!***
    2949              : 
    2950              : #endif
    2951              : 
    2952              : !----------------------------------------------------------------------
    2953              : 
    2954              : !!****f* m_fftw3/fftw3_alloc_complex1d_spc
    2955              : !! NAME
    2956              : !! fftw3_alloc_complex1d_spc
    2957              : !!
    2958              : !! SOURCE
    2959              : 
    2960              : #ifdef HAVE_FFTW3
    2961              : 
    2962              : subroutine fftw3_alloc_complex1d_spc(size,cptr,fptr)
    2963              : 
    2964              : !Arguments ------------------------------------
    2965              : !scalars
    2966              :  integer,intent(in) :: size
    2967              :  complex(sp),contiguous, pointer :: fptr(:)
    2968              :  type(C_PTR),intent(out) :: cptr
    2969              : ! *************************************************************************
    2970              : 
    2971              :  cptr = fftw_malloc( INT(2*size*C_FLOAT, KIND=C_SIZE_T))
    2972              :  if (.not. C_ASSOCIATED(cptr)) then
    2973              :    ABI_ERROR("fftw_malloc returned NULL!")
    2974              :  end if
    2975              : 
    2976              :  call c_f_pointer(cptr, fptr, [size])
    2977              : 
    2978              : end subroutine fftw3_alloc_complex1d_spc
    2979              : !!***
    2980              : 
    2981              : #endif
    2982              : 
    2983              : !----------------------------------------------------------------------
    2984              : 
    2985              : !!****f* m_fftw3/fftw3_alloc_complex1d_dpc
    2986              : !! NAME
    2987              : !! fftw3_alloc_complex1d_dpc
    2988              : !!
    2989              : !! SOURCE
    2990              : 
    2991              : #ifdef HAVE_FFTW3
    2992              : 
    2993              : subroutine fftw3_alloc_complex1d_dpc(size,cptr,fptr)
    2994              : 
    2995              : !Arguments ------------------------------------
    2996              : !scalars
    2997              :  integer,intent(in) :: size
    2998              :  complex(dp),contiguous, pointer :: fptr(:)
    2999              :  type(C_PTR),intent(out) :: cptr
    3000              : ! *************************************************************************
    3001              : 
    3002              :  cptr = fftw_malloc( INT(2*size*C_DOUBLE, KIND=C_SIZE_T))
    3003              :  if (.not. C_ASSOCIATED(cptr)) then
    3004              :    ABI_ERROR("fftw_malloc returned NULL!")
    3005              :  end if
    3006              : 
    3007              :  call c_f_pointer(cptr, fptr, [size])
    3008              : 
    3009              : end subroutine fftw3_alloc_complex1d_dpc
    3010              : !!***
    3011              : 
    3012              : #endif
    3013              : 
    3014              : !----------------------------------------------------------------------
    3015              : 
    3016              : !!****f* m_fftw3/fftw3_spawn_threads_here
    3017              : !! NAME
    3018              : !! fftw3_spawn_threads_here
    3019              : !!
    3020              : !! FUNCTION
    3021              : !!  Helper function that returns true if FFT calls should be OMP
    3022              : !!  parallelized in the client code.
    3023              : !!
    3024              : !! INPUTS
    3025              : !!  ndat=Number of FFT transforms to do
    3026              : !!  nthreads = Number of threads available
    3027              : !!
    3028              : !! SOURCE
    3029              : 
    3030            0 : function fftw3_spawn_threads_here(ndat,nthreads) result(ans)
    3031              : 
    3032              : !Arguments ------------------------------------
    3033              : !scalars
    3034              :  integer,intent(in) :: ndat,nthreads
    3035              :  logical :: ans
    3036              : ! *************************************************************************
    3037              : 
    3038            0 :  ans = .FALSE.
    3039              : #ifdef HAVE_OPENMP
    3040              :  ans = (nthreads > 1 .and. MOD(ndat,nthreads) == 0 .and. .not. USE_LIB_THREADS)
    3041              : #else
    3042              :  ABI_UNUSED((/ndat,nthreads/))
    3043              : #endif
    3044              : 
    3045            0 : end function fftw3_spawn_threads_here
    3046              : !!***
    3047              : 
    3048              : !----------------------------------------------------------------------
    3049              : 
    3050              : !!****f* m_fftw3/fftw3_use_lib_threads
    3051              : !! NAME
    3052              : !! fftw3_use_lib_threads
    3053              : !!
    3054              : !! FUNCTION
    3055              : !!
    3056              : !! INPUTS
    3057              : !!
    3058              : !! SOURCE
    3059              : 
    3060           19 : subroutine fftw3_use_lib_threads(logvar)
    3061              : 
    3062              : !Arguments ------------------------------------
    3063              :  logical,intent(in) :: logvar
    3064              : ! *************************************************************************
    3065              : 
    3066           19 :  USE_LIB_THREADS = logvar
    3067              : 
    3068           19 : end subroutine fftw3_use_lib_threads
    3069              : !!***
    3070              : 
    3071              : !----------------------------------------------------------------------
    3072              : 
    3073              : !!****f* m_fftw3/fftwmpi_get_work_array
    3074              : !! NAME
    3075              : !!  fftwmpi_get_work_array
    3076              : !!
    3077              : !! FUNCTION
    3078              : !! Driver routine for allocate fftw work array for 3D complex-to-complex FFTs of lengths nx, ny, nz.
    3079              : !!
    3080              : !! INPUTS
    3081              : !! nx,ny,nz=Number of points along the three directions.
    3082              : !! ndat=Number of FFTs to be done.
    3083              : !! comm_fft=MPI communicator.
    3084              : !!
    3085              : !! OUTPUT
    3086              : !! cdata_f,cdata_r: C pointers to use for fourier andreal data
    3087              : !! n0,n0_tr : local size on the shared dimension (nz or ny if transposed mode is used)
    3088              : !! offset,offset_tr : offset per process in continuous tabx
    3089              : !!
    3090              : !! SOURCE
    3091              : 
    3092              : subroutine fftwmpi_get_work_array(cdata_f,cdata_r,rank,nx,ny,nz,ndat,comm_fft,n0,offset,n0_tr,offset_tr)
    3093              : 
    3094              : !Arguments ------------------------------------
    3095              : !scalars
    3096              :  integer,intent(in) :: nx,ny,nz,ndat,rank,comm_fft
    3097              :  integer(C_INTPTR_T), intent(out) :: n0, offset, n0_tr, offset_tr
    3098              :  type(C_PTR), intent(out) :: cdata_f,cdata_r
    3099              : 
    3100              : !Local variables-------------------------------
    3101              : #ifdef HAVE_FFTW3_MPI
    3102              : !scalars
    3103              :  integer(C_INTPTR_T) :: alloc_local
    3104              : !arrays
    3105              :  integer(C_INTPTR_T) :: fft_sizes(4)
    3106              : ! *************************************************************************
    3107              : 
    3108              :  ! Dimensions are inverted here (C interface).
    3109              :  fft_sizes(1)=nz
    3110              :  fft_sizes(2)=ny
    3111              :  fft_sizes(3)=nx
    3112              :  fft_sizes(4)=ndat
    3113              : 
    3114              :  alloc_local = fftw_mpi_local_size_many_transposed(rank,fft_sizes(1:3),fft_sizes(4), &
    3115              : &      FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, comm_fft, &
    3116              : &      n0,offset, &
    3117              : &      n0_tr,offset_tr)
    3118              : 
    3119              :  cdata_f = fftw_alloc_complex(alloc_local)
    3120              :  cdata_r = fftw_alloc_complex(alloc_local)
    3121              : 
    3122              : #else
    3123              :   ABI_ERROR("FFTW3_MPI support not activated")
    3124              :   ABI_UNUSED((/nx,ny,nz,ndat,rank,comm_fft/))
    3125              :   cdata_f = C_NULL_PTR; cdata_r = C_NULL_PTR
    3126              :   n0 = 0; offset = 0; n0_tr = 0; offset_tr = 0
    3127              : #endif
    3128              : 
    3129              : end subroutine fftwmpi_get_work_array
    3130              : !!***
    3131              : 
    3132              : !----------------------------------------------------------------------
    3133              : 
    3134              : !!****f* m_fftw3/fftwmpi_free_work_array
    3135              : !! NAME
    3136              : !!  fftwmpi_free_work_array
    3137              : !!
    3138              : !! FUNCTION
    3139              : !!  routine for freeing fftw work array
    3140              : !!
    3141              : !! INPUTS
    3142              : !!
    3143              : !! OUTPUT
    3144              : !! cdata_f,cdata_r: C pointers to free for fourier andreal data
    3145              : !!
    3146              : !! SOURCE
    3147              : 
    3148              : subroutine fftwmpi_free_work_array(cdata_f,cdata_r)
    3149              : 
    3150              : !Arguments ------------------------------------
    3151              : !scalars
    3152              :  type(C_PTR), intent(inout) :: cdata_f,cdata_r
    3153              : ! *************************************************************************
    3154              : 
    3155              : #ifdef HAVE_FFTW3_MPI
    3156              :  call fftw_free(cdata_r)
    3157              :  call fftw_free(cdata_f)
    3158              : #else
    3159              :  ABI_ERROR("FFTW3_MPI support not activated")
    3160              :  if(.false.) then
    3161              :    cdata_r = C_NULL_PTR; cdata_f = C_NULL_PTR
    3162              :  end if
    3163              : #endif
    3164              : 
    3165              : end subroutine fftwmpi_free_work_array
    3166              : !!***
    3167              : 
    3168              : !----------------------------------------------------------------------
    3169              : 
    3170              : !!****f* m_fftw3/fftw3mpi_many_dft_ip
    3171              : !! NAME
    3172              : !!  fftw3mpi_many_dft_ip
    3173              : !!
    3174              : !! FUNCTION
    3175              : !! Driver routine for many out-of-place 3D complex-to-complex FFTs of lengths nx, ny, nz.
    3176              : !!
    3177              : !! INPUTS
    3178              : !! nx,ny,nz=Number of points along the three directions.
    3179              : !! ldx,ldy,ldz=Physical dimension of the fin and fout arrays (to avoid cache conflicts).
    3180              : !! ndat=Number of FFTs to be done.
    3181              : !! fin(2*ldx*ldy*ldz*ndat)=The complex array to be transformed.
    3182              : !! isign=sign of Fourier transform exponent: current convention uses
    3183              : !!   +1 for transforming from G to r,
    3184              : !!   -1 for transforming from r to G.
    3185              : !! comm_fft=MPI communicator for the FFT
    3186              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    3187              : !!   Defaults to ABI_FFTW_ESTIMATE.
    3188              : !!
    3189              : !! TODO
    3190              : !!  Remove me
    3191              : !!
    3192              : !! OUTPUT
    3193              : !! fout(2,ldx*ldy*ldz*ndat)=The Fourier transform of fin.
    3194              : !!
    3195              : !! SOURCE
    3196              : 
    3197              : subroutine fftw3mpi_many_dft_ip(nx,ny,nz,ldx,ldy,ldz,ndat,isign,fin,fout,comm_fft,fftw_flags)
    3198              : 
    3199              : !Arguments ------------------------------------
    3200              : !scalars
    3201              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,isign,comm_fft
    3202              :  integer,optional,intent(in) :: fftw_flags
    3203              : !arrays
    3204              :  real(dp),intent(in) :: fin(2,ldx,ldy,ldz*ndat)
    3205              :  real(dp),intent(out) :: fout(2,ldx,ldy,ldz*ndat)
    3206              : 
    3207              : #ifdef HAVE_FFTW3_MPI
    3208              : !Local variables-------------------------------
    3209              : !scalars
    3210              :  integer,parameter :: rank3=3
    3211              :  integer :: my_flags
    3212              :  real(dp):: factor_fft
    3213              : !arrays
    3214              :  type(C_PTR) :: plan, cdata
    3215              :  complex(C_DOUBLE_COMPLEX), contiguous, pointer :: data(:,:,:)
    3216              :  integer(C_INTPTR_T) :: i, j, k, alloc_local, local_n0, local_0_start,fft_sizes(4)
    3217              : !*************************************************************************
    3218              : 
    3219              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    3220              : 
    3221              :  ! get local data size and allocate (note dimension reversal)
    3222              :  fft_sizes = [nz,ny,nx,ndat]
    3223              : 
    3224              :  alloc_local = fftw_mpi_local_size_many( &
    3225              :       rank3,fft_sizes(1:3),fft_sizes(4),&
    3226              :       FFTW_MPI_DEFAULT_BLOCK, comm_fft, &
    3227              :       local_n0,local_0_start)
    3228              : 
    3229              :  ! Allocate cdata, build the plane and copy data: fin --> data
    3230              :  cdata = fftw_alloc_complex(alloc_local)
    3231              :  call c_f_pointer(cdata, data, [fft_sizes(3),fft_sizes(2), local_n0])
    3232              : 
    3233              :  plan = fftw_mpi_plan_many_dft(rank3,fft_sizes(1:3),fft_sizes(4), &
    3234              :                                FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
    3235              :                                data,data,comm_fft,isign,my_flags)
    3236              : 
    3237              :  do k=1, local_n0*ndat
    3238              :     do j=1, ny
    3239              :        do i=1, nx
    3240              :           data(i,j,k) = CMPLX( fin(1,i,j,k),fin(2,i,j,k),C_DOUBLE_COMPLEX)
    3241              :        end do
    3242              :     end do
    3243              :  end do
    3244              : 
    3245              :  ! Compute transform.
    3246              :  call fftw_mpi_execute_dft(plan, data, data)
    3247              : 
    3248              :  if(isign==ABI_FFTW_FORWARD) then
    3249              :     ! Scale results.
    3250              :     factor_fft = one / (nx*ny*nz)
    3251              :     do k=1, local_n0*ndat
    3252              :        do j=1, ny
    3253              :           do i=1, nx
    3254              :              fout(1,i,j,k) =  real(data(i,j,k)) * factor_fft
    3255              :              fout(2,i,j,k) = aimag(data(i,j,k)) * factor_fft
    3256              :           end do
    3257              :        end do
    3258              :     end do
    3259              :  end if
    3260              : 
    3261              :  call fftw_destroy_plan(plan)
    3262              :  call fftw_free(cdata)
    3263              : 
    3264              : #else
    3265              :  ABI_ERROR("FFTW3_MPI support not activated")
    3266              :  ABI_UNUSED((/nx,ny,nz,ldx,ldy,ldz,ndat,isign/))
    3267              :  ABI_UNUSED(comm_fft)
    3268              :  if (PRESENT(fftw_flags)) then
    3269              :     ABI_UNUSED(fftw_flags)
    3270              :  end if
    3271              :  ABI_UNUSED(fin(1,1,1,1))
    3272              :  ABI_UNUSED(fout(1,1,1,1))
    3273              : #endif
    3274              : 
    3275              : end subroutine fftw3mpi_many_dft_ip
    3276              : !!***
    3277              : 
    3278              : !----------------------------------------------------------------------
    3279              : 
    3280              : !!****f* m_fftw3/fftw3mpi_many_dft_tr
    3281              : !! NAME
    3282              : !!  fftw3mpi_many_dft_tr
    3283              : !!
    3284              : !! FUNCTION
    3285              : !! Driver routine for many out-of-place 3D complex-to-complex FFTs of lengths nx, ny, nz.
    3286              : !!
    3287              : !! INPUTS
    3288              : !! nx,ny,nz=Number of points along the three directions.
    3289              : !! ldx,ldy,ldz=Physical dimension of the fin and fout arrays (to avoid cache conflicts).
    3290              : !! ndat=Number of FFTs to be done.
    3291              : !! fin(2*ldx*ldy*ldz*ndat)=The complex array to be transformed.
    3292              : !! isign=sign of Fourier transform exponent: current convention uses
    3293              : !!   +1 for transforming from G to r,
    3294              : !!   -1 for transforming from r to G.
    3295              : !! comm_fft=MPI communicator for the FFT.
    3296              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    3297              : !!   Defaults to ABI_FFTW_ESTIMATE.
    3298              : !!
    3299              : !! TODO
    3300              : !!  Remove me
    3301              : !!
    3302              : !! OUTPUT
    3303              : !! fout(2,ldx*ldy*ldz*ndat)=The Fourier transform of fin.
    3304              : !!
    3305              : !! SOURCE
    3306              : 
    3307              : subroutine fftw3mpi_many_dft_tr(nx,ny,nz,ndat,isign,fin,fout,comm_fft,fftw_flags)
    3308              : 
    3309              : !Arguments ------------------------------------
    3310              : !scalars
    3311              :  integer,intent(in) :: nx,ny,nz,ndat,isign,comm_fft
    3312              :  integer,optional,intent(in) :: fftw_flags
    3313              : !arrays
    3314              :  complex(C_DOUBLE_COMPLEX),contiguous, pointer  :: fin(:,:,:)
    3315              :  complex(C_DOUBLE_COMPLEX),contiguous, pointer :: fout(:,:,:)
    3316              : 
    3317              : !Local variables-------------------------------
    3318              : #ifdef HAVE_FFTW3_MPI
    3319              : !scalars
    3320              :  integer :: my_flags
    3321              :  !FFTWMPI stuff
    3322              :  type(C_PTR) :: plan
    3323              :  integer(C_INTPTR_T) :: fft_sizes(4)
    3324              : !*************************************************************************
    3325              : 
    3326              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    3327              :  my_flags = ior(my_flags,FFTW_DESTROY_INPUT)
    3328              : 
    3329              :  fft_sizes(1)=nz
    3330              :  fft_sizes(2)=ny
    3331              :  fft_sizes(3)=nx
    3332              :  fft_sizes(4)=ndat
    3333              : 
    3334              :  plan = fftw_mpi_plan_many_dft(3,fft_sizes(1:3),fft_sizes(4), &
    3335              : &                              FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
    3336              : &                              fin,fout,comm_fft,isign,my_flags)
    3337              : 
    3338              : !Compute transform (as many times as desired)
    3339              :  call fftw_mpi_execute_dft(plan, fin, fout)
    3340              :  call fftw_destroy_plan(plan)
    3341              : 
    3342              : #else
    3343              :  ABI_ERROR("FFTW3_MPI support not activated")
    3344              :  ABI_UNUSED((/nx,ny,nz,ndat,isign,comm_fft/))
    3345              :  if (PRESENT(fftw_flags)) then
    3346              :     ABI_UNUSED(fftw_flags)
    3347              :  end if
    3348              :  ABI_UNUSED(fin(1,1,1))
    3349              :  ABI_UNUSED(fout(1,1,1))
    3350              : #endif
    3351              : 
    3352              : end subroutine fftw3mpi_many_dft_tr
    3353              : !!***
    3354              : 
    3355              : !----------------------------------------------------------------------
    3356              : 
    3357              : !!****f* m_fftw3/fftw3_mpifourdp_c2r
    3358              : !! NAME
    3359              : !!  fftw3_mpifourdp_c2r
    3360              : !!
    3361              : !! FUNCTION
    3362              : !! Driver routine for transposed out-of-place 3D complex-to-real FFT of lengths nx, ny, nz.
    3363              : !!
    3364              : !! INPUTS
    3365              : !! nx,ny,nz=Number of point along the three directions.
    3366              : !! ndat=Number of FFTs to be done.
    3367              : !! fofg(2,nx*ny*nz*ndat)=The complex array to be transformed.
    3368              : !! comm_fft=MPI communicator.
    3369              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    3370              : !!   Defaults to ABI_FFTW_ESTIMATE.
    3371              : !!
    3372              : !! OUTPUT
    3373              : !! fofr(2,nx*ny*nz*ndat)=The backwards real FFT of ff.
    3374              : !!
    3375              : !! NOTES
    3376              : !! LOCAL DATA IN FOURIER SPACE : TRANSPOSED ORDER
    3377              : !! real space     --> dim = [  nx  | ny | nz/np_fft]
    3378              : !! fourier  space --> dim = [ nx/2 | nz | ny/np_ff ]
    3379              : !!
    3380              : !! SOURCE
    3381              : 
    3382              : subroutine fftw3_mpifourdp_c2r(nfft,ngfft,ndat,&
    3383              :   fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local,fofg,fofr,comm_fft,fftw_flags)
    3384              : 
    3385              : !Arguments ------------------------------------
    3386              : !scalars
    3387              :  integer,intent(in) :: nfft,ndat,comm_fft
    3388              :  integer,optional,intent(in) :: fftw_flags
    3389              : !arrays
    3390              :  integer,intent(in) :: ngfft(18)
    3391              :  integer,intent(in) :: fftn2_distrib(ngfft(2)),ffti2_local(ngfft(2))
    3392              :  integer,intent(in) :: fftn3_distrib(ngfft(3)),ffti3_local(ngfft(3))
    3393              :  real(dp),intent(in) :: fofg(2,nfft*ndat)
    3394              :  real(dp),intent(out) :: fofr(nfft*ndat)
    3395              : 
    3396              : !Local variables-------------------------------
    3397              : #ifdef HAVE_FFTW3_MPI
    3398              : !scalars
    3399              :  integer,parameter :: rank3=3
    3400              :  integer :: nx,ny,nz,nproc_fft
    3401              :  type(C_PTR) :: plan_bw, cdata_cplx,cdata_real
    3402              :  integer(C_INTPTR_T) :: i,j,jdat,k,alloc_local,fft_sizes(4),demi_nx,base,idat,kdat
    3403              :  integer(C_INTPTR_T) :: local_n0, local_0_start, local_n1, local_1_start
    3404              : !arrays
    3405              :  complex(C_DOUBLE_COMPLEX), contiguous, pointer :: data_cplx(:,:,:)
    3406              :  real(C_DOUBLE), contiguous, pointer :: data_real(:,:,:)
    3407              : ! *************************************************************************
    3408              : 
    3409              :  !ABI_CHECK(ndat==1, "ndat > 1 not implemented yet")
    3410              : 
    3411              :  nx=ngfft(1); ny=ngfft(2); nz=ngfft(3)
    3412              :  nproc_fft = xmpi_comm_size(comm_fft)
    3413              : 
    3414              :  demi_nx = nx/2 + 1
    3415              :  fft_sizes(1)=nz
    3416              :  fft_sizes(2)=ny
    3417              :  fft_sizes(3)=demi_nx
    3418              :  fft_sizes(4)=ndat
    3419              : 
    3420              :  alloc_local = fftw_mpi_local_size_many_transposed(&
    3421              :       rank3,fft_sizes(1:3),fft_sizes(4), &
    3422              :       FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, comm_fft, &
    3423              :       local_n0,local_0_start, &
    3424              :       local_n1,local_1_start)
    3425              : 
    3426              :  cdata_cplx = fftw_alloc_complex(alloc_local)
    3427              :  cdata_real = fftw_alloc_real(alloc_local*2)
    3428              : 
    3429              : ! OLD BY FDHAM
    3430              :  ! dimensions are  (x/2,z,y) in Fourier's Space
    3431              :  call c_f_pointer(cdata_cplx, data_cplx, [demi_nx  ,fft_sizes(1),local_n1])
    3432              :  ! dimensions in real space : (nx,ny,nz/nproc)
    3433              :  call c_f_pointer(cdata_real, data_real, [2*demi_nx,fft_sizes(2),local_n0])
    3434              : 
    3435              :  ! dimensions are  (x/2,z,y) in Fourier's Space
    3436              :  !call c_f_pointer(cdata_cplx, data_cplx, [demi_nx  ,fft_sizes(1),local_n0])
    3437              : 
    3438              :  !! dimensions in real space : (nx,ny,nz/nproc)
    3439              :  !call c_f_pointer(cdata_real, data_real, [2*demi_nx,fft_sizes(2),local_n1])
    3440              : 
    3441              :  fft_sizes(3)=nx
    3442              :  plan_bw =  fftw_mpi_plan_many_dft_c2r(&
    3443              :       rank3,fft_sizes(1:3),fft_sizes(4), &
    3444              :       FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
    3445              :       data_cplx, data_real , &
    3446              :       comm_fft,ior(ABI_FFTW_ESTIMATE,ABI_FFTW_MPI_TRANSPOSED_IN))
    3447              : 
    3448              :  do idat=1,ndat
    3449              :    do k=1, nz
    3450              :      do j=1, ny / nproc_fft
    3451              :        jdat = j + (idat-1) * ny / nproc_fft
    3452              :        base = nx*((j-1) + (ny/nproc_fft)*(k-1)) + (idat-1) * nfft
    3453              :        do i=1, demi_nx
    3454              :          data_cplx(i,k,jdat) = CMPLX(fofg(1, i + base), fofg(2, i + base), kind=C_DOUBLE_COMPLEX)
    3455              :        end do
    3456              :      end do
    3457              :    end do
    3458              :  end do
    3459              : 
    3460              :  ! compute transform (as many times as desired)
    3461              :  call fftw_mpi_execute_dft_c2r(plan_bw, data_cplx, data_real)
    3462              : 
    3463              :  do idat=1,ndat
    3464              :    do k=1,local_n0
    3465              :      kdat = k + (idat - 1) * local_n0
    3466              :      do j=1,ny
    3467              :        base = nx*((j-1) + ny*(k-1)) + (idat - 1) * nfft
    3468              :        do i=1,nx
    3469              :          fofr(i+base) = data_real(i,j,kdat)
    3470              :        end do
    3471              :      end do
    3472              :    end do
    3473              :  end do
    3474              : 
    3475              :  call fftw_destroy_plan(plan_bw)
    3476              :  call fftw_free(cdata_cplx)
    3477              :  call fftw_free(cdata_real)
    3478              : 
    3479              : #else
    3480              :  ABI_ERROR("FFTW3_MPI support not activated")
    3481              :  ABI_UNUSED((/nfft,ngfft(1),ndat,comm_fft/))
    3482              :  ABI_UNUSED((/fftn2_distrib(1),ffti2_local(1)/))
    3483              :  ABI_UNUSED((/fftn3_distrib(1),ffti3_local(1)/))
    3484              :  if (PRESENT(fftw_flags)) then
    3485              :     ABI_UNUSED(fftw_flags)
    3486              :  end if
    3487              :  ABI_UNUSED(fofg(1,1))
    3488              :  ABI_UNUSED(fofr(1))
    3489              : #endif
    3490              : 
    3491              : end subroutine fftw3_mpifourdp_c2r
    3492              : !!***
    3493              : 
    3494              : !----------------------------------------------------------------------
    3495              : 
    3496              : !!****f* m_fftw3/fftw3_mpifourdp_r2c
    3497              : !! NAME
    3498              : !!  fftw3_mpifourdp_r2c
    3499              : !!
    3500              : !! FUNCTION
    3501              : !! Driver routine for out-of-place 3D real-to-complex FFT of lengths nx, ny, nz.
    3502              : !!
    3503              : !! INPUTS
    3504              : !! fofr(nx*ny*nz*ndat)=The real array to be transformed.
    3505              : !! ndat=Number of FFTs to be done.
    3506              : !! comm_fft=MPI communicator for the FFT.
    3507              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    3508              : !!   Defaults to ABI_FFTW_ESTIMATE.
    3509              : !!
    3510              : !! OUTPUT
    3511              : !! fofg(2,nx*ny*nz*ndat)=The forward FFT of ff.
    3512              : !!
    3513              : !! NOTES
    3514              : !! LOCAL DATA FOR FOURIER TRANSFORMS : TRANSPOSED ORDER AND DISTRIBUTED
    3515              : !! real space     --> dim = [  nx  | ny | nz/np_fft ]
    3516              : !! fourier  space --> dim = [  nx | nz | ny/np_fft ]
    3517              : !! we can't take in account the symmetric of the real case because after
    3518              : !! fft have been computed, the symmetric data needed are dispatched over
    3519              : !! other process in parallel
    3520              : !!
    3521              : !! SOURCE
    3522              : 
    3523              : subroutine fftw3_mpifourdp_r2c(nfft,ngfft,ndat,&
    3524              :   fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local,fofg,fofr,comm_fft,fftw_flags)
    3525              : 
    3526              : !Arguments ------------------------------------
    3527              : !scalars
    3528              :  integer,intent(in) :: nfft,ndat,comm_fft
    3529              :  integer,optional,intent(in) :: fftw_flags
    3530              : !arrays
    3531              :  integer,intent(in) :: ngfft(18)
    3532              :  integer,intent(in) :: fftn2_distrib(ngfft(2)),ffti2_local(ngfft(2))
    3533              :  integer,intent(in) :: fftn3_distrib(ngfft(3)),ffti3_local(ngfft(3))
    3534              :  real(dp),intent(in) :: fofr(nfft*ndat)
    3535              :  real(dp),intent(out) :: fofg(2,nfft*ndat)
    3536              : 
    3537              : !Local variables-------------------------------
    3538              : #ifdef HAVE_FFTW3_MPI
    3539              :  !scalars
    3540              :  integer,parameter :: rank3=3
    3541              :  integer :: my_flags,nproc_fft,nx,ny,nz
    3542              :  integer(C_INTPTR_T) :: i,j,k,base,alloc_local,i1,i2,i3,igf,idat,kdat,i2dat,padatf
    3543              :  integer(C_INTPTR_T) :: local_n0,local_0_start,local_n1,local_1_start
    3544              :  real(dp) :: factor_fft
    3545              :  type(C_PTR) :: plan_fw,cdata_cplx,cdata_real
    3546              : !arrays
    3547              :  complex(C_DOUBLE_COMPLEX), contiguous, pointer :: data_cplx(:,:,:),data_real(:,:,:)
    3548              :  integer(C_INTPTR_T) :: fft_sizes(4)
    3549              : ! *************************************************************************
    3550              : 
    3551              :  nproc_fft = xmpi_comm_size(comm_fft)
    3552              : 
    3553              :  nx=ngfft(1); ny=ngfft(2); nz=ngfft(3)
    3554              : 
    3555              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    3556              : 
    3557              :  fft_sizes(1)=nz
    3558              :  fft_sizes(2)=ny
    3559              :  fft_sizes(3)=nx
    3560              :  fft_sizes(4)=ndat
    3561              : 
    3562              :  ! Get parallel sizes
    3563              :  alloc_local = fftw_mpi_local_size_many_transposed(&
    3564              :       rank3,fft_sizes(1:3),fft_sizes(4), &
    3565              :       FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, comm_fft, &
    3566              :       local_n0,local_0_start, &
    3567              :       local_n1,local_1_start)
    3568              : 
    3569              :  ! Allocate data and reference it
    3570              : 
    3571              :  ! local data in real space     --> dim = [nx | ny | nz/nproc_fft]
    3572              :  cdata_real = fftw_alloc_complex(alloc_local)
    3573              :  call c_f_pointer(cdata_real, data_real, [fft_sizes(3),fft_sizes(2),local_n0])
    3574              : 
    3575              :  ! local data in Fourier space --> dim = [nx | nz | ny/nproc_fft]
    3576              :  cdata_cplx = fftw_alloc_complex(alloc_local)
    3577              :  call c_f_pointer(cdata_cplx, data_cplx, [fft_sizes(3),fft_sizes(1),local_n1])
    3578              : 
    3579              :  ! TODO: Use true real to complex API!
    3580              :  ! Create Plan C2C (nx,ny,nz)
    3581              :  plan_fw =  fftw_mpi_plan_many_dft(&
    3582              :       rank3,fft_sizes(1:3),fft_sizes(4), &
    3583              :       FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
    3584              :       data_real, data_cplx , &
    3585              :       comm_fft,ABI_FFTW_FORWARD,ior(ABI_FFTW_ESTIMATE,ABI_FFTW_MPI_TRANSPOSED_OUT))
    3586              : 
    3587              :  ! Copy input data in correct format
    3588              :  do idat=1,ndat
    3589              :    do k=1,local_n0
    3590              :      kdat = k + (idat-1) * local_n0
    3591              :      do j=1, ny
    3592              :        base = nx*((j-1) + ny*(k-1)) + (idat-1) * nfft
    3593              :        do i=1, nx
    3594              :          data_real(i,j,kdat) = CMPLX(fofr(i+base),zero, kind=C_DOUBLE_COMPLEX)
    3595              :        end do
    3596              :      end do
    3597              :    end do
    3598              :  end do
    3599              : 
    3600              :  ! Compute transform
    3601              :  call fftw_mpi_execute_dft(plan_fw, data_real, data_cplx)
    3602              : 
    3603              :  factor_fft = one / (nx*ny*nz)
    3604              : 
    3605              :  do idat=1,ndat
    3606              :     padatf=(idat-1)*nfft
    3607              :     do i3=1,nz
    3608              :        do i2=1,ny/nproc_fft ! equivalent a local_n1
    3609              :           i2dat = i2 + (idat-1) * ny/nproc_fft
    3610              :           do i1=1,nx
    3611              :              igf = i1 + nx*( (i2-1) + (i3-1)*ny/nproc_fft  ) + padatf
    3612              :              fofg(1,igf) = real(data_cplx(i1,i3,i2dat)) * factor_fft
    3613              :              fofg(2,igf) =aimag(data_cplx(i1,i3,i2dat)) * factor_fft
    3614              :           end do
    3615              :        end do
    3616              :     end do
    3617              :  end do
    3618              : 
    3619              :  call fftw_destroy_plan(plan_fw)
    3620              :  call fftw_free(cdata_cplx)
    3621              :  call fftw_free(cdata_real)
    3622              : 
    3623              : #else
    3624              :  ABI_ERROR("FFTW3_MPI support not activated")
    3625              :  ABI_UNUSED((/nfft,ngfft(1),ndat,comm_fft/))
    3626              :  ABI_UNUSED((/fftn2_distrib(1),ffti2_local(1)/))
    3627              :  ABI_UNUSED((/fftn3_distrib(1),ffti3_local(1)/))
    3628              :  if (PRESENT(fftw_flags)) then
    3629              :     ABI_UNUSED(fftw_flags)
    3630              :  end if
    3631              :  ABI_UNUSED(fofg(1,1))
    3632              :  ABI_UNUSED(fofr(1))
    3633              : #endif
    3634              : 
    3635              : end subroutine fftw3_mpifourdp_r2c
    3636              : !!***
    3637              : 
    3638              : !----------------------------------------------------------------------
    3639              : 
    3640              : !!****f* m_fftw3/old_fftw3_mpifourdp
    3641              : !! NAME
    3642              : !!  old_fftw3_mpifourdp
    3643              : !!
    3644              : !! FUNCTION
    3645              : !!
    3646              : !! INPUTS
    3647              : !! cplex=1 if fofr is real, 2 if fofr is complex
    3648              : !! nfft=(effective) number of FFT grid points (for this processor)
    3649              : !! ndat=Number of FFTs to be done.
    3650              : !! isign= +1 : fofg(G) => fofr(R);
    3651              : !!        -1 : fofr(R) => fofg(G)
    3652              : !! fftn2_distrib(n2)=  rank of the processor which own fft planes in 2nd dimension for fourdp
    3653              : !! ffti2_local(n2) = local i2 indices in fourdp
    3654              : !! fftn3_distrib(n3) = rank of the processor which own fft planes in 3rd dimension for fourdp
    3655              : !! ffti3_local(n3) = local i3 indices in fourdp
    3656              : !! comm_fft=MPI communicator for the FFT
    3657              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    3658              : !!
    3659              : !! SIDE EFFECTS
    3660              : !! Input/Output
    3661              : !! fofg(2,nfft*ndat)=f(G), complex.
    3662              : !! fofr(cplex*nfft*ndat)=input function f(r) (real or complex)
    3663              : !!
    3664              : !! SOURCE
    3665              : 
    3666              : subroutine old_fftw3_mpifourdp(cplex,nfft,ngfft,ndat,isign,&
    3667              :   fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local,fofg,fofr,comm_fft,fftw_flags)
    3668              : 
    3669              : !Arguments ------------------------------------
    3670              : !scalars
    3671              :  integer,intent(in) :: cplex,nfft,ndat,isign,comm_fft
    3672              :  integer,optional,intent(in) :: fftw_flags
    3673              : !arrays
    3674              :  integer,intent(in) :: ngfft(18)
    3675              :  integer,intent(in) :: fftn2_distrib(ngfft(2)),ffti2_local(ngfft(2))
    3676              :  integer,intent(in) :: fftn3_distrib(ngfft(3)),ffti3_local(ngfft(3))
    3677              :  real(dp),intent(inout) :: fofg(2,nfft*ndat),fofr(cplex*nfft*ndat)
    3678              : 
    3679              : #ifdef HAVE_FFTW3_MPI
    3680              : !Local variables-------------------------------
    3681              : !scalars
    3682              :  integer :: nx,ny,nz,my_flags
    3683              : ! *************************************************************************
    3684              : 
    3685              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    3686              : 
    3687              :  nx=ngfft(1); ny=ngfft(2); nz=ngfft(3)
    3688              :  !me_fft=ngfft(11); nproc_fft=ngfft(10)
    3689              : 
    3690              :  select case (cplex)
    3691              : 
    3692              :  case (1)
    3693              : 
    3694              :    ! Complex to Complex.
    3695              :    ! This one is ok when ndat > 1
    3696              :    !call fftw3_mpifourdp_c2c(cplex,nfft,ngfft,ndat,isign,&
    3697              :    !& fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local,fofg,fofr,comm_fft,fftw_flags=my_flags)
    3698              :    !return
    3699              : 
    3700              :    ! r2c or c2r case.
    3701              :    ! FIXME this one is buggy when ndat > 1
    3702              :    select case (isign)
    3703              :    case (ABI_FFTW_FORWARD)
    3704              :      ! +1; R --> G
    3705              :     call fftw3_mpifourdp_r2c(nfft,ngfft,ndat,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local,&
    3706              : &     fofg,fofr,comm_fft,fftw_flags=my_flags)
    3707              : 
    3708              :    case (ABI_FFTW_BACKWARD)
    3709              :      ! -1; G --> R
    3710              :     call fftw3_mpifourdp_c2r(nfft,ngfft,ndat,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local,&
    3711              :      fofg,fofr,comm_fft,fftw_flags=my_flags)
    3712              : 
    3713              :    case default
    3714              :      ABI_BUG("Wrong isign")
    3715              :    end select
    3716              : 
    3717              :  case (2)
    3718              :    ! Complex to Complex.
    3719              :    call fftw3_mpifourdp_c2c(cplex,nfft,ngfft,ndat,isign,&
    3720              :     fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local,fofg,fofr,comm_fft,fftw_flags=my_flags)
    3721              : 
    3722              :  case default
    3723              :    ABI_BUG(" Wrong value for cplex")
    3724              :  end select
    3725              : 
    3726              : #else
    3727              :  ABI_ERROR("FFTW3_MPI support not activated")
    3728              :  ABI_UNUSED((/cplex,nfft,ngfft(1),ndat,isign,comm_fft/))
    3729              :  ABI_UNUSED((/fftn2_distrib(1),ffti2_local(1)/))
    3730              :  ABI_UNUSED((/fftn3_distrib(1),ffti3_local(1)/))
    3731              :  if (PRESENT(fftw_flags)) then
    3732              :     ABI_UNUSED(fftw_flags)
    3733              :  end if
    3734              :  ABI_UNUSED(fofg(1,1))
    3735              :  ABI_UNUSED(fofr(1))
    3736              : #endif
    3737              : 
    3738              : end subroutine old_fftw3_mpifourdp
    3739              : !!***
    3740              : 
    3741              : !----------------------------------------------------------------------
    3742              : 
    3743              : !!****f* m_fftw3/fftw3_mpifourdp_c2c
    3744              : !! NAME
    3745              : !! fftw3_mpifourdp_c2c
    3746              : !!
    3747              : !! FUNCTION
    3748              : !! Driver routine for many out-of-place 3D complex-to-complex FFTs of lengths n1, n2, n3.
    3749              : !!
    3750              : !! INPUTS
    3751              : !! cplex=1 if fofr is real, 2 if fofr is complex
    3752              : !! nfft=(effective) number of FFT grid points (for this processor)
    3753              : !! ndat=Number of FFTs to be done.
    3754              : !! isign=sign of Fourier transform exponent: current convention uses
    3755              : !!   +1 for transforming from G to r,
    3756              : !!   -1 for transforming from r to G.
    3757              : !! fftn2_distrib(n2)=  rank of the processor which own fft planes in 2nd dimension for fourdp
    3758              : !! ffti2_local(n2) = local i2 indices in fourdp
    3759              : !! fftn3_distrib(n3) = rank of the processor which own fft planes in 3rd dimension for fourdp
    3760              : !! ffti3_local(n3) = local i3 indices in fourdp
    3761              : !! comm_fft=MPI communicator for the FFT
    3762              : !! [fftw_flags]=Flags used to create the plan. They can be combined with the "+" operator.
    3763              : !! fin(2*ldx*ldy*ldz*ndat)=The complex array to be transformed.
    3764              : !!
    3765              : !! TODO
    3766              : !!   Add c2r and r2c version.
    3767              : !!
    3768              : !! SIDE EFFECTS
    3769              : !! Input/Output
    3770              : !! fofg(2,nfft*ndat)=f(G), complex.
    3771              : !! fofr(cplex*nfft*ndat)=input function f(r) (real or complex)
    3772              : !!
    3773              : !! SOURCE
    3774              : 
    3775              : subroutine fftw3_mpifourdp_c2c(cplex,nfft,ngfft,ndat,isign,&
    3776              :    fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local,fofg,fofr,comm_fft,fftw_flags)
    3777              : 
    3778              : !Arguments ------------------------------------
    3779              : !scalars
    3780              :  integer,intent(in) :: cplex,isign,nfft,ndat,comm_fft
    3781              :  integer,optional,intent(in) :: fftw_flags
    3782              : !arrays
    3783              :  integer,intent(in) :: ngfft(18)
    3784              :  integer,intent(in) :: fftn2_distrib(ngfft(2)),ffti2_local(ngfft(2))
    3785              :  integer,intent(in) :: fftn3_distrib(ngfft(3)),ffti3_local(ngfft(3))
    3786              :  real(dp),intent(inout) :: fofg(2,nfft*ndat),fofr(cplex*nfft*ndat)
    3787              : 
    3788              : #ifdef HAVE_FFTW3_MPI
    3789              : !Local variables-------------------------------
    3790              : !scalars
    3791              :  integer,parameter :: rank3=3
    3792              :  integer :: n1,n2,n3,n4,n5,n6,nd2proc,nd3proc,my_flags,me_fft,nproc_fft
    3793              :  integer(C_INTPTR_T) :: alloc_local,local_n0,local_0_start,local_n1,local_1_start
    3794              :  type(C_PTR) :: plan,cptr_cdata
    3795              : !arrays
    3796              :  integer(C_INTPTR_T) :: fft_sizes(4)
    3797              :  complex(C_DOUBLE_COMPLEX), contiguous, pointer :: f03_cdata(:)
    3798              : !*************************************************************************
    3799              : 
    3800              :  my_flags=ABI_FFTW_ESTIMATE; if (PRESENT(fftw_flags)) my_flags= fftw_flags
    3801              : 
    3802              :  n1=ngfft(1); n2=ngfft(2); n3=ngfft(3)
    3803              :  ! No augmentation as FFTW3 does not support it
    3804              :  n4=n1; n5=n2; n6=n3
    3805              :  me_fft=ngfft(11); nproc_fft=ngfft(10)
    3806              : 
    3807              :  nd2proc=((n2-1)/nproc_fft) +1
    3808              :  nd3proc=((n6-1)/nproc_fft) +1
    3809              : 
    3810              :  ! Get local data size and allocate (note dimension reversal, we call the C interface directly!)
    3811              :  fft_sizes = [n3,n2,n1,ndat]
    3812              : 
    3813              :  ! Use TRANSPOSED_OUT
    3814              :  my_flags = ior(ABI_FFTW_ESTIMATE, ABI_FFTW_MPI_TRANSPOSED_OUT)
    3815              : 
    3816              :  if (isign == ABI_FFTW_BACKWARD) then
    3817              :    ! G --> R, Exchange n2 and n3
    3818              :    fft_sizes = [n2,n3,n1,ndat]
    3819              :    !my_flags = ior(ABI_FFTW_ESTIMATE, ABI_FFTW_MPI_TRANSPOSED_IN)
    3820              :  end if
    3821              : 
    3822              :  alloc_local = fftw_mpi_local_size_many_transposed(&
    3823              :       rank3,fft_sizes(1:3),fft_sizes(4), &
    3824              :       FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, comm_fft, &
    3825              :       local_n0,local_0_start, &
    3826              :       local_n1,local_1_start)
    3827              : 
    3828              :  ! C to F
    3829              :  !local_0_start = local_0_start + 1
    3830              :  !local_1_start = local_1_start + 1
    3831              :  !write(std_out,*)"local_n0,local_0_start,alloc_local",local_n0,local_0_start,alloc_local
    3832              :  !write(std_out,*)"local_n1,local_1_start,alloc_local",local_n1,local_1_start,alloc_local
    3833              : 
    3834              :  ! Allocate cptr_cdata, associate to F pointer and build the plane.
    3835              :  cptr_cdata = fftw_alloc_complex(alloc_local)
    3836              : 
    3837              :  call c_f_pointer(cptr_cdata, f03_cdata, [alloc_local])
    3838              : 
    3839              :  plan = fftw_mpi_plan_many_dft(rank3,fft_sizes(1:3),fft_sizes(4), &
    3840              :                               FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
    3841              :                               f03_cdata,f03_cdata,comm_fft,isign,my_flags)
    3842              : 
    3843              :  select case (isign)
    3844              :  case (ABI_FFTW_BACKWARD)
    3845              :      ! G --> R
    3846              :      ABI_CHECK(local_n0 == nd2proc, "local_n0 != nd2proc")
    3847              : 
    3848              :      call mpifft_fg2dbox_dpc(nfft,ndat,fofg,n1,n2,n3,n4,nd2proc,n6,fftn2_distrib,ffti2_local,me_fft,f03_cdata)
    3849              : 
    3850              :      ! Compute transform.
    3851              :      call fftw_mpi_execute_dft(plan, f03_cdata, f03_cdata)
    3852              : 
    3853              :      call mpifft_dbox2fr_dpc(n1,n2,n3,n4,n5,nd3proc,ndat,fftn3_distrib,ffti3_local,me_fft,f03_cdata,cplex,nfft,fofr)
    3854              : 
    3855              :  case (ABI_FFTW_FORWARD)
    3856              :      ! R --> G
    3857              :      ABI_CHECK(local_n0 == nd3proc, "local_n0 != nd3proc")
    3858              : 
    3859              :      call mpifft_fr2dbox_dpc(cplex,nfft,ndat,fofr,n1,n2,n3,n4,n5,nd3proc,fftn3_distrib,ffti3_local,me_fft,f03_cdata)
    3860              : 
    3861              :      ! Compute transform.
    3862              :      call fftw_mpi_execute_dft(plan, f03_cdata, f03_cdata)
    3863              : 
    3864              :      ! Scale results.
    3865              :      call mpifft_dbox2fg_dpc(n1,n2,n3,n4,nd2proc,n6,ndat,fftn2_distrib,ffti2_local,me_fft,f03_cdata,nfft,fofg)
    3866              : 
    3867              :  case default
    3868              :    ABI_ERROR("Wrong sign")
    3869              :  end select
    3870              : 
    3871              :  call fftw_destroy_plan(plan)
    3872              :  call fftw_free(cptr_cdata)
    3873              : 
    3874              : #else
    3875              :  ABI_ERROR("FFTW3_MPI support not activated")
    3876              :  ABI_UNUSED((/cplex,nfft,ngfft(1),ndat,isign,comm_fft/))
    3877              :  ABI_UNUSED((/fftn2_distrib(1),ffti2_local(1)/))
    3878              :  ABI_UNUSED((/fftn3_distrib(1),ffti3_local(1)/))
    3879              :  if (PRESENT(fftw_flags)) then
    3880              :     ABI_UNUSED(fftw_flags)
    3881              :  end if
    3882              :  ABI_UNUSED(fofg(1,1))
    3883              :  ABI_UNUSED(fofr(1))
    3884              : #endif
    3885              : 
    3886              : end subroutine fftw3_mpifourdp_c2c
    3887              : !!***
    3888              : 
    3889              : !----------------------------------------------------------------------
    3890              : 
    3891              : !!****f* m_fftw3/fftw3_mpiback_wf
    3892              : !! NAME
    3893              : !!  fftw3_mpiback_wf
    3894              : !!
    3895              : !! FUNCTION
    3896              : !!   Does multiple 3-dim backward FFTs from Fourier into real space
    3897              : !!   Adopt standard convention that isign=1 for backward transform
    3898              : !!
    3899              : !!   CALCULATES THE DISCRETE FOURIER TRANSFORM ZF(I1,I2,I3)=
    3900              : !!
    3901              : !!   S_(j1,j2,j3) EXP(isign*i*2*pi*(j1*i1/n1+j2*i2/n2+j3*i3/n3)) ZF(j1,j3,j2)
    3902              : !!
    3903              : !!   in parallel using MPI/OpenMP.
    3904              : !!
    3905              : !! INPUTS:
    3906              : !!    cplexwf=1 if wavefunction is real, 2 if complex
    3907              : !!    ndat=Number of wavefunctions to transform.
    3908              : !!    n1,n2,n3: logical dimension of the transform. As transform lengths
    3909              : !!              most products of the prime factors 2,3,5 are allowed.
    3910              : !!              The detailed table with allowed transform lengths can be found in subroutine CTRIG
    3911              : !!    nd1,nd2,nd3: Leading Dimension of ZR
    3912              : !!    nd3proc=((nd3-1)/nproc_fft)+1 maximal number of big box 3rd dim slices for one proc
    3913              : !!    max1 is positive or zero; m1 >=max1+1
    3914              : !!      i1= 1... max1+1 corresponds to positive and zero wavevectors 0 ... max1
    3915              : !!      then, if m1 > max1+1, one has min1=max1-m1+1 and
    3916              : !!      i1= max1+2 ... m1 corresponds to negative wavevectors min1 ... -1
    3917              : !!    max2 and max3 have a similar definition of range
    3918              : !!    m1,m2,m3=Size of the box enclosing the G-sphere.
    3919              : !!    md1,md2,md3: Dimension of ZF given on the **small** FFT box.
    3920              : !!    md2proc=((md2-1)/nproc_fft)+1 maximal number of small box 2nd dim slices for one proc
    3921              : !!    nproc_fft: number of processors used as returned by MPI_COMM_SIZE
    3922              : !!    comm_fft=MPI communicator for the FFT.
    3923              : !!    ZF: input array (note the switch of i2 and i3)
    3924              : !!          real(F(i1,i3,i2,idat))=ZF(1,i1,i3,i2,idat)
    3925              : !!          imag(F(i1,i3,i2,idat))=ZF(2,i1,i3,i2,idat)
    3926              : !!
    3927              : !! OUTPUTS
    3928              : !!    ZR: output array
    3929              : !!          ZR(1,i1,i2,i3,idat)=real(R(i1,i2,i3,idat))
    3930              : !!          ZR(2,i1,i2,i3,idat)=imag(R(i1,i2,i3,idat))
    3931              : !!        i1=1,n1 , i2=1,n2 , i3=1,n3 , idat=1,ndat
    3932              : !!
    3933              : !! NOTES
    3934              : !!   The maximum number of processors that can reasonably be used is max(n2/2,n3/2)
    3935              : !!
    3936              : !!   It is very important to find the optimal
    3937              : !!   value of NCACHE. NCACHE determines the size of the work array ZW, that
    3938              : !!   has to fit into cache. It has therefore to be chosen to equal roughly
    3939              : !!   half the size of the physical cache in units of real*8 numbers.
    3940              : !!   The optimal value of ncache can easily be determined by numerical
    3941              : !!   experimentation. A too large value of ncache leads to a dramatic
    3942              : !!   and sudden decrease of performance, a too small value to a to a
    3943              : !!   slow and less dramatic decrease of performance. If NCACHE is set
    3944              : !!   to a value so small, that not even a single one dimensional transform
    3945              : !!   can be done in the workarray zw, the program stops with an error message.
    3946              : !!
    3947              : !! SOURCE
    3948              : 
    3949            0 : subroutine fftw3_mpiback_wf(cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc,&
    3950            0 :                             max1,max2,max3,m1,m2,m3,md1,md2proc,md3,zf,zr,comm_fft)
    3951              : 
    3952              : !Arguments ------------------------------------
    3953              :  integer,intent(in) :: cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc
    3954              :  integer,intent(in) :: max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft
    3955              :  real(dp),intent(in) :: zf(2,md1,md3,md2proc,ndat)
    3956              :  real(dp),intent(out) :: zr(2,nd1,nd2,nd3proc,ndat)
    3957              : 
    3958              : #ifdef HAVE_FFTW3
    3959              : !Local variables-------------------------------
    3960              :  integer,parameter :: nt1=1
    3961              :  integer :: j,i1,i2,idat,ierr,includelast
    3962              :  integer :: ioption,j2,j3,j2st,jp2st,jeff,lzt,m1zt,ma,mb,n1dfft,nnd3
    3963              :  integer :: lot1,lot2,lot3
    3964              :  integer :: m2eff,ncache,n1eff,n1half,nproc_fft,me_fft,nthreads
    3965              :  integer(KIND_FFTW_PLAN) :: bw_plan1_lot,bw_plan1_rest
    3966              :  integer(KIND_FFTW_PLAN) :: bw_plan2_lot,bw_plan2_rest
    3967              :  integer(KIND_FFTW_PLAN) :: bw_plan3_lot,bw_plan3_rest
    3968              :  !type(C_PTR) :: zw_cptr,zt_cptr
    3969              :  character(len=500) :: msg
    3970              : !arrays
    3971              :  real(dp),allocatable :: zmpi1(:,:,:,:),zmpi2(:,:,:,:)  ! work arrays for MPI
    3972              :  real(dp),allocatable :: zw(:,:),zt(:,:,:) ! cache work array and array for transpositions
    3973              :  !real(dp),contiguous, pointer :: zw(:,:),zt(:,:,:)
    3974              : ! FFT work arrays
    3975              :  real(dp) :: tsec(2)
    3976              : ! *************************************************************************
    3977              : 
    3978              :  !call wrtout(std_out,"mpiback standard ALLTOALL + FFTW3")
    3979              : 
    3980              :  ! FIXME must provide a default value but which one?
    3981              :  ! ioption = 0
    3982              :  ioption = 1
    3983              :  !if (paral_kgb==1) ioption=1
    3984              : 
    3985              :  nproc_fft = xmpi_comm_size(comm_fft); me_fft = xmpi_comm_rank(comm_fft)
    3986              : 
    3987              :  ! Find cache size that gives optimal performance on machine
    3988              :  ncache=2*max(n1,n2,n3,1024)
    3989              :  if (ncache/(2*max(n1,n2,n3))<1) then
    3990              :    write(msg,"(5a)") &
    3991              :     'ncache has to be enlarged to be able to hold at',ch10, &
    3992              :     'least one 1-d FFT of each size even though this will',ch10,&
    3993              :     'reduce the performance for shorter transform lengths'
    3994              :     ABI_ERROR(msg)
    3995              :  end if
    3996              : 
    3997              :  ! Effective m1 and m2 (complex-to-complex or real-to-complex)
    3998              :  n1eff=n1; m2eff=m2; m1zt=n1
    3999              :  if (cplexwf==1) then
    4000              :    n1eff=(n1+1)/2; m2eff=m2/2+1; m1zt=2*(n1/2+1)
    4001              :  end if
    4002              : 
    4003              :  lzt=m2eff
    4004              :  if (mod(m2eff,2)==0) lzt=lzt+1
    4005              :  if (mod(m2eff,4)==0) lzt=lzt+1
    4006              : 
    4007              :  ! maximal number of big box 3rd dim slices for all procs
    4008              :  nnd3=nd3proc*nproc_fft
    4009              : 
    4010              :  ! Allocate cache work array and work arrays for MPI transpositions.
    4011              :  ABI_MALLOC(zw,(2,ncache/2))
    4012              :  ABI_MALLOC(zt,(2,lzt,m1zt))
    4013              : 
    4014              :  !call fftw3_alloc_real([2,ncache/2],zw_cptr,zw)
    4015              :  !call fftw3_alloc_real([2,lzt,m1zt],zt_cptr,zt)
    4016              : 
    4017              :  ABI_MALLOC(zmpi2,(2,md1,md2proc,nnd3))
    4018              :  if (nproc_fft>1)  then
    4019              :    ABI_MALLOC(zmpi1,(2,md1,md2proc,nnd3))
    4020              :  end if
    4021              : 
    4022              : !DEBUG
    4023              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),': fftw3_mpiback_wf,zf n1,n2,n3',n1,n2,n3
    4024              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),': nd1,nd2,nd3proc',nd1,nd2,nd3proc
    4025              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),': m1,m2,m3',m1,m2,m3
    4026              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),': max1,max2,max3',max1,max2,max3
    4027              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),': md1,md2proc,md3',md1,md2proc,md3
    4028              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),'n1eff,m2eff,m1zt',n1eff,m2eff,m1zt
    4029              : !ENDDEBUG
    4030              : 
    4031              :  ! Create plans.
    4032              :  ! The prototype for sfftw_plan_many_dft is:
    4033              :  ! sfftw_plan_many_dft(rank, n, howmany,
    4034              :  !   fin,  iembed, istride, idist,
    4035              :  !   fout, oembed, ostride, odist, isign, my_flags)
    4036              : 
    4037              :  lot3=ncache/(2*n3)
    4038              :  lot1=ncache/(2*n1)
    4039              :  lot2=ncache/(2*n2)
    4040              : 
    4041              :  nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
    4042              :  !nthreads = 1
    4043              : 
    4044              :  bw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    4045              :     zw, [ncache/2], lot3, 1,                          &
    4046              :     zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4047              : 
    4048              :  if (mod(m1, lot3) /= 0) then
    4049              :    bw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(m1, lot3), &
    4050              :       zw, [ncache/2], lot3, 1,                                    &
    4051              :       zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4052              :  end if
    4053              : 
    4054              :  bw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1, &
    4055              :     zw, [ncache/2],  lot1, 1,                         &
    4056              :     zt, [lzt, m1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4057              : 
    4058              :  if (mod(m2eff, lot1) /= 0) then
    4059              :    bw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(m2eff, lot1), &
    4060              :       zw, [ncache/2],  lot1, 1,                                      &
    4061              :       zt, [lzt, m1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4062              :  end if
    4063              : 
    4064              :  bw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2, &
    4065              :     zw, [ncache/2], lot2, 1,                          &
    4066              :     zr, [nd1,nd2,nd3proc,ndat], nd1, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4067              : 
    4068              :  if (mod(n1eff, lot2) /= 0) then
    4069              :    bw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2), &
    4070              :       zw, [ncache/2], lot2, 1,                                      &
    4071              :       zr, [nd1,nd2,nd3proc,ndat], nd1, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4072              :  end if
    4073              : 
    4074              :  do idat=1,ndat
    4075              :     ! transform along z axis
    4076              :     ! input: G1,G3,G2,(Gp2)
    4077              : 
    4078              :     ! Loop over the y planes treated by this node and transform n1ddft G_z lines.
    4079              :     do j2=1,md2proc
    4080              :       ! if (me_fft*md2proc+j2<=m2eff) then !a faire plus tard
    4081              :       do i1=1,m1,lot3
    4082              :         ma=i1
    4083              :         mb=min(i1+(lot3-1),m1)
    4084              :         n1dfft=mb-ma+1
    4085              : 
    4086              :         ! zero-pad n1dfft G_z lines
    4087              :         ! input:  G1,G3,G2,(Gp2)
    4088              :         ! output: G1,R3,G2,(Gp2)
    4089              :         call fill_cent(md1,md3,lot3,n1dfft,max3,m3,n3,zf(1,i1,1,j2,idat),zw)
    4090              : 
    4091              :         ! Transform along z.
    4092              :         if (n1dfft == lot3) then
    4093              :           call dfftw_execute_dft(bw_plan3_lot, zw, zw)
    4094              :         else
    4095              :           call dfftw_execute_dft(bw_plan3_rest, zw, zw)
    4096              :         end if
    4097              : 
    4098              :         ! Local rotation.
    4099              :         ! input:  G1,R3,G2,(Gp2)
    4100              :         ! output: G1,G2,R3,(Gp2)
    4101              :         call scramble(i1,j2,lot3,n1dfft,md1,n3,md2proc,nnd3,zw,zmpi2)
    4102              :       end do
    4103              :     end do ! j2
    4104              : 
    4105              :     ! Interprocessor data transposition
    4106              :     ! input:  G1,G2,R3,Rp3,(Gp2)
    4107              :     ! output: G1,G2,R3,Gp2,(Rp3)
    4108              :     if (nproc_fft>1) then
    4109              :       call timab(543,1,tsec)
    4110              :       call xmpi_alltoall(zmpi2,2*md1*md2proc*nd3proc, &
    4111              :                         zmpi1,2*md1*md2proc*nd3proc,comm_fft,ierr)
    4112              :       call timab(543,2,tsec)
    4113              :     end if
    4114              : 
    4115              :     ! Loop over the z treated by this node.
    4116              :     do j3=1,nd3proc
    4117              :       if (me_fft*nd3proc+j3 <= n3) then
    4118              :         Jp2st=1; J2st=1
    4119              : 
    4120              :         ! Loop over G_y in the small box.
    4121              :         do j=1,m2eff,lot1
    4122              :           ma=j
    4123              :           mb=min(j+(lot1-1),m2eff)
    4124              :           n1dfft=mb-ma+1
    4125              : 
    4126              :           ! Zero-pad input.
    4127              :           ! input:  G1,G2,R3,JG2,(Rp3)
    4128              :           ! output: G2,G1,R3,JG2,(Rp3)
    4129              :           if (nproc_fft==1) then
    4130              :             call mpiswitch_cent(j3,n1dfft,Jp2st,J2st,lot1,max1,md1,m1,n1,&
    4131              :              md2proc,nd3proc,nproc_fft,ioption,zmpi2,zw,max2,m2,n2)
    4132              :           else
    4133              :             call mpiswitch_cent(j3,n1dfft,Jp2st,J2st,lot1,max1,md1,m1,n1,&
    4134              :              md2proc,nd3proc,nproc_fft,ioption,zmpi1,zw,max2,m2,n2)
    4135              :           end if
    4136              : 
    4137              :           ! Transform along x
    4138              :           ! input:  G2,G1,R3,(Rp3)
    4139              :           ! output: G2,R1,R3,(Rp3)
    4140              :           if (n1dfft == lot1) then
    4141              :             call dfftw_execute_dft(bw_plan1_lot, zw, zt(1,j,1))
    4142              :           else
    4143              :             call dfftw_execute_dft(bw_plan1_rest, zw, zt(1,j,1))
    4144              :           end if
    4145              : 
    4146              :         end do ! j
    4147              : 
    4148              :         ! Transform along y axis (take into account c2c or c2r case).
    4149              :         ! Must loop over the full box.
    4150              :         do j=1,n1eff,lot2
    4151              :           ma=j
    4152              :           mb=min(j+(lot2-1),n1eff)
    4153              :           n1dfft=mb-ma+1
    4154              :           includelast=1
    4155              : 
    4156              :           if (cplexwf==1) then
    4157              :             jeff=2*j-1
    4158              :             if (mb==n1eff .and. n1eff*2/=n1) includelast=0
    4159              :           end if
    4160              : 
    4161              :           ! Zero-pad the input.
    4162              :           ! input:  G2,R1,R3,(Rp3)
    4163              :           ! output: R1,G2,R3,(Rp3)
    4164              :           if (cplexwf==2) then
    4165              :             call switch_cent(n1dfft,max2,m2,n2,lot2,n1,lzt,zt(1,1,j),zw)
    4166              :           else
    4167              :             call switchreal_cent(includelast,n1dfft,max2,n2,lot2,m1zt,lzt,zt(1,1,jeff),zw)
    4168              :           end if
    4169              : 
    4170              :           ! input:  R1,G2,R3,(Rp3)
    4171              :           ! output: R1,R2,R3,(Rp3)
    4172              :           if (n1dfft == lot2) then
    4173              :             call dfftw_execute_dft(bw_plan2_lot, zw, zr(1,j,1,j3,idat))
    4174              :           else
    4175              :             call dfftw_execute_dft(bw_plan2_rest, zw, zr(1,j,1,j3,idat))
    4176              :           end if
    4177              : 
    4178              :         end do
    4179              : 
    4180              :         ! Treat real wavefunctions.
    4181              :         if (cplexwf==1) then
    4182              :           n1half=n1/2
    4183              :           ! If odd
    4184              :           if (n1half*2/=n1) then
    4185              :             do i2=1,n2
    4186              :               zr(1,n1,i2,j3,idat)=zr(1,n1eff,i2,j3,idat)
    4187              :               zr(2,n1,i2,j3,idat)=zero
    4188              :             end do
    4189              :           end if
    4190              :           do i2=1,n2
    4191              :             do i1=n1half,1,-1
    4192              :               zr(1,2*i1-1,i2,j3,idat)=zr(1,i1,i2,j3,idat)
    4193              :               zr(1,2*i1  ,i2,j3,idat)=zr(2,i1,i2,j3,idat)
    4194              :               zr(2,2*i1-1,i2,j3,idat)=zero
    4195              :               zr(2,2*i1  ,i2,j3,idat)=zero
    4196              :             end do
    4197              :           end do
    4198              :         end if
    4199              : 
    4200              :       end if
    4201              :    end do ! j3
    4202              :  end do ! idat
    4203              : 
    4204              :  call dfftw_destroy_plan(bw_plan3_lot)
    4205              :  if (mod(m1, lot3) /= 0) call dfftw_destroy_plan(bw_plan3_rest)
    4206              : 
    4207              :  call dfftw_destroy_plan(bw_plan1_lot)
    4208              :  if (mod(m2eff, lot1) /= 0) call dfftw_destroy_plan(bw_plan1_rest)
    4209              : 
    4210              :  call dfftw_destroy_plan(bw_plan2_lot)
    4211              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(bw_plan2_rest)
    4212              : 
    4213              :  ABI_FREE(zmpi2)
    4214              :  ABI_FREE(zw)
    4215              :  ABI_FREE(zt)
    4216              :  if (nproc_fft>1)  then
    4217              :    ABI_FREE(zmpi1)
    4218              :  end if
    4219              : 
    4220              : #else
    4221            0 :  ABI_ERROR("FFTW3 support not activated")
    4222              :  ABI_UNUSED((/cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc/))
    4223              :  ABI_UNUSED((/ max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft/))
    4224              :  ABI_UNUSED((/zf(1,1,1,1,1),zr(1,1,1,1,1)/))
    4225              : #endif
    4226              : 
    4227            0 : end subroutine fftw3_mpiback_wf
    4228              : !!***
    4229              : 
    4230              : !----------------------------------------------------------------------
    4231              : 
    4232              : !!****f* m_fftw3/fftw3_mpiforw_wf
    4233              : !! NAME
    4234              : !!  fftw3_mpiforw_wf
    4235              : !!
    4236              : !! FUNCTION
    4237              : !!   Does multiple 3-dim backward FFTs from real into Fourier space
    4238              : !!   Adopt standard convention that isign=-1 for forward transform
    4239              : !!   CALCULATES THE DISCRETE FOURIERTRANSFORM
    4240              : !!
    4241              : !!   ZF(I1,I3,I2)=S_(j1,j2,j3) EXP(isign*i*2*pi*(j1*i1/n1+j2*i2/n2+j3*i3/n3)) ZR(j1,j2,j3)
    4242              : !!
    4243              : !!   in parallel using MPI/OpenMP.
    4244              : !!
    4245              : !! INPUT:
    4246              : !!   ZR: input array
    4247              : !!        ZR(1,i1,i2,i3,idat)=real(R(i1,i2,i3,idat))
    4248              : !!        ZR(2,i1,i2,i3,idat)=imag(R(i1,i2,i3,idat))
    4249              : !!        i1=1,n1 , i2=1,n2 , i3=1,n3 , idat=1,ndat
    4250              : !!   NOTE that ZR is changed by the routine
    4251              : !!
    4252              : !!   n1,n2,n3: logical dimension of the transform. As transform lengths
    4253              : !!             most products of the prime factors 2,3,5 are allowed.
    4254              : !!             The detailed table with allowed transform lengths can
    4255              : !!             be found in subroutine CTRIG
    4256              : !!   nd1,nd2,nd3: Dimension of ZR
    4257              : !!   nd3proc=((nd3-1)/nproc_fft)+1  maximal number of big box 3rd dim slices for one proc
    4258              : !!
    4259              : !! OUTPUT:
    4260              : !!   ZF: output array (note the switch of i2 and i3)
    4261              : !!        real(F(i1,i3,i2,idat))=ZF(1,i1,i3,i2,idat)
    4262              : !!        imag(F(i1,i3,i2,idat))=ZF(2,i1,i3,i2,idat)
    4263              : !!   max1 is positive or zero ; m1 >=max1+1
    4264              : !!     i1= 1... max1+1 corresponds to positive and zero wavevectors 0 ... max1
    4265              : !!     then, if m1 > max1+1, one has min1=max1-m1+1 and
    4266              : !!     i1= max1+2 ... m1 corresponds to negative wavevectors min1 ... -1
    4267              : !!     i2 and i3 have a similar definition of range
    4268              : !!   idat=1,ndat
    4269              : !!   md1,md2,md3: Dimension of ZF
    4270              : !!   md2proc=((md2-1)/nproc_fft)+1  maximal number of small box 2nd dim slices for one proc
    4271              : !!   nproc_fft: number of processors used as returned by MPI_COMM_SIZE
    4272              : !!   me_fft: [0:nproc-1] rank of the processor in the FFT communicator.
    4273              : !!   comm_fft=MPI communicator for parallel FFT.
    4274              : !!
    4275              : !! NOTES
    4276              : !!  The maximum number of processors that can reasonably be used is max(n2/2,n3/2)
    4277              : !!
    4278              : !!  It is very important to find the optimal
    4279              : !!  value of NCACHE. NCACHE determines the size of the work array ZW, that
    4280              : !!  has to fit into cache. It has therefore to be chosen to equal roughly
    4281              : !!   half the size of the physical cache in units of real*8 numbers.
    4282              : !!  The optimal value of ncache can easily be determined by numerical
    4283              : !!  experimentation. A too large value of ncache leads to a dramatic
    4284              : !!  and sudden decrease of performance, a too small value to a to a
    4285              : !!  slow and less dramatic decrease of performance. If NCACHE is set
    4286              : !!  to a value so small, that not even a single one dimensional transform
    4287              : !!  can be done in the workarray zw, the program stops with an error message.
    4288              : !!
    4289              : !! SOURCE
    4290              : 
    4291            0 : subroutine fftw3_mpiforw_wf(cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc,&
    4292            0 : &        max1,max2,max3,m1,m2,m3,md1,md2proc,md3,zr,zf,comm_fft)
    4293              : 
    4294              : !Arguments ------------------------------------
    4295              : !scalars
    4296              :  integer,intent(in) :: cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc
    4297              :  integer,intent(in) :: max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft
    4298              : !arrays
    4299              :  real(dp),intent(inout) :: zr(2,nd1,nd2,nd3proc,ndat)
    4300              :  real(dp),intent(out) :: zf(2,md1,md3,md2proc,ndat)
    4301              : 
    4302              : !Local variables-------------------------------
    4303              : !scalars
    4304              : #ifdef HAVE_FFTW3
    4305              :  integer :: j,i1,i2,i3,idat,ierr,nproc_fft,me_fft,nthreads
    4306              :  integer :: ioption,j2,j3,j2st,jp2st,lot1,lot2,lot3,lzt,m1zt,ma,mb,n1dfft,nnd3
    4307              :  integer :: m2eff,ncache,n1eff,n1half,i1inv,i2inv,i3inv
    4308              :  integer(KIND_FFTW_PLAN) :: fw_plan1_lot,fw_plan1_rest
    4309              :  integer(KIND_FFTW_PLAN) :: fw_plan2_lot,fw_plan2_rest
    4310              :  integer(KIND_FFTW_PLAN) :: fw_plan3_lot,fw_plan3_rest
    4311              :  character(len=500) :: msg
    4312              : !arrays
    4313              :  real(dp), allocatable :: zmpi1(:,:,:,:),zmpi2(:,:,:,:) ! work arrays for MPI
    4314              :  real(dp),allocatable :: zw(:,:),zt(:,:,:) ! cache work array and array for transpositions
    4315              : ! FFT work arrays
    4316              :  real(dp) :: tsec(2)
    4317              : ! *************************************************************************
    4318              : 
    4319              :  ! FIXME must provide a default value but which one?
    4320              :  !ioption = 0
    4321              :  ioption = 1
    4322              :  !if (paral_kgb==1) ioption=1
    4323              : 
    4324              :  nproc_fft = xmpi_comm_size(comm_fft); me_fft = xmpi_comm_rank(comm_fft)
    4325              : 
    4326              :  ! find cache size that gives optimal performance on machine
    4327              :  ncache=2*max(n1,n2,n3,1024)
    4328              :  !ncache=2*max(n1,n2,n3,16*1024)
    4329              : 
    4330              :  if (ncache/(2*max(n1,n2,n3))<1) then
    4331              :    write(msg,'(5a)') &
    4332              :     'ncache has to be enlarged to be able to hold at',ch10, &
    4333              :     'least one 1-d FFT of each size even though this will',ch10,&
    4334              :     'reduce the performance for shorter transform lengths'
    4335              :    ABI_ERROR(msg)
    4336              :  end if
    4337              : 
    4338              :  ! Effective m1 and m2 (complex-to-complex or real-to-complex)
    4339              :  n1eff=n1; m2eff=m2; m1zt=n1
    4340              :  if (cplexwf==1) then
    4341              :    n1eff=(n1+1)/2; m2eff=m2/2+1; m1zt=2*(n1/2+1)
    4342              :  end if
    4343              : 
    4344              :  lzt=m2eff
    4345              :  if (mod(m2eff,2)==0) lzt=lzt+1
    4346              :  if (mod(m2eff,4)==0) lzt=lzt+1
    4347              : 
    4348              :  ! maximal number of big box 3rd dim slices for all procs
    4349              :  nnd3=nd3proc*nproc_fft
    4350              : 
    4351              :  ABI_MALLOC(zw,(2,ncache/2))
    4352              :  ABI_MALLOC(zt,(2,lzt,m1zt))
    4353              :  ABI_MALLOC(zmpi2,(2,md1,md2proc,nnd3))
    4354              :  if (nproc_fft>1)  then
    4355              :    ABI_MALLOC(zmpi1,(2,md1,md2proc,nnd3))
    4356              :  end if
    4357              : 
    4358              : !DEBUG
    4359              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),'fftw3_mpiforw_wf, enter, i1,i2,i3,zr,n1,n2,n3',n1,n2,n3
    4360              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),'nd1,nd2,nd3proc',nd1,nd2,nd3proc
    4361              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),'m1,m2,m3',m1,m2,m3
    4362              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),'max1,max2,max3',max1,max2,max3
    4363              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),'md1,md2proc,md3',md1,md2proc,md3
    4364              : ! write(std_out,'(2a,3i4)' )itoa(me_fft),'n1eff,m2eff,m1zt',n1eff,m2eff,m1zt
    4365              : !ENDDEBUG
    4366              : 
    4367              :  ! Create plans.
    4368              :  ! The prototype for sfftw_plan_many_dft is:
    4369              :  ! sfftw_plan_many_dft(rank, n, howmany,
    4370              :  !   fin,  iembed, istride, idist,
    4371              :  !   fout, oembed, ostride, odist, isign, my_flags)
    4372              : 
    4373              :  lot2=ncache/(2*n2)
    4374              :  lot1=ncache/(2*n1)
    4375              :  lot3=ncache/(2*n3)
    4376              : 
    4377              :  nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
    4378              :  !nthreads = 1
    4379              : 
    4380              :  fw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    4381              :     zw, [ncache/2], lot3, 1,                          &
    4382              :     zw, [ncache/2], lot3, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE,nthreads)
    4383              : 
    4384              :  if (mod(m1, lot3) /= 0) then
    4385              :    fw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(m1, lot3), &
    4386              :     zw, [ncache/2], lot3, 1,                                      &
    4387              :     zw, [ncache/2], lot3, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    4388              :  end if
    4389              : 
    4390              :  fw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1, &
    4391              :     zt, [lzt, m1zt],   lzt,  1,                       &
    4392              :     zw, [ncache/2], lot1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    4393              : 
    4394              :  if (mod(m2eff, lot1) /= 0) then
    4395              :    fw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(m2eff, lot1), &
    4396              :     zt, [lzt, m1zt],   lzt, 1,                                       &
    4397              :     zw, [ncache/2], lot1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    4398              :  end if
    4399              : 
    4400              :  fw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2, &
    4401              :     zr, [nd1,nd2,nd3proc,ndat], nd1, 1,               &
    4402              :     zw, [ncache/2], lot2, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    4403              : 
    4404              :  if (mod(n1eff, lot2) /= 0) then
    4405              :    fw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2), &
    4406              :     zr, [nd1,nd2,nd3proc,ndat], nd1, 1,                             &
    4407              :     zw, [ncache/2], lot2, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    4408              :  end if
    4409              : 
    4410              :  do idat=1,ndat
    4411              :    ! Loop over the z-planes treated by this node
    4412              :    do j3=1,nd3proc
    4413              : 
    4414              :      if (me_fft*nd3proc+j3 <= n3) then
    4415              :        Jp2st=1
    4416              :        J2st=1
    4417              : 
    4418              :        ! Treat real wavefunctions.
    4419              :        if (cplexwf==1) then
    4420              :          n1half=n1/2
    4421              :          do i2=1,n2
    4422              :            do i1=1,n1half
    4423              :              zr(1,i1,i2,j3,idat)=zr(1,2*i1-1,i2,j3,idat)
    4424              :              zr(2,i1,i2,j3,idat)=zr(1,2*i1  ,i2,j3,idat)
    4425              :            end do
    4426              :          end do
    4427              :          ! If odd
    4428              :          if(n1half*2/=n1)then
    4429              :            do i2=1,n2
    4430              :              zr(1,n1eff,i2,j3,idat)=zr(1,n1,i2,j3,idat)
    4431              :              zr(2,n1eff,i2,j3,idat)=zero
    4432              :            end do
    4433              :          end if
    4434              :        end if
    4435              : 
    4436              :        ! transform along y axis
    4437              :        ! input: R1,R2,R3,(Rp3)
    4438              :        ! input: R1,G2,R3,(Rp3)
    4439              :        do j=1,n1eff,lot2
    4440              :          ma=j
    4441              :          mb=min(j+(lot2-1),n1eff)
    4442              :          n1dfft=mb-ma+1
    4443              : 
    4444              :          if (n1dfft == lot2) then
    4445              :            call dfftw_execute_dft(fw_plan2_lot,  zr(1,j,1,j3,idat), zw)
    4446              :          else
    4447              :            call dfftw_execute_dft(fw_plan2_rest, zr(1,j,1,j3,idat), zw)
    4448              :          end if
    4449              : 
    4450              :          ! input:  R1,G2,R3,(Rp3)
    4451              :          ! output: G2,R1,R3,(Rp3)
    4452              :          if (cplexwf==2) then
    4453              :            call unswitch_cent(n1dfft,max2,m2,n2,lot2,n1,lzt,zw,zt(1,1,j))
    4454              :          else
    4455              :            call unswitchreal_cent(n1dfft,max2,n2,lot2,n1,lzt,zw,zt(1,1,2*j-1))
    4456              :          end if
    4457              :        end do
    4458              : 
    4459              :        ! transform along x axis
    4460              :        ! input: G2,R1,R3,(Rp3)
    4461              :        do j=1,m2eff,lot1
    4462              :          ma=j
    4463              :          mb=min(j+(lot1-1),m2eff)
    4464              :          n1dfft=mb-ma+1
    4465              : 
    4466              :          if (n1dfft == lot1) then
    4467              :            call dfftw_execute_dft(fw_plan1_lot,  zt(1,j,1), zw)
    4468              :          else
    4469              :            call dfftw_execute_dft(fw_plan1_rest, zt(1,j,1), zw)
    4470              :          end if
    4471              :          ! output: G2,G1,R3,(Rp3)
    4472              : 
    4473              :          ! input:  G2,G1,R3,Gp2,(Rp3)
    4474              :          ! output: G1,G2,R3,Gp2,(Rp3)
    4475              :          if (nproc_fft==1) then
    4476              :            call unmpiswitch_cent(j3,n1dfft,Jp2st,J2st,lot1,max1,md1,m1,n1,&
    4477              :             md2proc,nd3proc,nproc_fft,ioption,zw,zmpi2)
    4478              :          else
    4479              :            call unmpiswitch_cent(j3,n1dfft,Jp2st,J2st,lot1,max1,md1,m1,n1,&
    4480              :             md2proc,nd3proc,nproc_fft,ioption,zw,zmpi1)
    4481              :          end if
    4482              :        end do
    4483              : 
    4484              :       end if
    4485              :     end do ! j3
    4486              : 
    4487              :     ! Interprocessor data transposition
    4488              :     ! input:  G1,G2,R3,Gp2,(Rp3)
    4489              :     ! output: G1,G2,R3,Rp3,(Gp2)
    4490              :     if (nproc_fft>1) then
    4491              :       call timab(544,1,tsec)
    4492              :       call xmpi_alltoall(zmpi1,2*md1*md2proc*nd3proc, &
    4493              :                         zmpi2,2*md1*md2proc*nd3proc,comm_fft,ierr)
    4494              :       call timab(544,2,tsec)
    4495              :     end if
    4496              : 
    4497              :     ! transform along z axis
    4498              :     ! input: G1,G2,R3,(Gp2)
    4499              : 
    4500              :     do j2=1,md2proc
    4501              :       if (me_fft*md2proc+j2 <= m2eff) then
    4502              :         ! write(std_out,*)' forwf_wf : before unscramble, j2,md2proc,me_fft,m2=',j2,md2proc,me_fft,m2
    4503              :         do i1=1,m1,lot3
    4504              :           ma=i1
    4505              :           mb=min(i1+(lot3-1),m1)
    4506              :           n1dfft=mb-ma+1
    4507              : 
    4508              :           ! input:  G1,G2,R3,(Gp2)
    4509              :           ! output: G1,R3,G2,(Gp2)
    4510              :           call unscramble(i1,j2,lot3,n1dfft,md1,n3,md2proc,nnd3,zmpi2,zw)
    4511              : 
    4512              :           if (n1dfft == lot3) then
    4513              :             call dfftw_execute_dft(fw_plan3_lot, zw, zw)
    4514              :           else
    4515              :             call dfftw_execute_dft(fw_plan3_rest, zw, zw)
    4516              :           end if
    4517              : 
    4518              :           call unfill_cent(md1,md3,lot3,n1dfft,max3,m3,n3,zw,zf(1,i1,1,j2,idat))
    4519              :           ! output: G1,G3,G2,(Gp2)
    4520              :         end do
    4521              :       end if
    4522              :     end do
    4523              : 
    4524              :     if (cplexwf==1) then
    4525              :       ! Complete missing values with complex conjugate
    4526              :       ! Inverse of ix is located at nx+2-ix , except for ix=1, for which it is 1.
    4527              :       do i3=1,m3
    4528              :         i3inv=m3+2-i3
    4529              :         if(i3==1)i3inv=1
    4530              : 
    4531              :         if (m2eff>1) then
    4532              :           do i2=2,m2eff
    4533              :             i2inv=m2+2-i2
    4534              :             zf(1,1,i3inv,i2inv,idat)= zf(1,1,i3,i2,idat)
    4535              :             zf(2,1,i3inv,i2inv,idat)=-zf(2,1,i3,i2,idat)
    4536              :             do i1=2,m1
    4537              :               i1inv=m1+2-i1
    4538              :               zf(1,i1inv,i3inv,i2inv,idat)= zf(1,i1,i3,i2,idat)
    4539              :               zf(2,i1inv,i3inv,i2inv,idat)=-zf(2,i1,i3,i2,idat)
    4540              :             end do
    4541              :           end do
    4542              :         end if
    4543              :       end do
    4544              :     end if
    4545              : 
    4546              :  end do ! idat
    4547              : 
    4548              :  call dfftw_destroy_plan(fw_plan3_lot)
    4549              :  if (mod(m1, lot3) /= 0) call dfftw_destroy_plan(fw_plan3_rest)
    4550              : 
    4551              :  call dfftw_destroy_plan(fw_plan1_lot)
    4552              :  if (mod(m2eff, lot1) /= 0) call dfftw_destroy_plan(fw_plan1_rest)
    4553              : 
    4554              :  call dfftw_destroy_plan(fw_plan2_lot)
    4555              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(fw_plan2_rest)
    4556              : 
    4557              :  ABI_FREE(zmpi2)
    4558              :  ABI_FREE(zw)
    4559              :  ABI_FREE(zt)
    4560              :  if (nproc_fft>1)  then
    4561              :    ABI_FREE(zmpi1)
    4562              :  end if
    4563              : 
    4564              : #else
    4565            0 :  ABI_ERROR("FFTW3 support not activated")
    4566              :  ABI_UNUSED((/cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc/))
    4567              :  ABI_UNUSED((/max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft/))
    4568              :  ABI_UNUSED((/zf(1,1,1,1,1),zr(1,1,1,1,1)/))
    4569              : #endif
    4570              : 
    4571            0 : end subroutine fftw3_mpiforw_wf
    4572              : !!***
    4573              : 
    4574              : !----------------------------------------------------------------------
    4575              : 
    4576              : !!****f* m_fftw3/fftw3_mpiback
    4577              : !! NAME
    4578              : !!  fftw3_mpiback
    4579              : !!
    4580              : !! FUNCTION
    4581              : !!   CALCULATES THE DISCRETE FOURIER TRANSFORM  in parallel using MPI/OpenMP
    4582              : !!
    4583              : !!   ZR(I1,I2,I3)= \sum_(j1,j2,j3) EXP(isign*i*2*pi*(j1*i1/n1+j2*i2/n2+j3*i3/n3)) ZF(j1,j3,j2)
    4584              : !!
    4585              : !! Adopt standard convention that isign=1 for backward transform
    4586              : !!
    4587              : !! INPUTS:
    4588              : !!    option= 1 if call from fourwf, 2 if call from other routine
    4589              : !!    cplex=1 for real --> complex, 2 for complex --> complex
    4590              : !!    ZF: input array in G-space (note the switch of i2 and i3)
    4591              : !!
    4592              : !!         real(F(i1,i3,i2,idat))=ZF(1,i1,i3,i2,idat)
    4593              : !!         imag(F(i1,i3,i2,idat))=ZF(2,i1,i3,i2,idat)
    4594              : !!
    4595              : !!         i1=1,n1 , i2=1,n2 , i3=1,n3 , idat=1,ndat
    4596              : !! OUTPUTS:
    4597              : !!    ZR: output array in R space.
    4598              : !!
    4599              : !!         ZR(1,i1,i2,i3,idat)=real(R(i1,i2,i3,idat))
    4600              : !!         ZR(2,i1,i2,i3,idat)=imag(R(i1,i2,i3,idat))
    4601              : !!
    4602              : !!         i1=1,n1 , i2=1,n2 , i3=1,n3 , idat=1,ndat
    4603              : !!
    4604              : !!    nproc_fft: number of processors used as returned by MPI_COMM_SIZE
    4605              : !!    me_fft: [0:nproc_fft-1] number of processor as returned by MPI_COMM_RANK
    4606              : !!    n1,n2,n3: logical dimension of the transform. As transform lengths
    4607              : !!              most products of the prime factors 2,3,5 are allowed.
    4608              : !!              The detailed table with allowed transform lengths can
    4609              : !!              be found in subroutine CTRIG
    4610              : !!    nd1,nd2,nd3: Dimension of ZF and ZR
    4611              : !!    nd2proc=((nd2-1)/nproc_fft)+1 maximal number of 2nd dim slices
    4612              : !!    nd3proc=((nd3-1)/nproc_fft)+1 maximal number of 3rd dim slices
    4613              : !!
    4614              : !! NOTES:
    4615              : !!   The maximum number of processors that can reasonably be used is max(n2,n3)
    4616              : !!   It is very important to find the optimal
    4617              : !!   value of NCACHE. NCACHE determines the size of the work array ZW, that
    4618              : !!   has to fit into cache. It has therefore to be chosen to equal roughly
    4619              : !!    half the size of the physical cache in units of real*8 numbers.
    4620              : !!   The optimal value of ncache can easily be determined by numerical
    4621              : !!   experimentation. A too large value of ncache leads to a dramatic
    4622              : !!   and sudden decrease of performance, a too small value to a to a
    4623              : !!   slow and less dramatic decrease of performance. If NCACHE is set
    4624              : !!   to a value so small, that not even a single one dimensional transform
    4625              : !!   can be done in the workarray zw, the program stops with an error message.
    4626              : !!
    4627              : !! SOURCE
    4628              : 
    4629            0 : subroutine fftw3_mpiback(cplex,ndat,n1,n2,n3,nd1,nd2,nd3,nd1eff,nd2proc,nd3proc,option,zf,zr,comm_fft)
    4630              : 
    4631              : !Arguments ------------------------------------
    4632              : ! real space input
    4633              :  integer,intent(in) :: cplex,ndat,n1,n2,n3,nd1,nd2,nd3,nd1eff,nd2proc,nd3proc,option,comm_fft
    4634              :  real(dp),intent(in) :: zf(2,nd1,nd3,nd2proc,ndat)
    4635              :  real(dp),intent(out) :: zr(2,nd1eff,nd2,nd3proc,ndat)
    4636              : 
    4637              : !Local variables-------------------------------
    4638              : !scalaras
    4639              : #ifdef HAVE_FFTW3
    4640              :  integer :: j,i1,idat,ierr,includelast,j2,j2st,j3,jeff,jp2st,lzt,nthreads
    4641              :  integer :: ma,mb,n1dfft,n1eff,n2eff,n1zt,ncache,nnd3,nproc_fft,me_fft,lot1,lot2,lot3
    4642              :  integer(KIND_FFTW_PLAN) :: bw_plan1_lot,bw_plan1_rest
    4643              :  integer(KIND_FFTW_PLAN) :: bw_plan2_lot,bw_plan2_rest
    4644              :  integer(KIND_FFTW_PLAN) :: bw_plan3_lot,bw_plan3_rest
    4645              :  character(len=500) :: msg
    4646              : !arrays
    4647              :  real(dp), allocatable :: zmpi1(:,:,:,:),zmpi2(:,:,:,:) ! work arrays for MPI
    4648              :  real(dp),allocatable :: zw(:,:),zt(:,:,:) ! cache work array and array for transpositions
    4649              : ! *************************************************************************
    4650              : 
    4651              :  nproc_fft = xmpi_comm_size(comm_fft); me_fft = xmpi_comm_rank(comm_fft)
    4652              : 
    4653              :  ! find cache size that gives optimal performance on machine
    4654              :  ncache=2*max(n1,n2,n3,1024)
    4655              : 
    4656              :  if (ncache/(2*max(n1,n2,n3))<1) then
    4657              :    write(msg,'(5a)') &
    4658              :     'ncache has to be enlarged to be able to hold at',ch10, &
    4659              :     'least one 1-d FFT of each size even though this will',ch10,&
    4660              :     'reduce the performance for shorter transform lengths'
    4661              :    ABI_ERROR(msg)
    4662              :  end if
    4663              : 
    4664              : ! check input
    4665              :  if (nd1<n1 .or. nd2<n2 .or. nd3<n3) then
    4666              :    ABI_ERROR("nd1<n1 .or. nd2<n2 .or. nd3<n3")
    4667              :  end if
    4668              : 
    4669              :  ! Effective n1 and n2 (complex-to-complex or real-to-complex)
    4670              :  n1eff=n1; n2eff=n2; n1zt=n1
    4671              :  if (cplex==1) then
    4672              :    n1eff=(n1+1)/2; n2eff=n2/2+1 ; n1zt=2*(n1/2+1)
    4673              :  end if
    4674              : 
    4675              :  lzt=n2eff
    4676              :  if (mod(n2eff,2) == 0) lzt=lzt+1
    4677              :  if (mod(n2eff,4) == 0) lzt=lzt+1
    4678              : 
    4679              : ! maximal number of big box 3rd dim slices for all procs
    4680              :  nnd3=nd3proc*nproc_fft
    4681              : 
    4682              :  ABI_MALLOC(zw,(2,ncache/2))
    4683              :  ABI_MALLOC(zt,(2,lzt,n1zt))
    4684              :  ABI_MALLOC(zmpi2,(2,n1,nd2proc,nnd3))
    4685              :  if (nproc_fft>1)  then
    4686              :    ABI_MALLOC(zmpi1,(2,n1,nd2proc,nnd3))
    4687              :  end if
    4688              : 
    4689              : !DEBUG
    4690              : ! write(std_out,'(a,3i4)' )'back,zf n1,n2,n3',n1,n2,n3
    4691              : ! write(std_out,'(a,3i4)' )'nd1,nd2,nd3proc',nd1,nd2,nd3proc
    4692              : ! write(std_out,'(a,3i4)' )'m1,m2,m3',m1,m2,m3
    4693              : ! write(std_out,'(a,3i4)' )'max1,max2,max3',max1,max2,max3
    4694              : ! write(std_out,'(a,3i4)' )'md1,md2proc,md3',md1,md2proc,md3
    4695              : ! write(std_out,'(a,3i4)' )'n1eff,m2eff,m1zt',n1eff,m2eff,m1zt
    4696              : !ENDDEBUG
    4697              : 
    4698              :  ! Create plans.
    4699              :  ! The prototype for sfftw_plan_many_dft is:
    4700              :  ! sfftw_plan_many_dft(rank, n, howmany,
    4701              :  !   fin,  iembed, istride, idist,
    4702              :  !   fout, oembed, ostride, odist, isign, my_flags)
    4703              : 
    4704              :  lot3=ncache/(2*n3)
    4705              :  lot1=ncache/(2*n1)
    4706              :  lot2=ncache/(2*n2)
    4707              : 
    4708              :  nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
    4709              :  !nthreads = 1
    4710              : 
    4711              :  bw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    4712              :     zw, [ncache/2], lot3, 1,                          &
    4713              :     zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4714              : 
    4715              :  if (mod(n1, lot3) /= 0) then
    4716              :    bw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(n1, lot3), &
    4717              :       zw, [ncache/2], lot3, 1,                                    &
    4718              :       zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4719              :  end if
    4720              : 
    4721              :  bw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1, &
    4722              :     zw, [ncache/2],  lot1, 1,                         &
    4723              :     zt, [lzt, n1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4724              : 
    4725              :  if (mod(n2eff, lot1) /= 0) then
    4726              :    bw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(n2eff, lot1), &
    4727              :       zw, [ncache/2], lot1, 1,                                       &
    4728              :       zt, [lzt, n1zt],   lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4729              :  end if
    4730              : 
    4731              :  bw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2, &
    4732              :     zw, [ncache/2], lot2, 1,                          &
    4733              :     zr, [nd1eff,nd2,nd3proc,ndat], nd1eff, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4734              : 
    4735              :  if (mod(n1eff, lot2) /= 0) then
    4736              :    bw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2), &
    4737              :       zw, [ncache/2], lot2, 1,                                      &
    4738              :       zr, [nd1eff,nd2,nd3proc,ndat], nd1eff, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    4739              :  end if
    4740              : 
    4741              :  do idat=1,ndat
    4742              :    ! transform along z axis
    4743              :    ! input: I1,I3,J2,(Jp2)
    4744              : 
    4745              :    do j2=1,nd2proc
    4746              :      if (me_fft*nd2proc+j2 <= n2eff) then
    4747              : 
    4748              :        do i1=1,n1,lot3
    4749              :          ma=i1
    4750              :          mb=min(i1+(lot3-1),n1)
    4751              :          n1dfft=mb-ma+1
    4752              : 
    4753              :          ! input:  G1,G3,G2,(Gp2)
    4754              :          ! output: G1,R3,G2,(Gp2)
    4755              :          call fill(nd1,nd3,lot3,n1dfft,n3,zf(1,i1,1,j2,idat),zw)
    4756              : 
    4757              :          if (n1dfft == lot3) then
    4758              :            call dfftw_execute_dft(bw_plan3_lot, zw, zw)
    4759              :          else
    4760              :            call dfftw_execute_dft(bw_plan3_rest, zw, zw)
    4761              :          end if
    4762              : 
    4763              :          ! input:  G1,R3,G2,(Gp2)
    4764              :          ! output: G1,G2,R3,(Gp2)
    4765              :          call scramble(i1,j2,lot3,n1dfft,n1,n3,nd2proc,nd3,zw,zmpi2)
    4766              :        end do
    4767              :      end if
    4768              :    end do
    4769              : 
    4770              :    ! Interprocessor data transposition
    4771              :    ! input:  G1,G2,R3,Rp3,(Gp2)
    4772              :    ! output: G1,G2,G3,Gp2,(Rp3)
    4773              :    if (nproc_fft>1) then
    4774              :      call xmpi_alltoall(zmpi2,2*n1*nd2proc*nd3proc, &
    4775              :                        zmpi1,2*n1*nd2proc*nd3proc,comm_fft,ierr)
    4776              :    end if
    4777              : 
    4778              :    do j3=1,nd3proc
    4779              :      if (me_fft*nd3proc+j3 <= n3) then
    4780              :        Jp2st=1; J2st=1
    4781              : 
    4782              :        ! transform along x axis
    4783              :        do j=1,n2eff,lot1
    4784              :          ma=j
    4785              :          mb=min(j+(lot1-1),n2eff)
    4786              :          n1dfft=mb-ma+1
    4787              : 
    4788              :          ! input:  G1,G2,R3,Gp2,(Rp3)
    4789              :          ! output: G2,G1,R3,Jp2,(Rp3)
    4790              :          if (nproc_fft == 1) then
    4791              :            call mpiswitch(j3,n1dfft,Jp2st,J2st,lot1,n1,nd2proc,nd3proc,nproc_fft,option,zmpi2,zw)
    4792              :          else
    4793              :            call mpiswitch(j3,n1dfft,Jp2st,J2st,lot1,n1,nd2proc,nd3proc,nproc_fft,option,zmpi1,zw)
    4794              :          end if
    4795              : 
    4796              :          ! input:  G2,G1,R3,(Rp3)
    4797              :          ! output: G2,R1,R3,(Rp3)
    4798              :          if (n1dfft == lot1) then
    4799              :            call dfftw_execute_dft(bw_plan1_lot, zw, zt(1,j,1))
    4800              :          else
    4801              :            call dfftw_execute_dft(bw_plan1_rest, zw, zt(1,j,1))
    4802              :          end if
    4803              : 
    4804              :        end do
    4805              : 
    4806              :        ! transform along y axis
    4807              :        do j=1,n1eff,lot2
    4808              :          ma=j
    4809              :          mb=min(j+(lot2-1),n1eff)
    4810              :          n1dfft=mb-ma+1
    4811              :          includelast=1
    4812              :          if (cplex==1) then
    4813              :           jeff=2*j-1
    4814              :           includelast=1
    4815              :           if (mb==n1eff .and. n1eff*2/=n1) includelast=0
    4816              :          end if
    4817              : 
    4818              :          ! input:  G2,R1,R3,(Rp3)
    4819              :          ! output: R1,G2,R3,(Rp3)
    4820              :          if (cplex==2) then
    4821              :            call switch(n1dfft,n2,lot2,n1,lzt,zt(1,1,j),zw)
    4822              :          else
    4823              :            call switchreal(includelast,n1dfft,n2,n2eff,lot2,n1zt,lzt,zt(1,1,jeff),zw)
    4824              :          end if
    4825              : 
    4826              :          if (n1dfft == lot2) then
    4827              :            call dfftw_execute_dft(bw_plan2_lot, zw, zr(1,j,1,j3,idat))
    4828              :          else
    4829              :            call dfftw_execute_dft(bw_plan2_rest, zw, zr(1,j,1,j3,idat))
    4830              :          end if
    4831              :        end do
    4832              :        ! output: R1,R2,R3,(Rp3)
    4833              : 
    4834              :      end if
    4835              :    end do
    4836              :  end do ! idat
    4837              : 
    4838              :  call dfftw_destroy_plan(bw_plan3_lot)
    4839              :  if (mod(n1, lot3) /= 0) call dfftw_destroy_plan(bw_plan3_rest)
    4840              : 
    4841              :  call dfftw_destroy_plan(bw_plan1_lot)
    4842              :  if (mod(n2eff, lot1) /= 0) call dfftw_destroy_plan(bw_plan1_rest)
    4843              : 
    4844              :  call dfftw_destroy_plan(bw_plan2_lot)
    4845              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(bw_plan2_rest)
    4846              : 
    4847              :  ABI_FREE(zmpi2)
    4848              :  ABI_FREE(zw)
    4849              :  ABI_FREE(zt)
    4850              :  if (nproc_fft>1)  then
    4851              :    ABI_FREE(zmpi1)
    4852              :  end if
    4853              : 
    4854              : #else
    4855            0 :  ABI_ERROR("FFTW3 support not activated")
    4856              :  ABI_UNUSED((/cplex,ndat,n1,n2,n3,nd1,nd2,nd1eff,nd2proc,nd3proc,option,comm_fft/))
    4857              :  ABI_UNUSED((/zf(1,1,1,1,1),zr(1,1,1,1,1)/))
    4858              : #endif
    4859              : 
    4860            0 : end subroutine fftw3_mpiback
    4861              : !!***
    4862              : 
    4863              : !----------------------------------------------------------------------
    4864              : 
    4865              : !!****f* m_fftw3/fftw3_mpiforw
    4866              : !! NAME
    4867              : !!  fftw3_mpiforw
    4868              : !!
    4869              : !! FUNCTION
    4870              : !!   Adopt standard convention that isign=-1 for forward transform
    4871              : !!   CALCULATES THE DISCRETE FOURIERTRANSFORM ZF(I1,I3,I2)=
    4872              : !!   S_(j1,j2,j3) EXP(isign*i*2*pi*(j1*i1/n1+j2*i2/n2+j3*i3/n3)) ZR(j1,j2,j3)
    4873              : !!   in parallel using MPI/OpenMP and BLAS library calls.
    4874              : !!
    4875              : !! INPUTS
    4876              : !!    ZR: input array
    4877              : !!         ZR(1,i1,i2,i3,idat)=real(R(i1,i2,i3,idat))
    4878              : !!         ZR(2,i1,i2,i3,idat)=imag(R(i1,i2,i3,idat))
    4879              : !!         i1=1,n1 , i2=1,n2 , i3=1,n3 , idat=1,ndat
    4880              : !! OUTPUTS
    4881              : !!    ZF: output array (note the switch of i2 and i3)
    4882              : !!         real(F(i1,i3,i2,idat))=ZF(1,i1,i3,i2,idat)
    4883              : !!         imag(F(i1,i3,i2,idat))=ZF(2,i1,i3,i2,idat)
    4884              : !!         i1=1,n1 , i2=1,n2 , i3=1,n3 , idat=1,ndat
    4885              : !!    nproc_fft: number of processors used as returned by MPI_COMM_SIZE
    4886              : !!    me_fft: [0:nproc_fft-1] number of processor as returned by MPI_COMM_RANK
    4887              : !!     n1,n2,n3: logical dimension of the transform. As transform lengths
    4888              : !!               most products of the prime factors 2,3,5 are allowed.
    4889              : !!              The detailed table with allowed transform lengths can
    4890              : !!              be found in subroutine CTRIG
    4891              : !!     nd1,nd2,nd3: Dimension of ZR and ZF
    4892              : !!    nd2proc=((nd2-1)/nproc_fft)+1 maximal number of 2nd dim slices
    4893              : !!    nd3proc=((nd3-1)/nproc_fft)+1 maximal number of 3rd dim slices
    4894              : !!
    4895              : !! NOTES
    4896              : !!  SHOULD describe nd1eff
    4897              : !!  SHOULD put cplex and nd1eff in OMP declarations
    4898              : !!  SHOULD describe the change of value of nd2prod
    4899              : !!
    4900              : !!  The maximum number of processors that can reasonably be used is max(n2,n3)
    4901              : !!
    4902              : !!  It is very important to find the optimal
    4903              : !!  value of NCACHE. NCACHE determines the size of the work array ZW, that
    4904              : !!  has to fit into cache. It has therefore to be chosen to equal roughly
    4905              : !!   half the size of the physical cache in units of real*8 numbers.
    4906              : !!  The optimal value of ncache can easily be determined by numerical
    4907              : !!  experimentation. A too large value of ncache leads to a dramatic
    4908              : !!  and sudden decrease of performance, a too small value to a to a
    4909              : !!  slow and less dramatic decrease of performance. If NCACHE is set
    4910              : !!  to a value so small, that not even a single one dimensional transform
    4911              : !!  can be done in the workarray zw, the program stops with an error message.
    4912              : !!
    4913              : !! SOURCE
    4914              : 
    4915            0 : subroutine fftw3_mpiforw(cplex,ndat,n1,n2,n3,nd1,nd2,nd3,nd1eff,nd2proc,nd3proc,option,zr,zf,comm_fft)
    4916              : 
    4917              : !Arguments ------------------------------------
    4918              : !scalars
    4919              :  integer,intent(in) :: cplex,comm_fft
    4920              :  integer,intent(in) :: ndat,n1,n2,n3,nd1,nd2,nd3,nd1eff,nd2proc,nd3proc,option
    4921              : !arrays
    4922              :  real(dp),intent(in) :: zr(2,nd1eff,nd2,nd3proc,ndat)
    4923              :  real(dp),intent(out) :: zf(2,nd1,nd3,nd2proc,ndat)
    4924              : 
    4925              : !Local variables-------------------------------
    4926              : !scalars
    4927              : #ifdef HAVE_FFTW3
    4928              :  integer :: j,i1,idat,ierr,j2,j2st,j3,jp2st,lzt,nthreads
    4929              :  integer :: ma,mb,n1dfft,n1eff,n2eff,n1zt,ncache,nnd3,nproc_fft,me_fft,lot1,lot2,lot3
    4930              :  integer(KIND_FFTW_PLAN) :: fw_plan1_lot,fw_plan1_rest
    4931              :  integer(KIND_FFTW_PLAN) :: fw_plan2_lot,fw_plan2_rest
    4932              :  integer(KIND_FFTW_PLAN) :: fw_plan3_lot,fw_plan3_rest
    4933              :  character(len=500) :: msg
    4934              : !arrays
    4935              :  real(dp), allocatable :: zmpi1(:,:,:,:),zmpi2(:,:,:,:) ! work arrays for MPI
    4936              :  real(dp),allocatable :: zw(:,:),zt(:,:,:) ! cache work array and array for transpositions
    4937              : ! *************************************************************************
    4938              : 
    4939              :  nproc_fft = xmpi_comm_size(comm_fft); me_fft = xmpi_comm_rank(comm_fft)
    4940              : 
    4941              :  ! find cache size that gives optimal performance on machine
    4942              :  ncache=2*max(n1,n2,n3,1024)
    4943              :  if (ncache/(2*max(n1,n2,n3))<1) then
    4944              :    write(msg,'(5a)')&
    4945              :      'ncache has to be enlarged to be able to hold at',ch10, &
    4946              :      'least one 1-d FFT of each size even though this will',ch10,&
    4947              :      'reduce the performance for shorter transform lengths'
    4948              :    ABI_ERROR(msg)
    4949              :  end if
    4950              : 
    4951              :  ! check input
    4952              :  if (nd1<n1 .or. nd2<n2 .or. nd3<n3) then
    4953              :    ABI_ERROR("forw: assertion error nd1<n1 .or. nd2<n2 .or. nd3<n3")
    4954              :  end if
    4955              : 
    4956              : !Effective n1 and n2 (complex-to-complex or real-to-complex)
    4957              :  n1eff=n1; n2eff=n2; n1zt=n1
    4958              :  if (cplex==1) then
    4959              :    n1eff=(n1+1)/2; n2eff=n2/2+1; n1zt=2*(n1/2+1)
    4960              :  end if
    4961              : 
    4962              :  lzt=n2eff
    4963              :  if (mod(n2eff,2) == 0) lzt=lzt+1
    4964              :  if (mod(n2eff,4) == 0) lzt=lzt+1
    4965              : 
    4966              :  ! maximal number of big box 3rd dim slices for all procs
    4967              :  nnd3=nd3proc*nproc_fft
    4968              : 
    4969              :  ABI_MALLOC(zw,(2,ncache/2))
    4970              :  ABI_MALLOC(zt,(2,lzt,n1zt))
    4971              :  ABI_MALLOC(zmpi2,(2,n1,nd2proc,nnd3))
    4972              :  if (nproc_fft>1)  then
    4973              :    ABI_MALLOC(zmpi1,(2,n1,nd2proc,nnd3))
    4974              :  end if
    4975              : 
    4976              :  ! Create plans.
    4977              :  ! The prototype for sfftw_plan_many_dft is:
    4978              :  ! sfftw_plan_many_dft(rank, n, howmany,
    4979              :  !   fin,  iembed, istride, idist,
    4980              :  !   fout, oembed, ostride, odist, isign, my_flags)
    4981              : 
    4982              :  lot1=ncache/(2*n1)
    4983              :  lot2=ncache/(2*n2)
    4984              :  lot3=ncache/(2*n3)
    4985              : 
    4986              :  nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
    4987              :  !nthreads = 1
    4988              : 
    4989              :  fw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    4990              :     zw, [ncache/2], lot3, 1,                          &
    4991              :     zw, [ncache/2], lot3, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    4992              : 
    4993              :  if (mod(n1, lot3) /= 0) then
    4994              :    fw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(n1, lot3), &
    4995              :     zw, [ncache/2], lot3, 1,                                      &
    4996              :     zw, [ncache/2], lot3, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    4997              :  end if
    4998              : 
    4999              :  fw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1, &
    5000              :     zt, [lzt, n1zt],   lzt,  1,                       &
    5001              :     zw, [ncache/2], lot1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    5002              : 
    5003              :  if (mod(n2eff, lot1) /= 0) then
    5004              :    fw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(n2eff, lot1), &
    5005              :     zt, [lzt, n1zt],   lzt, 1,                                       &
    5006              :     zw, [ncache/2], lot1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    5007              :  end if
    5008              : 
    5009              :  fw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2, &
    5010              :     zr, [nd1eff,nd2,nd3proc,ndat], nd1eff, 1,         &
    5011              :     zw, [ncache/2], lot2, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    5012              : 
    5013              :  if (mod(n1eff, lot2) /= 0) then
    5014              :    fw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2), &
    5015              :     zr, [nd1eff,nd2,nd3proc,ndat], nd1eff, 1,                       &
    5016              :     zw, [ncache/2], lot2, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    5017              :  end if
    5018              : 
    5019              :  do idat=1,ndat
    5020              : 
    5021              :    do j3=1,nd3proc
    5022              :      if (me_fft*(nd3proc)+j3 <= n3) then
    5023              :        Jp2st=1; J2st=1
    5024              : 
    5025              :        ! transform along y axis
    5026              :        ! input: R1,R2,R3,(Rp3)
    5027              :        do j=1,n1eff,lot2
    5028              :          ma=j
    5029              :          mb=min(j+(lot2-1),n1eff)
    5030              :          n1dfft=mb-ma+1
    5031              : 
    5032              :          if (n1dfft == lot2) then
    5033              :            call dfftw_execute_dft(fw_plan2_lot,  zr(1,j,1,j3,idat), zw)
    5034              :          else
    5035              :            call dfftw_execute_dft(fw_plan2_rest, zr(1,j,1,j3,idat), zw)
    5036              :          end if
    5037              : 
    5038              :          !  input: R1,G2,R3,(Rp3)
    5039              :          ! output: G2,R1,R3,(Rp3)
    5040              :          if (cplex==2) then
    5041              :            call unswitch(n1dfft,n2,lot2,n1zt,lzt,zw,zt(1,1,j))
    5042              :          else
    5043              :            call unswitchreal(n1dfft,n2,n2eff,lot2,n1zt,lzt,zw,zt(1,1,2*j-1))
    5044              :          end if
    5045              :        end do
    5046              : 
    5047              :        ! transform along x axis
    5048              :        ! input: G2,R1,R3,(Rp3)
    5049              :        do j=1,n2eff,lot1
    5050              :          ma=j
    5051              :          mb=min(j+(lot1-1),n2eff)
    5052              :          n1dfft=mb-ma+1
    5053              : 
    5054              :          if (n1dfft == lot1) then
    5055              :            call dfftw_execute_dft(fw_plan1_lot,  zt(1,j,1), zw)
    5056              :          else
    5057              :            call dfftw_execute_dft(fw_plan1_rest, zt(1,j,1), zw)
    5058              :          end if
    5059              : 
    5060              :          ! input:  G2,G1,R3,Gp2,(Rp3)
    5061              :          ! output: G1,G2,R3,Gp2,(Rp3)
    5062              :          ! write(std_out,*) 'J2st,Jp2st',J2st,Jp2st
    5063              :          if (nproc_fft == 1) then
    5064              :            call unmpiswitch(j3,n1dfft,Jp2st,J2st,lot1,n1,nd2proc,nd3proc,nproc_fft,option,zw,zmpi2)
    5065              :          else
    5066              :            call unmpiswitch(j3,n1dfft,Jp2st,J2st,lot1,n1,nd2proc,nd3proc,nproc_fft,option,zw,zmpi1)
    5067              :          end if
    5068              :        end do
    5069              : 
    5070              :      end if
    5071              :    end do ! j3
    5072              : 
    5073              :    ! Interprocessor data transposition
    5074              :    ! input:  G1,G2,R3,Gp2,(Rp3)
    5075              :    ! output: G1,G2,R3,Rp3,(Gp2)
    5076              :    if (nproc_fft>1) then
    5077              :      call xmpi_alltoall(zmpi1,2*n1*nd2proc*nd3proc, &
    5078              :                         zmpi2,2*n1*nd2proc*nd3proc,comm_fft,ierr)
    5079              :    end if
    5080              : 
    5081              :    ! transform along z axis
    5082              :    ! input: G1,G2,R3,(Gp2)
    5083              : 
    5084              :    do j2=1,nd2proc
    5085              :      if (me_fft*(nd2proc)+j2 <= n2eff) then
    5086              :        do i1=1,n1,lot3
    5087              :          ma=i1
    5088              :          mb=min(i1+(lot3-1),n1)
    5089              :          n1dfft=mb-ma+1
    5090              : 
    5091              :          ! input:  G1,G2,R3,(Gp2)
    5092              :          ! output: G1,R3,G2,(Gp2)
    5093              :          call unscramble(i1,j2,lot3,n1dfft,n1,n3,nd2proc,nd3,zmpi2,zw)
    5094              : 
    5095              :          if (n1dfft == lot3) then
    5096              :            call dfftw_execute_dft(fw_plan3_lot, zw, zw)
    5097              :          else
    5098              :            call dfftw_execute_dft(fw_plan3_rest, zw, zw)
    5099              :          end if
    5100              : 
    5101              :          call unfill(nd1,nd3,lot3,n1dfft,n3,zw,zf(1,i1,1,j2,idat))
    5102              :          ! output: G1,G3,G2,(Gp2)
    5103              :        end do
    5104              :      end if
    5105              :    end do
    5106              : 
    5107              :  end do ! idat
    5108              : 
    5109              :  call dfftw_destroy_plan(fw_plan3_lot)
    5110              :  if (mod(n1, lot3) /= 0) call dfftw_destroy_plan(fw_plan3_rest)
    5111              : 
    5112              :  call dfftw_destroy_plan(fw_plan1_lot)
    5113              :  if (mod(n2eff, lot1) /= 0) call dfftw_destroy_plan(fw_plan1_rest)
    5114              : 
    5115              :  call dfftw_destroy_plan(fw_plan2_lot)
    5116              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(fw_plan2_rest)
    5117              : 
    5118              :  ABI_FREE(zmpi2)
    5119              :  ABI_FREE(zw)
    5120              :  ABI_FREE(zt)
    5121              :  if (nproc_fft>1)  then
    5122              :    ABI_FREE(zmpi1)
    5123              :  end if
    5124              : 
    5125              : #else
    5126            0 :  ABI_ERROR("FFTW3 support not activated")
    5127              :  ABI_UNUSED((/cplex,ndat,n1,n2,n3,nd1,nd2,nd1eff,nd2proc,nd3proc,option,comm_fft/))
    5128              :  ABI_UNUSED((/zf(1,1,1,1,1),zr(1,1,1,1,1)/))
    5129              : #endif
    5130              : 
    5131            0 : end subroutine fftw3_mpiforw
    5132              : !!***
    5133              : 
    5134              : !----------------------------------------------------------------------
    5135              : 
    5136              : !!****f* m_m_fftw3/fftw3_mpifourdp
    5137              : !! NAME
    5138              : !! fftw3_mpifourdp
    5139              : !!
    5140              : !! FUNCTION
    5141              : !! Conduct Fourier transform of REAL or COMPLEX function f(r)=fofr defined on
    5142              : !! fft grid in real space, to create complex f(G)=fofg defined on full fft grid
    5143              : !! in reciprocal space, in full storage mode, or the reverse operation.
    5144              : !! For the reverse operation, the final data is divided by nfftot.
    5145              : !! REAL case when cplex=1, COMPLEX case when cplex=2
    5146              : !! Usually used for density and potentials.
    5147              : !!
    5148              : !! INPUTS
    5149              : !! cplex=1 if fofr is real, 2 if fofr is complex
    5150              : !! nfft=(effective) number of FFT grid points (for this processor)
    5151              : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
    5152              : !! ndat=Number of FFT transforms
    5153              : !! isign=sign of Fourier transform exponent: current convention uses
    5154              : !!    +1 for transforming from G to r
    5155              : !!    -1 for transforming from r to G.
    5156              : !! fftn2_distrib(2),ffti2_local(2)
    5157              : !! fftn3_distrib(3),ffti3_local(3)
    5158              : !! comm_fft=MPI communicator
    5159              : !!
    5160              : !! SIDE EFFECTS
    5161              : !! Input/Output
    5162              : !! fofg(2,nfft)=f(G), complex.
    5163              : !! fofr(cplex*nfft)=input function f(r) (real or complex)
    5164              : !!
    5165              : !! SOURCE
    5166              : 
    5167            0 : subroutine fftw3_mpifourdp(cplex,nfft,ngfft,ndat,isign,&
    5168            0 :                            fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local,fofg,fofr,comm_fft)
    5169              : 
    5170              : !Arguments ------------------------------------
    5171              : !scalars
    5172              :  integer,intent(in) :: cplex,isign,nfft,ndat,comm_fft
    5173              : !arrays
    5174              :  integer,intent(in) :: ngfft(18)
    5175              :  integer,intent(in) :: fftn2_distrib(ngfft(2)),ffti2_local(ngfft(2))
    5176              :  integer,intent(in) :: fftn3_distrib(ngfft(3)),ffti3_local(ngfft(3))
    5177              :  real(dp),intent(inout) :: fofg(2,nfft*ndat),fofr(cplex*nfft*ndat)
    5178              : 
    5179              : !Local variables-------------------------------
    5180              : !scalars
    5181              :  integer :: n1,n2,n3,n4,n5,n6,nd2proc,nd3proc,nproc_fft,me_fft
    5182              : !arrays
    5183            0 :  real(dp),allocatable :: workf(:,:,:,:,:),workr(:,:,:,:,:)
    5184              : ! *************************************************************************
    5185              : 
    5186              :  ! Note the only c2c is supported in parallel.
    5187            0 :  n1=ngfft(1); n2=ngfft(2); n3=ngfft(3)
    5188            0 :  n4=ngfft(4); n5=ngfft(5); n6=ngfft(6)
    5189            0 :  me_fft=ngfft(11); nproc_fft=ngfft(10)
    5190              : 
    5191            0 :  nd2proc=((n2-1)/nproc_fft) +1
    5192            0 :  nd3proc=((n6-1)/nproc_fft) +1
    5193            0 :  ABI_MALLOC(workr,(2,n4,n5,nd3proc,ndat))
    5194            0 :  ABI_MALLOC(workf,(2,n4,n6,nd2proc,ndat))
    5195              : 
    5196              :  ! Complex to Complex
    5197              :  ! TODO: Complex to Real
    5198            0 :  select case (isign)
    5199              :  case (1)
    5200              :    ! G --> R
    5201            0 :    call mpifft_fg2dbox(nfft,ndat,fofg,n1,n2,n3,n4,nd2proc,n6,fftn2_distrib,ffti2_local,me_fft,workf)
    5202              : 
    5203            0 :    call fftw3_mpiback(2,ndat,n1,n2,n3,n4,n5,n6,n4,nd2proc,nd3proc,2,workf,workr,comm_fft)
    5204              : 
    5205            0 :    call mpifft_dbox2fr(n1,n2,n3,n4,n5,nd3proc,ndat,fftn3_distrib,ffti3_local,me_fft,workr,cplex,nfft,fofr)
    5206              : 
    5207              :  case (-1)
    5208              :    ! R --> G
    5209            0 :    call mpifft_fr2dbox(cplex,nfft,ndat,fofr,n1,n2,n3,n4,n5,nd3proc,fftn3_distrib,ffti3_local,me_fft,workr)
    5210              : 
    5211            0 :    call fftw3_mpiforw(2,ndat,n1,n2,n3,n4,n5,n6,n4,nd2proc,nd3proc,2,workr,workf,comm_fft)
    5212              : 
    5213              :    ! Transfer FFT output to the original fft box.
    5214            0 :    call mpifft_dbox2fg(n1,n2,n3,n4,nd2proc,n6,ndat,fftn2_distrib,ffti2_local,me_fft,workf,nfft,fofg)
    5215              : 
    5216              :  case default
    5217            0 :    ABI_BUG("Wrong isign")
    5218              :  end select
    5219              : 
    5220            0 :  ABI_FREE(workr)
    5221            0 :  ABI_FREE(workf)
    5222              : 
    5223            0 : end subroutine fftw3_mpifourdp
    5224              : !!***
    5225              : 
    5226              : !----------------------------------------------------------------------
    5227              : 
    5228              : !!****f* m_fftw3/fftw3_applypot
    5229              : !! NAME
    5230              : !!  fftw3_applypot
    5231              : !!
    5232              : !! FUNCTION
    5233              : !! Applies the local real space potential to multiple wavefunctions in Fourier space
    5234              : !!
    5235              : !! INPUTS
    5236              : !!   ZF: Wavefunction (input/output) (note the switch of i2 and i3)
    5237              : !!        real(F(i1,i3,i2,idat))=ZF(1,i1,i3,i2,idat)
    5238              : !!        imag(F(i1,i3,i2,idat))=ZF(2,i1,i3,i2,idat)
    5239              : !!   max1 is positive or zero ; m1 >=max1+1
    5240              : !!   i1= 1... max1+1 corresponds to positive and zero wavevectors 0 ... max1
    5241              : !!   then, if m1 > max1+1, one has min1=max1-m1+1 and
    5242              : !!   i1= max1+2 ... m1 corresponds to negative wavevectors min1 ... -1
    5243              : !!   i2 and i3 have a similar definition of range
    5244              : !!   idat=1,ndat
    5245              : !!   md1,md2,md3: Dimension of ZF (input as well as output), distributed on different procs
    5246              : !!   md2proc=((md2-1)/nproc_fft)+1  maximal number of small box 2nd dim slices for one proc
    5247              : !!
    5248              : !!   POT: Potential
    5249              : !!        POT(cplex*i1,i2,i3)
    5250              : !!        cplex=1 or 2 ,  i1=1,n1 , i2=1,n2 , i3=1,n3
    5251              : !!   nd1,nd2,nd3: dimension of pot
    5252              : !!   comm_fft: MPI communicator
    5253              : !!   nproc_fft: number of processors used as returned by MPI_COMM_SIZE
    5254              : !!   me_fft: [0:nproc_fft-1] number of processor as returned by MPI_COMM_RANK
    5255              : !!    n1,n2,n3: logical dimension of the transform. As transform lengths
    5256              : !!              most products of the prime factors 2,3,5 are allowed.
    5257              : !!             The detailed table with allowed transform lengths can
    5258              : !!             be found in subroutine CTRIG
    5259              : !!
    5260              : !! NOTES:
    5261              : !!   PERFORMANCE CONSIDERATIONS:
    5262              : !!   The maximum number of processors that can reasonably be used is max(n2/2,n3/2)
    5263              : !!
    5264              : !!   It is very important to find the optimal
    5265              : !!   value of NCACHE. NCACHE determines the size of the work array ZW, that
    5266              : !!   has to fit into cache. It has therefore to be chosen to equal roughly
    5267              : !!    half the size of the physical cache in units of real*8 numbers.
    5268              : !!   The optimal value of ncache can easily be determined by numerical
    5269              : !!   experimentation. A too large value of ncache leads to a dramatic
    5270              : !!   and sudden decrease of performance, a too small value to a to a
    5271              : !!   slow and less dramatic decrease of performance. If NCACHE is set
    5272              : !!   to a value so small, that not even a single one dimensional transform
    5273              : !!   can be done in the workarray zw, the program stops with an error message.
    5274              : !!
    5275              : !! SOURCE
    5276              : 
    5277              : 
    5278            0 : subroutine fftw3_applypot(cplexwf,cplex,ndat,n1,n2,n3,nd1,nd2,nd3,nd3proc,&
    5279              : &  max1i,max2i,max3i,m1i,m2i,m3i,md1,md2proc,md3,&
    5280            0 : &  max1o,max2o,max3o,m1o,m2o,m3o,comm_fft,nproc_fft,me_fft,pot,zf)
    5281              : 
    5282              : !Arguments ------------------------------------
    5283              :  integer,intent(in) :: cplexwf,cplex,ndat,n1,n2,n3,nd1,nd2,nd3,nd3proc
    5284              :  integer,intent(in) :: max1i,max2i,max3i,m1i,m2i,m3i,md1,md2proc,md3
    5285              :  integer,intent(in) :: max1o,max2o,max3o,m1o,m2o,m3o,comm_fft,nproc_fft,me_fft
    5286              :  real(dp),intent(in) :: pot(cplex*nd1,nd2,nd3)
    5287              :  real(dp),intent(inout) :: zf(2,md1,md3,md2proc,ndat)
    5288              : 
    5289              : !Local variables-------------------------------
    5290              : !scalars
    5291              : #ifdef HAVE_FFTW3
    5292              :  integer,parameter :: unused0=0
    5293              :  integer :: j,i1,i2,i3,idat,ierr,j3glob,nthreads
    5294              :  integer :: ioption,j2,j3,lzt,m1zt,ma,mb,n1dfft,nnd3,lot1,lot2,lot3
    5295              :  integer :: m2eff,ncache,n1eff,i1inv,i2inv,i3inv,jeff,includelast,j2stb
    5296              :  integer :: jx,j2stf,Jp2stb,Jp2stf,m2ieff,m2oeff
    5297              :  integer(KIND_FFTW_PLAN) :: bw_plan1_lot,bw_plan1_rest
    5298              :  integer(KIND_FFTW_PLAN) :: bw_plan2_lot,bw_plan2_rest
    5299              :  integer(KIND_FFTW_PLAN) :: bw_plan3_lot,bw_plan3_rest
    5300              :  integer(KIND_FFTW_PLAN) :: fw_plan1_lot,fw_plan1_rest
    5301              :  integer(KIND_FFTW_PLAN) :: fw_plan2_lot,fw_plan2_rest
    5302              :  integer(KIND_FFTW_PLAN) :: fw_plan3_lot,fw_plan3_rest
    5303              :  character(len=500) :: msg
    5304              : !arrays
    5305              :  real(dp) :: tsec(2)
    5306              :  real(dp), allocatable :: zmpi1(:,:,:,:),zmpi2(:,:,:,:) ! work arrays for MPI
    5307              :  real(dp),allocatable :: zw(:,:),zt(:,:,:) ! cache work array and array for transpositions
    5308              : ! FFT work arrays
    5309              : ! *************************************************************************
    5310              : 
    5311              :  !ioption=0 ! This was in the old version.
    5312              :  ioption=1 ! This one is needed to be compatible with paral_kgb
    5313              : 
    5314              :  ncache=2*max(n1,n2,n3,1024)
    5315              :  if (ncache/(2*max(n1,n2,n3)) < 1) then
    5316              :    write(msg,"(5a)") &
    5317              :     'ncache has to be enlarged to be able to hold at',ch10,&
    5318              :     'least one 1-d FFT of each size even though this will',ch10,&
    5319              :     'reduce the performance for shorter transform lengths'
    5320              :    ABI_ERROR(msg)
    5321              :  end if
    5322              : 
    5323              :  !call wrtout(std_out,"applypot standard ALLTOALL + FFTW3")
    5324              : 
    5325              :  ! Effective m1 and m2 (complex-to-complex or real-to-complex)
    5326              :  n1eff=n1; m2ieff=m2i; m2oeff=m2o; m1zt=n1
    5327              :  if (cplexwf==1) then
    5328              :    n1eff=(n1+1)/2; m2ieff=m2i/2+1; m2oeff=m2o/2+1; m1zt=2*(n1/2+1)
    5329              :  end if
    5330              : 
    5331              :  m2eff=max(m2ieff,m2oeff)
    5332              :  lzt=m2eff
    5333              :  if (mod(m2eff,2) == 0) lzt=lzt+1
    5334              :  if (mod(m2eff,4) == 0) lzt=lzt+1
    5335              : 
    5336              :  ! maximal number of big box 3rd dim slices for all procs
    5337              :  nnd3=nd3proc*nproc_fft
    5338              : 
    5339              :  ABI_MALLOC(zw,(2,ncache/2))
    5340              :  ABI_MALLOC(zt,(2,lzt,m1zt))
    5341              :  ABI_MALLOC(zmpi2,(2,md1,md2proc,nnd3))
    5342              :  if (nproc_fft > 1)  then
    5343              :    ABI_MALLOC(zmpi1,(2,md1,md2proc,nnd3))
    5344              :  end if
    5345              : 
    5346              :  lot3=ncache/(2*n3)
    5347              :  lot1=ncache/(2*n1)
    5348              :  lot2=ncache/(2*n2)
    5349              : 
    5350              :  ! The prototype for sfftw_plan_many_dft is:
    5351              :  ! sfftw_plan_many_dft(rank, n, howmany,
    5352              :  !   fin,  iembed, istride, idist,
    5353              :  !   fout, oembed, ostride, odist, isign, my_flags)
    5354              : 
    5355              :  nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
    5356              :  !nthreads = 1
    5357              : 
    5358              :  ! Create plans for G --> R (see back_wf)
    5359              :  bw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    5360              :     zw, [ncache/2], lot3, 1,                          &
    5361              :     zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5362              : 
    5363              :  if (mod(m1i, lot3) /= 0) then
    5364              :    bw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(m1i, lot3),&
    5365              :       zw, [ncache/2], lot3, 1,                                    &
    5366              :       zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5367              :  end if
    5368              : 
    5369              :  bw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1, &
    5370              :     zw, [ncache/2],  lot1, 1,                         &
    5371              :     zt, [lzt, m1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5372              : 
    5373              :  if (mod(m2ieff, lot1) /= 0) then
    5374              :    bw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(m2ieff, lot1), &
    5375              :       zw, [ncache/2],  lot1, 1,                                       &
    5376              :       zt, [lzt, m1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5377              :  end if
    5378              : 
    5379              :  !TODO this won't work if iclexwf==1
    5380              :  ! Recheck this
    5381              :  bw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2, &
    5382              :     zw, [ncache/2], lot2, 1,                          &
    5383              :     zw, [ncache/2], lot2, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5384              : 
    5385              :  if (mod(n1eff, lot2) /= 0) then
    5386              :    bw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2), &
    5387              :       zw, [ncache/2], lot2, 1,                                      &
    5388              :       zw, [ncache/2], lot2, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5389              :  end if
    5390              : 
    5391              :  ! Create plans for G --> R (see forw_wf)
    5392              :  fw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    5393              :     zw, [ncache/2], lot3, 1,                          &
    5394              :     zw, [ncache/2], lot3, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    5395              : 
    5396              :  if (mod(m1o, lot3) /= 0) then
    5397              :    fw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(m1o, lot3),&
    5398              :     zw, [ncache/2], lot3, 1,                                      &
    5399              :     zw, [ncache/2], lot3, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    5400              :  end if
    5401              : 
    5402              :  fw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1,&
    5403              :     zt, [lzt, m1zt], lzt,  1,                        &
    5404              :     zw, [ncache/2],  lot1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    5405              : 
    5406              :  if (mod(m2oeff, lot1) /= 0) then
    5407              :    fw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(m2oeff, lot1),&
    5408              :     zt, [lzt, m1zt], lzt,  1,                                        &
    5409              :     zw, [ncache/2],  lot1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    5410              :  end if
    5411              : 
    5412              :  fw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2,&
    5413              :     zw, [ncache/2], lot2, 1,                         &
    5414              :     zw, [ncache/2], lot2, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    5415              : 
    5416              :  if (mod(n1eff, lot2) /= 0) then
    5417              :    fw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2),&
    5418              :     zw, [ncache/2], lot2, 1,                                       &
    5419              :     zw, [ncache/2], lot2, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    5420              :  end if
    5421              : 
    5422              :  do idat=1,ndat
    5423              :    !
    5424              :    ! transform along z axis
    5425              :    ! input: G1,G3,G2,(Gp2)
    5426              :    do j2=1,md2proc
    5427              :      if (me_fft*md2proc+j2 <= m2ieff) then
    5428              :        do i1=1,m1i,lot3
    5429              :          ma=i1
    5430              :          mb=min(i1+(lot3-1),m1i)
    5431              :          n1dfft=mb-ma+1
    5432              : 
    5433              :          ! zero-pad n1dfft G_z lines
    5434              :          ! input: G1,G3,G2,(Gp2)
    5435              :          call fill_cent(md1,md3,lot3,n1dfft,max3i,m3i,n3,zf(1,i1,1,j2,idat),zw)
    5436              : 
    5437              :          if (n1dfft == lot3) then
    5438              :            call dfftw_execute_dft(bw_plan3_lot, zw, zw)
    5439              :          else
    5440              :            call dfftw_execute_dft(bw_plan3_rest, zw, zw)
    5441              :          end if
    5442              : 
    5443              :          ! Local rotation.
    5444              :          ! input:  G1,R3,G2,(Gp2)
    5445              :          ! output: G1,G2,R3,(Gp2)
    5446              :          call scramble(i1,j2,lot3,n1dfft,md1,n3,md2proc,nnd3,zw,zmpi2)
    5447              :        end do
    5448              :      end if
    5449              :    end do
    5450              : 
    5451              :    ! Interprocessor data transposition
    5452              :    ! input:  G1,G2,R3,Rp3,(Gp2)
    5453              :    ! output: G1,G2,R3,Gp2,(Rp3)
    5454              :    if (nproc_fft > 1) then
    5455              :      call timab(543,1,tsec)
    5456              :      call xmpi_alltoall(zmpi2,2*md1*md2proc*nd3proc,&
    5457              :                         zmpi1,2*md1*md2proc*nd3proc,comm_fft,ierr)
    5458              :      call timab(543,2,tsec)
    5459              :    end if
    5460              : 
    5461              :    do j3=1,nd3proc
    5462              :      j3glob = j3 + me_fft*nd3proc
    5463              :      if (me_fft*nd3proc+j3 <= n3) then
    5464              :        Jp2stb=1; J2stb=1
    5465              :        Jp2stf=1; J2stf=1
    5466              : 
    5467              :        ! transform along x axis
    5468              :        do j=1,m2ieff,lot1
    5469              :          ma=j
    5470              :          mb=min(j+(lot1-1),m2ieff)
    5471              :          n1dfft=mb-ma+1
    5472              : 
    5473              :          ! Zero-pad input.
    5474              :          ! input:  G1,G2,R3,G2,(Rp3)
    5475              :          ! output: G2,G1,R3,G2,(Rp3)
    5476              :          if (nproc_fft == 1) then
    5477              :            call mpiswitch_cent(j3,n1dfft,Jp2stb,J2stb,lot1,max1i,md1,m1i,n1,&
    5478              :             md2proc,nd3proc,nproc_fft,ioption,zmpi2,zw, unused0, unused0, unused0)
    5479              :          else
    5480              :            call mpiswitch_cent(j3,n1dfft,Jp2stb,J2stb,lot1,max1i,md1,m1i,n1,&
    5481              :             md2proc,nd3proc,nproc_fft,ioption,zmpi1,zw, unused0, unused0, unused0)
    5482              :          end if
    5483              : 
    5484              :          ! Transform along x
    5485              :          ! input:  G2,G1,R3,(Rp3)
    5486              :          ! output: G2,R1,R3,(Rp3)
    5487              :          if (n1dfft == lot1) then
    5488              :            call dfftw_execute_dft(bw_plan1_lot, zw, zt(1,j,1))
    5489              :          else
    5490              :            call dfftw_execute_dft(bw_plan1_rest, zw, zt(1,j,1))
    5491              :          end if
    5492              :        end do
    5493              : 
    5494              :        ! Transform along y axis (take into account c2c or c2r case).
    5495              :        ! Must loop over the full box.
    5496              :        !TODO this won't work
    5497              :        if (cplexwf==1) then
    5498              :          if(mod(lot2,2).ne.0) lot2=lot2-1 ! needed to introduce jeff
    5499              :        end if
    5500              : 
    5501              :        do j=1,n1eff,lot2
    5502              :          ma=j
    5503              :          mb=min(j+(lot2-1),n1eff)
    5504              :          n1dfft=mb-ma+1
    5505              :          jeff=j
    5506              :          includelast=1
    5507              : 
    5508              :          if (cplexwf==1) then
    5509              :            jeff=2*j-1
    5510              :            includelast=1
    5511              :            if (mb==n1eff .and. n1eff*2/=n1) includelast=0
    5512              :          end if
    5513              : 
    5514              :          ! Zero-pad the input.
    5515              :          !  input: G2,R1,R3,(Rp3)
    5516              :          ! output: R1,G2,R3,(Rp3)
    5517              :          if (cplexwf==2) then
    5518              :            call switch_cent(n1dfft,max2i,m2i,n2,lot2,n1,lzt,zt(1,1,jeff),zw)
    5519              :          else
    5520              :            call switchreal_cent(includelast,n1dfft,max2i,n2,lot2,m1zt,lzt,zt(1,1,jeff),zw)
    5521              :          end if
    5522              : 
    5523              :          ! input:  R1,G2,R3,(Rp3)
    5524              :          ! output: R1,R2,R3,(Rp3)
    5525              :          ! Be careful here
    5526              :          if (n1dfft == lot2) then
    5527              :            call dfftw_execute_dft(bw_plan2_lot, zw, zw)
    5528              :          else
    5529              :            call dfftw_execute_dft(bw_plan2_rest, zw, zw)
    5530              :          end if
    5531              : 
    5532              :          ! Multiply with potential in real space
    5533              :          jx=cplex*(jeff-1)+1
    5534              :          call multpot(cplexwf,cplex,includelast,nd1,nd2,n2,lot2,n1dfft,pot(jx,1,j3glob),zw)
    5535              : 
    5536              :          ! TRANSFORM BACK IN FOURIER SPACE
    5537              :          ! transform along y axis
    5538              :          ! input: R1,R2,R3,(Rp3)
    5539              :          if (n1dfft == lot2) then
    5540              :            call dfftw_execute_dft(fw_plan2_lot,  zw, zw)
    5541              :          else
    5542              :            call dfftw_execute_dft(fw_plan2_rest, zw, zw)
    5543              :          end if
    5544              : 
    5545              :          ! input: R1,G2,R3,(Rp3)
    5546              :          ! output: G2,R1,R3,(Rp3)
    5547              :          if (cplexwf==2) then
    5548              :            call unswitch_cent(n1dfft,max2o,m2o,n2,lot2,n1,lzt,zw,zt(1,1,jeff))
    5549              :          else
    5550              :            call unswitchreal_cent(n1dfft,max2o,n2,lot2,n1,lzt,zw,zt(1,1,jeff))
    5551              :          end if
    5552              :        end do ! j
    5553              : 
    5554              :        ! transform along x axis
    5555              :        ! input:  R2,R1,R3,(Rp3)
    5556              :        ! output: R2,G1,R3,(Rp3)
    5557              :        do j=1,m2oeff,lot1
    5558              :          ma=j
    5559              :          mb=min(j+(lot1-1),m2oeff)
    5560              :          n1dfft=mb-ma+1
    5561              : 
    5562              :          if (n1dfft == lot1) then
    5563              :            call dfftw_execute_dft(fw_plan1_lot,  zt(1,j,1), zw)
    5564              :          else
    5565              :            call dfftw_execute_dft(fw_plan1_rest, zt(1,j,1), zw)
    5566              :          end if
    5567              : 
    5568              :          ! input:  G2,G1,R3,Gp2,(Rp3)
    5569              :          ! output: G1,G2,R3,Gp2,(Rp3)
    5570              :          if (nproc_fft == 1) then
    5571              :            call unmpiswitch_cent(j3,n1dfft,Jp2stf,J2stf,lot1,max1o,md1,m1o,n1,&
    5572              :             md2proc,nd3proc,nproc_fft,ioption,zw,zmpi2)
    5573              :          else
    5574              :            call unmpiswitch_cent(j3,n1dfft,Jp2stf,J2stf,lot1,max1o,md1,m1o,n1,&
    5575              :             md2proc,nd3proc,nproc_fft,ioption,zw,zmpi1)
    5576              :          end if
    5577              :        end do ! j
    5578              :      end if
    5579              :    end do
    5580              : 
    5581              :    ! Interprocessor data transposition
    5582              :    ! input:  G1,G2,R3,Gp2,(Rp3)
    5583              :    ! output: G1,G2,R3,Rp3,(Gp2)
    5584              :    if (nproc_fft > 1) then
    5585              :      call timab(544,1,tsec)
    5586              :      call xmpi_alltoall(zmpi1,2*md1*md2proc*nd3proc, &
    5587              :                         zmpi2,2*md1*md2proc*nd3proc,comm_fft,ierr)
    5588              :      call timab(544,2,tsec)
    5589              :    end if
    5590              : 
    5591              :    ! transform along z axis
    5592              :    ! input: G1,G2,R3,(Gp2)
    5593              :    !lot=ncache/(4*n3)
    5594              :    do j2=1,md2proc
    5595              :      if (me_fft*md2proc+j2 <= m2oeff) then
    5596              :        do i1=1,m1o,lot3
    5597              :          ma=i1
    5598              :          mb=min(i1+(lot3-1),m1o)
    5599              :          n1dfft=mb-ma+1
    5600              : 
    5601              :          ! input:  G1,G2,R3,(Gp2)
    5602              :          ! output: G1,R3,G2,(Gp2)
    5603              :          call unscramble(i1,j2,lot3,n1dfft,md1,n3,md2proc,nnd3,zmpi2,zw)
    5604              : 
    5605              :           if (n1dfft == lot3) then
    5606              :             call dfftw_execute_dft(fw_plan3_lot, zw, zw)
    5607              :           else
    5608              :             call dfftw_execute_dft(fw_plan3_rest, zw, zw)
    5609              :           end if
    5610              : 
    5611              :          call unfill_cent(md1,md3,lot3,n1dfft,max3o,m3o,n3,zw,zf(1,i1,1,j2,idat))
    5612              :          ! output: G1,G3,G2,(Gp2)
    5613              :        end do
    5614              :      end if
    5615              :    end do
    5616              : 
    5617              :    ! Complete missing values with complex conjugate
    5618              :    ! Inverse of ix is located at nx+2-ix , except for ix=1, for which it is 1.
    5619              :    if (cplexwf==1) then
    5620              :      do i3=1,m3o
    5621              :        i3inv=m3o+2-i3
    5622              :        if (i3==1) i3inv=1
    5623              :        if (m2oeff>1)then
    5624              :          do i2=2,m2oeff
    5625              :            i2inv=m2o+2-i2
    5626              :            zf(1,1,i3inv,i2inv,idat)= zf(1,1,i3,i2,idat)
    5627              :            zf(2,1,i3inv,i2inv,idat)=-zf(2,1,i3,i2,idat)
    5628              :            do i1=2,m1o
    5629              :              i1inv=m1o+2-i1
    5630              :              zf(1,i1inv,i3inv,i2inv,idat)= zf(1,i1,i3,i2,idat)
    5631              :              zf(2,i1inv,i3inv,i2inv,idat)=-zf(2,i1,i3,i2,idat)
    5632              :            end do
    5633              :          end do
    5634              :        end if
    5635              :      end do
    5636              :    end if
    5637              : 
    5638              :  end do ! idat
    5639              : 
    5640              :  call dfftw_destroy_plan(bw_plan3_lot)
    5641              :  if (mod(m1i, lot3) /= 0) call dfftw_destroy_plan(bw_plan3_rest)
    5642              : 
    5643              :  call dfftw_destroy_plan(bw_plan1_lot)
    5644              :  if (mod(m2ieff, lot1) /= 0) call dfftw_destroy_plan(bw_plan1_rest)
    5645              : 
    5646              :  call dfftw_destroy_plan(bw_plan2_lot)
    5647              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(bw_plan2_rest)
    5648              : 
    5649              :  call dfftw_destroy_plan(fw_plan3_lot)
    5650              :  if (mod(m1o, lot3) /= 0) call dfftw_destroy_plan(fw_plan3_rest)
    5651              : 
    5652              :  call dfftw_destroy_plan(fw_plan1_lot)
    5653              :  if (mod(m2oeff, lot1) /= 0) call dfftw_destroy_plan(fw_plan1_rest)
    5654              : 
    5655              :  call dfftw_destroy_plan(fw_plan2_lot)
    5656              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(fw_plan2_rest)
    5657              : 
    5658              :  ABI_FREE(zmpi2)
    5659              :  ABI_FREE(zw)
    5660              :  ABI_FREE(zt)
    5661              :  if (nproc_fft > 1)  then
    5662              :    ABI_FREE(zmpi1)
    5663              :  end if
    5664              : 
    5665              : #else
    5666            0 :  ABI_ERROR("FFTW3 support not activated")
    5667              :  ABI_UNUSED((/cplexwf,cplex,ndat,n1,n2,n3,nd1,nd2,nd3,nd3proc/))
    5668              :  ABI_UNUSED((/max1i,max2i,max3i,m1i,m2i,m3i,md1,md2proc,md3/))
    5669              :  ABI_UNUSED((/max1o,max2o,max3o,m1o,m2o,m3o,comm_fft,nproc_fft,me_fft/))
    5670              :  ABI_UNUSED((/pot(1,1,1),zf(1,1,1,1,1)/))
    5671              : #endif
    5672              : 
    5673            0 : end subroutine fftw3_applypot
    5674              : !!***
    5675              : 
    5676              : !----------------------------------------------------------------------
    5677              : 
    5678              : !!****f* m_fftw3/fftw3_accrho
    5679              : !! NAME
    5680              : !! fftw3_accrho
    5681              : !!
    5682              : !! FUNCTION
    5683              : !! Accumulates the real space density rho from the ndat wavefunctions zf
    5684              : !! by transforming zf into real space and adding all the amplitudes squared
    5685              : !!
    5686              : !! INPUTS:
    5687              : !!   ZF: input array (note the switch of i2 and i3)
    5688              : !!         real(F(i1,i3,i2,idat))=ZF(1,i1,i3,i2,idat)
    5689              : !!         imag(F(i1,i3,i2,idat))=ZF(2,i1,i3,i2,idat)
    5690              : !!   max1 is positive or zero ; m1 >=max1+1
    5691              : !!   i1= 1... max1+1 corresponds to positive and zero wavevectors 0 ... max1
    5692              : !!   then, if m1 > max1+1, one has min1=max1-m1+1 and
    5693              : !!   i1= max1+2 ... m1 corresponds to negative wavevectors min1 ... -1
    5694              : !!   i2 and i3 have a similar definition of range
    5695              : !!   idat=1,ndat
    5696              : !!   md1,md2,md3: Dimension of ZF
    5697              : !!   md2proc=((md2-1)/nproc_fft)+1 ! maximal number of small box 2nd dim slices for one proc
    5698              : !!   weight(ndat)= weight for the density accumulation
    5699              : !!
    5700              : !! OUTPUTS:
    5701              : !!    RHOoutput(i1,i2,i3) = RHOinput(i1,i2,i3) + sum on idat of (FFT(ZF))**2 *weight
    5702              : !!        i1=1,n1 , i2=1,n2 , i3=1,n3
    5703              : !!   comm_fft: MPI communicator
    5704              : !!   nproc_fft: number of processors used as returned by MPI_COMM_SIZE
    5705              : !!   me_fft: [0:nproc_fft-1] number of processor as returned by MPI_COMM_RANK
    5706              : !!    n1,n2,n3: logical dimension of the transform. As transform lengths
    5707              : !!              most products of the prime factors 2,3,5 are allowed.
    5708              : !!             The detailed table with allowed transform lengths can
    5709              : !!             be found in subroutine CTRIG
    5710              : !!    nd1,nd2,nd3: Dimension of RHO
    5711              : !!   nd3proc=((nd3-1)/nproc_fft)+1 ! maximal number of big box 3rd dim slices for one proc
    5712              : !!
    5713              : !! NOTES:
    5714              : !!   PERFORMANCE CONSIDERATIONS:
    5715              : !!   The maximum number of processors that can reasonably be used is max(n2/2,n3/2)
    5716              : !!
    5717              : !!   It is very important to find the optimal
    5718              : !!   value of NCACHE. NCACHE determines the size of the work array ZW, that
    5719              : !!   has to fit into cache. It has therefore to be chosen to equal roughly
    5720              : !!    half the size of the physical cache in units of real*8 numbers.
    5721              : !!   The optimal value of ncache can easily be determined by numerical
    5722              : !!   experimentation. A too large value of ncache leads to a dramatic
    5723              : !!   and sudden decrease of performance, a too small value to a to a
    5724              : !!   slow and less dramatic decrease of performance. If NCACHE is set
    5725              : !!   to a value so small, that not even a single one dimensional transform
    5726              : !!   can be done in the workarray zw, the program stops with an error message.
    5727              : !!
    5728              : !! SOURCE
    5729              : 
    5730            0 : subroutine fftw3_accrho(cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3,nd3proc,&
    5731            0 : &  max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft,nproc_fft,me_fft,zf,rho,weight_r,weight_i)
    5732              : 
    5733              : !Arguments ------------------------------------
    5734              :  integer,intent(in) :: cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3,nd3proc
    5735              :  integer,intent(in) :: max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft,nproc_fft,me_fft
    5736              :  real(dp),intent(in) :: zf(2,md1,md3,md2proc,ndat)
    5737              :  real(dp),intent(in) :: weight_r(ndat) , weight_i(ndat)
    5738              :  real(dp),intent(inout) :: rho(nd1,nd2,nd3)
    5739              : 
    5740              : !Local variables-------------------------------
    5741              : !scalars
    5742              : #ifdef HAVE_FFTW3
    5743              :  integer,parameter :: unused0=0
    5744              :  integer :: j,i1,idat,ierr,j3glob
    5745              :  integer :: ioption,j2,j3,j2st,jp2st,lzt,m1zt,ma,mb,n1dfft,nnd3
    5746              :  integer :: m2eff,ncache,n1eff,jeff,includelast,lot1,lot2,lot3,nthreads
    5747              :  integer(KIND_FFTW_PLAN) :: bw_plan1_lot,bw_plan1_rest
    5748              :  integer(KIND_FFTW_PLAN) :: bw_plan2_lot,bw_plan2_rest
    5749              :  integer(KIND_FFTW_PLAN) :: bw_plan3_lot,bw_plan3_rest
    5750              :  character(len=500) :: msg
    5751              : !arrays
    5752              :  real(dp), allocatable :: zmpi1(:,:,:,:),zmpi2(:,:,:,:) ! work arrays for MPI
    5753              :  real(dp),allocatable :: zw(:,:),zt(:,:,:) ! cache work array and array for transpositions
    5754              :  real(dp) :: tsec(2)
    5755              : ! *************************************************************************
    5756              : 
    5757              :  !ioption=0 ! This was in the old version.
    5758              :  ioption=1 ! This one is needed to be compatible with paral_kgb
    5759              : 
    5760              :  !nproc_fft = xmpi_comm_size(comm_fft); me_fft = xmpi_comm_rank(comm_fft)
    5761              : 
    5762              : ! find cache size that gives optimal performance on machine
    5763              :  ncache=2*max(n1,n2,n3,1024)
    5764              :  if (ncache/(2*max(n1,n2,n3)) < 1) then
    5765              :     write(msg,"(5a)") &
    5766              :      'ncache has to be enlarged to be able to hold at',ch10,&
    5767              :      'least one 1-d FFT of each size even though this will',ch10,&
    5768              :      'reduce the performance for shorter transform lengths'
    5769              :     ABI_ERROR(msg)
    5770              :  end if
    5771              : 
    5772              : !Effective m1 and m2 (complex-to-complex or real-to-complex)
    5773              :  n1eff=n1; m2eff=m2 ; m1zt=n1
    5774              :  if (cplexwf==1) then
    5775              :    n1eff=(n1+1)/2; m2eff=m2/2+1; m1zt=2*(n1/2+1)
    5776              :  end if
    5777              : 
    5778              :  lzt=m2eff
    5779              :  if (mod(m2eff,2) == 0) lzt=lzt+1
    5780              :  if (mod(m2eff,4) == 0) lzt=lzt+1
    5781              : 
    5782              :  ! maximal number of big box 3rd dim slices for all procs
    5783              :  nnd3=nd3proc*nproc_fft
    5784              : 
    5785              :  ABI_MALLOC(zw,(2,ncache/2))
    5786              :  ABI_MALLOC(zt,(2,lzt,m1zt))
    5787              :  ABI_MALLOC(zmpi2,(2,md1,md2proc,nnd3))
    5788              :  if (nproc_fft > 1)  then
    5789              :    ABI_MALLOC(zmpi1,(2,md1,md2proc,nnd3))
    5790              :  end if
    5791              : 
    5792              :  ! Create plans.
    5793              :  ! The prototype for sfftw_plan_many_dft is:
    5794              :  ! sfftw_plan_many_dft(rank, n, howmany,
    5795              :  !   fin,  iembed, istride, idist,
    5796              :  !   fout, oembed, ostride, odist, isign, my_flags)
    5797              : 
    5798              :  lot3=ncache/(2*n3)
    5799              :  lot1=ncache/(2*n1)
    5800              :  lot2=ncache/(2*n2)
    5801              : 
    5802              :  nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
    5803              :  !nthreads = 1
    5804              : 
    5805              :  bw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    5806              :     zw, [ncache/2], lot3, 1,                          &
    5807              :     zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5808              : 
    5809              :  if (mod(m1, lot3) /= 0) then
    5810              :    bw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(m1, lot3), &
    5811              :       zw, [ncache/2], lot3, 1,                                    &
    5812              :       zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5813              :  end if
    5814              : 
    5815              :  bw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1, &
    5816              :     zw, [ncache/2],  lot1, 1,                         &
    5817              :     zt, [lzt, m1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5818              : 
    5819              :  if (mod(m2eff, lot1) /= 0) then
    5820              :    bw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(m2eff, lot1), &
    5821              :       zw, [ncache/2],  lot1, 1,                                      &
    5822              :       zt, [lzt, m1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5823              :  end if
    5824              : 
    5825              :  ! FIXME THis won't work if ixplexwf == 1
    5826              :  bw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2, &
    5827              :     zw, [ncache/2], lot2, 1,                          &
    5828              :     zw, [ncache/2], lot2, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5829              : 
    5830              :  if (mod(n1eff, lot2) /= 0) then
    5831              :    bw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2), &
    5832              :       zw, [ncache/2], lot2, 1,                                      &
    5833              :       zw, [ncache/2], lot2, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    5834              :  end if
    5835              : 
    5836              :  do idat=1,ndat
    5837              :    ! transform along z axis
    5838              :    ! input: I1,I3,J2,(Jp2)
    5839              :    !lot=ncache/(4*n3)
    5840              : 
    5841              :    ! Loop over the y planes treated by this node and transform n1ddft G_z lines.
    5842              :    do j2=1,md2proc
    5843              :      if (me_fft*md2proc+j2 <= m2eff) then ! MG REMOVED TO BE CONSISTENT WITH BACK_WF
    5844              :        do i1=1,m1,lot3
    5845              :          ma=i1
    5846              :          mb=min(i1+(lot3-1),m1)
    5847              :          n1dfft=mb-ma+1
    5848              : 
    5849              :          ! zero-pad n1dfft G_z lines
    5850              :          !  input: G1,G3,G2,(Gp2)
    5851              :          ! output: G1,R3,G2,(Gp2)
    5852              :          call fill_cent(md1,md3,lot3,n1dfft,max3,m3,n3,zf(1,i1,1,j2,idat),zw)
    5853              : 
    5854              :          ! Transform along z.
    5855              :          if (n1dfft == lot3) then
    5856              :            call dfftw_execute_dft(bw_plan3_lot, zw, zw)
    5857              :          else
    5858              :            call dfftw_execute_dft(bw_plan3_rest, zw, zw)
    5859              :          end if
    5860              : 
    5861              :          ! Local rotation.
    5862              :          ! input:  G1,R3,G2,(Gp2)
    5863              :          ! output: G1,G2,R3,(Gp2)
    5864              :          call scramble(i1,j2,lot3,n1dfft,md1,n3,md2proc,nnd3,zw,zmpi2)
    5865              :        end do
    5866              :      end if
    5867              :    end do
    5868              : 
    5869              :    ! Interprocessor data transposition
    5870              :    ! input:  G1,G2,R3,Rp3,(Gp2)
    5871              :    ! output: G1,G2,R3,Gp2,(Rp3)
    5872              :    if (nproc_fft > 1) then
    5873              :      call timab(543,1,tsec)
    5874              :      call xmpi_alltoall(zmpi2,2*md1*md2proc*nd3proc, &
    5875              :                         zmpi1,2*md1*md2proc*nd3proc,comm_fft,ierr)
    5876              :      call timab(543,2,tsec)
    5877              :    end if
    5878              : 
    5879              :    ! Loop over the z treated by this node.
    5880              :    do j3=1,nd3proc
    5881              :      j3glob = j3 + me_fft*nd3proc
    5882              : 
    5883              :      if (me_fft*nd3proc+j3 <= n3) then
    5884              :        Jp2st=1; J2st=1
    5885              : 
    5886              :        ! Loop over G_y in the small box.
    5887              :        do j=1,m2eff,lot1
    5888              :          ma=j
    5889              :          mb=min(j+(lot1-1),m2eff)
    5890              :          n1dfft=mb-ma+1
    5891              : 
    5892              :          ! Zero-pad input.
    5893              :          ! input:  G1,G2,R3,JG2,(Rp3)
    5894              :          ! output: G2,G1,R3,JG2,(Rp3)
    5895              :          if (nproc_fft == 1) then
    5896              :           call mpiswitch_cent(j3,n1dfft,Jp2st,J2st,lot1,max1,md1,m1,n1,&
    5897              :            md2proc,nd3proc,nproc_fft,ioption,zmpi2,zw,unused0, unused0,unused0)
    5898              :          else
    5899              :           call mpiswitch_cent(j3,n1dfft,Jp2st,J2st,lot1,max1,md1,m1,n1,&
    5900              :            md2proc,nd3proc,nproc_fft,ioption,zmpi1,zw, unused0,unused0,unused0)
    5901              :          end if
    5902              : 
    5903              :          ! Transform along x
    5904              :          ! input:  G2,G1,R3,(Rp3)
    5905              :          ! output: G2,R1,R3,(Rp3)
    5906              :          if (n1dfft == lot1) then
    5907              :            call dfftw_execute_dft(bw_plan1_lot, zw, zt(1,j,1))
    5908              :          else
    5909              :            call dfftw_execute_dft(bw_plan1_rest, zw, zt(1,j,1))
    5910              :          end if
    5911              : 
    5912              :        end do
    5913              : 
    5914              :        ! Transform along y axis (take into account c2c or c2r case).
    5915              :        ! Must loop over the full box.
    5916              :        !lot=ncache/(4*n2)
    5917              :        ! FIXME THis won't work
    5918              :        if (cplexwf==1) then
    5919              :          if (mod(lot2,2) /=0) lot2=lot2-1 ! needed to introduce jeff
    5920              :        end if
    5921              : 
    5922              :        do j=1,n1eff,lot2
    5923              :          ma=j
    5924              :          mb=min(j+(lot2-1),n1eff)
    5925              :          n1dfft=mb-ma+1
    5926              :          jeff=j
    5927              :          includelast=1
    5928              : 
    5929              :          if (cplexwf==1) then
    5930              :            jeff=2*j-1
    5931              :            includelast=1
    5932              :            if (mb==n1eff .and. n1eff*2/=n1) includelast=0
    5933              :          end if
    5934              : 
    5935              :          ! Zero-pad the input.
    5936              :          ! input:  G2,R1,R3,(Rp3)
    5937              :          ! output: R1,G2,R3,(Rp3)
    5938              :          if (cplexwf==2) then
    5939              :            call switch_cent(n1dfft,max2,m2,n2,lot2,n1,lzt,zt(1,1,j),zw)
    5940              :          else
    5941              :            call switchreal_cent(includelast,n1dfft,max2,n2,lot2,m1zt,lzt,zt(1,1,jeff),zw)
    5942              :          end if
    5943              : 
    5944              :          if (n1dfft == lot2) then
    5945              :            call dfftw_execute_dft(bw_plan2_lot, zw, zw)
    5946              :          else
    5947              :            call dfftw_execute_dft(bw_plan2_rest, zw, zw)
    5948              :          end if
    5949              : 
    5950              :          ! Accumulate
    5951              :          call addrho(cplexwf,includelast,nd1,nd2,n2,lot2,n1dfft,&
    5952              : &          zw,rho(jeff,1,j3glob),weight_r(idat),weight_i(idat))
    5953              :        end do
    5954              :        ! output: i1,i2,j3,(jp3)
    5955              : 
    5956              :       end if
    5957              :     end do ! j3
    5958              :  end do ! idat
    5959              : 
    5960              :  call dfftw_destroy_plan(bw_plan3_lot)
    5961              :  if (mod(m1, lot3) /= 0) call dfftw_destroy_plan(bw_plan3_rest)
    5962              : 
    5963              :  call dfftw_destroy_plan(bw_plan1_lot)
    5964              :  if (mod(m2eff, lot1) /= 0) call dfftw_destroy_plan(bw_plan1_rest)
    5965              : 
    5966              :  call dfftw_destroy_plan(bw_plan2_lot)
    5967              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(bw_plan2_rest)
    5968              : 
    5969              :  ABI_FREE(zmpi2)
    5970              :  ABI_FREE(zw)
    5971              :  ABI_FREE(zt)
    5972              :  if (nproc_fft > 1)  then
    5973              :    ABI_FREE(zmpi1)
    5974              :  end if
    5975              : 
    5976              : #else
    5977            0 :  ABI_ERROR("FFTW3 support not activated")
    5978              :  ABI_UNUSED((/cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc/))
    5979              :  ABI_UNUSED((/ max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft,nproc_fft,me_fft/))
    5980              :  ABI_UNUSED((/zf(1,1,1,1,1),rho(1,1,1),weight_r(1),weight_i(1)/))
    5981              : #endif
    5982              : 
    5983            0 : end subroutine fftw3_accrho
    5984              : !!***
    5985              : 
    5986              : !----------------------------------------------------------------------
    5987              : 
    5988              : !!****f* m_fftw3/fftw3_mpiback_manywf
    5989              : !! NAME
    5990              : !!  fftw3_mpiback_manywf
    5991              : !!
    5992              : !! FUNCTION
    5993              : !!   Does multiple 3-dim backward FFTs from Fourier into real space
    5994              : !!   Adopt standard convention that isign=1 for backward transform
    5995              : !!
    5996              : !!   CALCULATES THE DISCRETE FOURIER TRANSFORM ZF(I1,I2,I3)=
    5997              : !!
    5998              : !!   S_(j1,j2,j3) EXP(isign*i*2*pi*(j1*i1/n1+j2*i2/n2+j3*i3/n3)) ZF(j1,j3,j2)
    5999              : !!
    6000              : !!   in parallel using MPI/OpenMP.
    6001              : !!
    6002              : !! INPUTS:
    6003              : !!    cplexwf=1 if wavefunction is real, 2 if complex
    6004              : !!    ndat=Number of wavefunctions to transform.
    6005              : !!    n1,n2,n3: logical dimension of the transform. As transform lengths
    6006              : !!              most products of the prime factors 2,3,5 are allowed.
    6007              : !!              The detailed table with allowed transform lengths can be found in subroutine CTRIG
    6008              : !!    nd1,nd2,nd3: Leading Dimension of ZR
    6009              : !!    nd3proc=((nd3-1)/nproc_fft)+1 maximal number of big box 3rd dim slices for one proc
    6010              : !!    max1 is positive or zero; m1 >=max1+1
    6011              : !!      i1= 1... max1+1 corresponds to positive and zero wavevectors 0 ... max1
    6012              : !!      then, if m1 > max1+1, one has min1=max1-m1+1 and
    6013              : !!      i1= max1+2 ... m1 corresponds to negative wavevectors min1 ... -1
    6014              : !!    max2 and max3 have a similar definition of range
    6015              : !!    m1,m2,m3=Size of the box enclosing the G-sphere.
    6016              : !!    md1,md2,md3: Dimension of ZF given on the **small** FFT box.
    6017              : !!    md2proc=((md2-1)/nproc_fft)+1 maximal number of small box 2nd dim slices for one proc
    6018              : !!    nproc_fft: number of processors used as returned by MPI_COMM_SIZE
    6019              : !!    comm_fft=MPI communicator for the FFT.
    6020              : !!    ZF: input array (note the switch of i2 and i3)
    6021              : !!          real(F(i1,i3,i2,idat))=ZF(1,i1,i3,i2,idat)
    6022              : !!          imag(F(i1,i3,i2,idat))=ZF(2,i1,i3,i2,idat)
    6023              : !!
    6024              : !! OUTPUTS
    6025              : !!    ZR: output array
    6026              : !!          ZR(1,i1,i2,i3,idat)=real(R(i1,i2,i3,idat))
    6027              : !!          ZR(2,i1,i2,i3,idat)=imag(R(i1,i2,i3,idat))
    6028              : !!        i1=1,n1 , i2=1,n2 , i3=1,n3 , idat=1,ndat
    6029              : !!
    6030              : !! NOTES
    6031              : !!   The maximum number of processors that can reasonably be used is max(n2/2,n3/2)
    6032              : !!
    6033              : !!   It is very important to find the optimal
    6034              : !!   value of NCACHE. NCACHE determines the size of the work array ZW, that
    6035              : !!   has to fit into cache. It has therefore to be chosen to equal roughly
    6036              : !!   half the size of the physical cache in units of real*8 numbers.
    6037              : !!   The optimal value of ncache can easily be determined by numerical
    6038              : !!   experimentation. A too large value of ncache leads to a dramatic
    6039              : !!   and sudden decrease of performance, a too small value to a to a
    6040              : !!   slow and less dramatic decrease of performance. If NCACHE is set
    6041              : !!   to a value so small, that not even a single one dimensional transform
    6042              : !!   can be done in the workarray zw, the program stops with an error message.
    6043              : !!
    6044              : !! SOURCE
    6045              : 
    6046            0 : subroutine fftw3_mpiback_manywf(cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc,&
    6047            0 : &  max1,max2,max3,m1,m2,m3,md1,md2proc,md3,zf,zr,comm_fft)
    6048              : 
    6049              : !Arguments ------------------------------------
    6050              :  integer,intent(in) :: cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc
    6051              :  integer,intent(in) :: max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft
    6052              :  real(dp),intent(in) :: zf(2,md1,md3,md2proc,ndat)
    6053              :  real(dp),intent(out) :: zr(2,nd1,nd2,nd3proc,ndat)
    6054              : 
    6055              : #ifdef HAVE_FFTW3
    6056              : !Local variables-------------------------------
    6057              :  integer,parameter :: nt1=1
    6058              :  integer :: j,i1,i2,idat,ierr,includelast,nthreads
    6059              :  integer :: ioption,j2,j3,j2st,jp2st,jeff,lzt,m1zt,ma,mb,n1dfft,nnd3
    6060              :  integer :: lot1,lot2,lot3
    6061              :  integer :: m2eff,ncache,n1eff,n1half,nproc_fft,me_fft
    6062              :  integer(KIND_FFTW_PLAN) :: bw_plan1_lot,bw_plan1_rest
    6063              :  integer(KIND_FFTW_PLAN) :: bw_plan2_lot,bw_plan2_rest
    6064              :  integer(KIND_FFTW_PLAN) :: bw_plan3_lot,bw_plan3_rest
    6065              :  !type(C_PTR) :: zw_cptr,zt_cptr
    6066              :  character(len=500) :: msg
    6067              : !arrays
    6068              :  integer :: requests(ndat)
    6069              :  real(dp) ABI_ASYNC, allocatable :: zmpi1(:,:,:,:,:),zmpi2(:,:,:,:,:)  ! work arrays for MPI
    6070              :  real(dp),allocatable :: zw(:,:),zt(:,:,:) ! cache work array and array for transpositions
    6071              :  !real(dp),contiguous, pointer :: zw(:,:),zt(:,:,:)
    6072              : ! FFT work arrays
    6073              :  real(dp) :: tsec(2)
    6074              : ! *************************************************************************
    6075              : 
    6076              :  !call wrtout(std_out,"mpiback with non-blocking IALLTOALL + FFTW3")
    6077              :  ! FIXME must provide a default value but which one?
    6078              :  ! ioption = 0
    6079              :  ioption = 1
    6080              :  !if (paral_kgb==1) ioption=1
    6081              : 
    6082              :  nproc_fft = xmpi_comm_size(comm_fft); me_fft = xmpi_comm_rank(comm_fft)
    6083              : 
    6084              :  ! Find cache size that gives optimal performance on machine
    6085              :  ncache=2*max(n1,n2,n3,1024)
    6086              :  if (ncache/(2*max(n1,n2,n3))<1) then
    6087              :    write(msg,"(5a)") &
    6088              :     'ncache has to be enlarged to be able to hold at',ch10, &
    6089              :     'least one 1-d FFT of each size even though this will',ch10,&
    6090              :     'reduce the performance for shorter transform lengths'
    6091              :     ABI_ERROR(msg)
    6092              :  end if
    6093              : 
    6094              :  ! Effective m1 and m2 (complex-to-complex or real-to-complex)
    6095              :  n1eff=n1; m2eff=m2; m1zt=n1
    6096              :  if (cplexwf==1) then
    6097              :    n1eff=(n1+1)/2; m2eff=m2/2+1; m1zt=2*(n1/2+1)
    6098              :  end if
    6099              : 
    6100              :  lzt=m2eff
    6101              :  if (mod(m2eff,2)==0) lzt=lzt+1
    6102              :  if (mod(m2eff,4)==0) lzt=lzt+1
    6103              : 
    6104              :  ! maximal number of big box 3rd dim slices for all procs
    6105              :  nnd3=nd3proc*nproc_fft
    6106              : 
    6107              :  ! Allocate cache work array and work arrays for MPI transpositions.
    6108              :  ABI_MALLOC(zw,(2,ncache/2))
    6109              :  ABI_MALLOC(zt,(2,lzt,m1zt))
    6110              : 
    6111              :  !call fftw3_alloc_real([2,ncache/2],zw_cptr,zw)
    6112              :  !call fftw3_alloc_real([2,lzt,m1zt],zt_cptr,zt)
    6113              : 
    6114              :  ABI_MALLOC(zmpi2,(2,md1,md2proc,nnd3,ndat))
    6115              :  if (nproc_fft>1)  then
    6116              :    ABI_MALLOC(zmpi1,(2,md1,md2proc,nnd3,ndat))
    6117              :  end if
    6118              : 
    6119              :  ! Create plans.
    6120              :  ! The prototype for sfftw_plan_many_dft is:
    6121              :  ! sfftw_plan_many_dft(rank, n, howmany,
    6122              :  !   fin,  iembed, istride, idist,
    6123              :  !   fout, oembed, ostride, odist, isign, my_flags)
    6124              : 
    6125              :  lot3=ncache/(2*n3)
    6126              :  lot1=ncache/(2*n1)
    6127              :  lot2=ncache/(2*n2)
    6128              : 
    6129              :  nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
    6130              :  !nthreads = 1
    6131              : 
    6132              :  bw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    6133              :     zw, [ncache/2], lot3, 1,                          &
    6134              :     zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6135              : 
    6136              :  if (mod(m1, lot3) /= 0) then
    6137              :    bw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(m1, lot3), &
    6138              :       zw, [ncache/2], lot3, 1,                                    &
    6139              :       zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6140              :  end if
    6141              : 
    6142              :  bw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1, &
    6143              :     zw, [ncache/2],  lot1, 1,                         &
    6144              :     zt, [lzt, m1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6145              : 
    6146              :  if (mod(m2eff, lot1) /= 0) then
    6147              :    bw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(m2eff, lot1), &
    6148              :       zw, [ncache/2],  lot1, 1,                                      &
    6149              :       zt, [lzt, m1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6150              :  end if
    6151              : 
    6152              :  bw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2, &
    6153              :     zw, [ncache/2], lot2, 1,                          &
    6154              :     zr, [nd1,nd2,nd3proc,ndat], nd1, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6155              : 
    6156              :  if (mod(n1eff, lot2) /= 0) then
    6157              :    bw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2), &
    6158              :       zw, [ncache/2], lot2, 1,                                      &
    6159              :       zr, [nd1,nd2,nd3proc,ndat], nd1, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6160              :  end if
    6161              : 
    6162              :  do idat=1,ndat
    6163              :     ! transform along z axis
    6164              :     ! input: G1,G3,G2,(Gp2)
    6165              : 
    6166              :     ! Loop over the y planes treated by this node and transform n1ddft G_z lines.
    6167              :     do j2=1,md2proc
    6168              :       ! if (me_fft*md2proc+j2<=m2eff) then !a faire plus tard
    6169              :       do i1=1,m1,lot3
    6170              :         ma=i1
    6171              :         mb=min(i1+(lot3-1),m1)
    6172              :         n1dfft=mb-ma+1
    6173              : 
    6174              :         ! zero-pad n1dfft G_z lines
    6175              :         ! input:  G1,G3,G2,(Gp2)
    6176              :         ! output: G1,R3,G2,(Gp2)
    6177              :         call fill_cent(md1,md3,lot3,n1dfft,max3,m3,n3,zf(1,i1,1,j2,idat),zw)
    6178              : 
    6179              :         ! Transform along z.
    6180              :         if (n1dfft == lot3) then
    6181              :           call dfftw_execute_dft(bw_plan3_lot, zw, zw)
    6182              :         else
    6183              :           call dfftw_execute_dft(bw_plan3_rest, zw, zw)
    6184              :         end if
    6185              : 
    6186              :         ! Local rotation.
    6187              :         ! input:  G1,R3,G2,(Gp2)
    6188              :         ! output: G1,G2,R3,(Gp2)
    6189              :         call scramble(i1,j2,lot3,n1dfft,md1,n3,md2proc,nnd3,zw,zmpi2(:,:,:,:,idat))
    6190              :       end do
    6191              :     end do ! j2
    6192              : 
    6193              :     ! Interprocessor data transposition
    6194              :     ! input:  G1,G2,R3,Rp3,(Gp2)
    6195              :     ! output: G1,G2,R3,Gp2,(Rp3)
    6196              :     if (nproc_fft>1) then
    6197              :       call timab(543,1,tsec)
    6198              :       call xmpi_ialltoall(zmpi2(:,:,:,:,idat),2*md1*md2proc*nd3proc, &
    6199              :                           zmpi1(:,:,:,:,idat),2*md1*md2proc*nd3proc,comm_fft,requests(idat))
    6200              :       call timab(543,2,tsec)
    6201              :     end if
    6202              :  end do
    6203              : 
    6204              :  do idat=1,ndat
    6205              :     if (nproc_fft>1) call xmpi_wait(requests(idat),ierr)
    6206              :     ! Loop over the z treated by this node.
    6207              :     do j3=1,nd3proc
    6208              :       if (me_fft*nd3proc+j3 <= n3) then
    6209              :         Jp2st=1; J2st=1
    6210              : 
    6211              :         ! Loop over G_y in the small box.
    6212              :         do j=1,m2eff,lot1
    6213              :           ma=j
    6214              :           mb=min(j+(lot1-1),m2eff)
    6215              :           n1dfft=mb-ma+1
    6216              : 
    6217              :           ! Zero-pad input.
    6218              :           ! input:  G1,G2,R3,JG2,(Rp3)
    6219              :           ! output: G2,G1,R3,JG2,(Rp3)
    6220              :           if (nproc_fft==1) then
    6221              :             call mpiswitch_cent(j3,n1dfft,Jp2st,J2st,lot1,max1,md1,m1,n1,&
    6222              :              md2proc,nd3proc,nproc_fft,ioption,zmpi2(:,:,:,:,idat),zw,max2,m2,n2)
    6223              :           else
    6224              :             call mpiswitch_cent(j3,n1dfft,Jp2st,J2st,lot1,max1,md1,m1,n1,&
    6225              :              md2proc,nd3proc,nproc_fft,ioption,zmpi1(:,:,:,:,idat),zw,max2,m2,n2)
    6226              :           end if
    6227              : 
    6228              :           ! Transform along x
    6229              :           ! input:  G2,G1,R3,(Rp3)
    6230              :           ! output: G2,R1,R3,(Rp3)
    6231              :           if (n1dfft == lot1) then
    6232              :             call dfftw_execute_dft(bw_plan1_lot, zw, zt(1,j,1))
    6233              :           else
    6234              :             call dfftw_execute_dft(bw_plan1_rest, zw, zt(1,j,1))
    6235              :           end if
    6236              : 
    6237              :         end do ! j
    6238              : 
    6239              :         ! Transform along y axis (take into account c2c or c2r case).
    6240              :         ! Must loop over the full box.
    6241              :         do j=1,n1eff,lot2
    6242              :           ma=j
    6243              :           mb=min(j+(lot2-1),n1eff)
    6244              :           n1dfft=mb-ma+1
    6245              :           includelast=1
    6246              : 
    6247              :           if (cplexwf==1) then
    6248              :             jeff=2*j-1
    6249              :             if (mb==n1eff .and. n1eff*2/=n1) includelast=0
    6250              :           end if
    6251              : 
    6252              :           ! Zero-pad the input.
    6253              :           ! input:  G2,R1,R3,(Rp3)
    6254              :           ! output: R1,G2,R3,(Rp3)
    6255              :           if (cplexwf==2) then
    6256              :             call switch_cent(n1dfft,max2,m2,n2,lot2,n1,lzt,zt(1,1,j),zw)
    6257              :           else
    6258              :             call switchreal_cent(includelast,n1dfft,max2,n2,lot2,m1zt,lzt,zt(1,1,jeff),zw)
    6259              :           end if
    6260              : 
    6261              :           ! input:  R1,G2,R3,(Rp3)
    6262              :           ! output: R1,R2,R3,(Rp3)
    6263              :           if (n1dfft == lot2) then
    6264              :             call dfftw_execute_dft(bw_plan2_lot, zw, zr(1,j,1,j3,idat))
    6265              :           else
    6266              :             call dfftw_execute_dft(bw_plan2_rest, zw, zr(1,j,1,j3,idat))
    6267              :           end if
    6268              : 
    6269              :         end do
    6270              : 
    6271              :         ! Treat real wavefunctions.
    6272              :         if (cplexwf==1) then
    6273              :           n1half=n1/2
    6274              :           ! If odd
    6275              :           if (n1half*2/=n1) then
    6276              :             do i2=1,n2
    6277              :               zr(1,n1,i2,j3,idat)=zr(1,n1eff,i2,j3,idat)
    6278              :               zr(2,n1,i2,j3,idat)=zero
    6279              :             end do
    6280              :           end if
    6281              :           do i2=1,n2
    6282              :             do i1=n1half,1,-1
    6283              :               zr(1,2*i1-1,i2,j3,idat)=zr(1,i1,i2,j3,idat)
    6284              :               zr(1,2*i1  ,i2,j3,idat)=zr(2,i1,i2,j3,idat)
    6285              :               zr(2,2*i1-1,i2,j3,idat)=zero
    6286              :               zr(2,2*i1  ,i2,j3,idat)=zero
    6287              :             end do
    6288              :           end do
    6289              :         end if
    6290              : 
    6291              :       end if
    6292              : 
    6293              :    end do ! j3
    6294              :  end do ! idat
    6295              : 
    6296              :  call dfftw_destroy_plan(bw_plan3_lot)
    6297              :  if (mod(m1, lot3) /= 0) call dfftw_destroy_plan(bw_plan3_rest)
    6298              : 
    6299              :  call dfftw_destroy_plan(bw_plan1_lot)
    6300              :  if (mod(m2eff, lot1) /= 0) call dfftw_destroy_plan(bw_plan1_rest)
    6301              : 
    6302              :  call dfftw_destroy_plan(bw_plan2_lot)
    6303              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(bw_plan2_rest)
    6304              : 
    6305              :  ABI_FREE(zmpi2)
    6306              :  ABI_FREE(zw)
    6307              :  ABI_FREE(zt)
    6308              :  if (nproc_fft>1)  then
    6309              :    ABI_FREE(zmpi1)
    6310              :  end if
    6311              : 
    6312              : #else
    6313            0 :  ABI_ERROR("FFTW3 support not activated")
    6314              :  ABI_UNUSED((/cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc/))
    6315              :  ABI_UNUSED((/ max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft/))
    6316              :  ABI_UNUSED((/zf(1,1,1,1,1),zr(1,1,1,1,1)/))
    6317              : #endif
    6318              : 
    6319            0 : end subroutine fftw3_mpiback_manywf
    6320              : !!***
    6321              : 
    6322              : !----------------------------------------------------------------------
    6323              : 
    6324              : !!****f* m_fftw3/fftw3_mpiforw_manywf
    6325              : !! NAME
    6326              : !!  fftw3_mpiforw_manywf
    6327              : !!
    6328              : !! FUNCTION
    6329              : !!   Does multiple 3-dim backward FFTs from real into Fourier space
    6330              : !!   Adopt standard convention that isign=-1 for forward transform
    6331              : !!   CALCULATES THE DISCRETE FOURIERTRANSFORM
    6332              : !!
    6333              : !!   ZF(I1,I3,I2)=S_(j1,j2,j3) EXP(isign*i*2*pi*(j1*i1/n1+j2*i2/n2+j3*i3/n3)) ZR(j1,j2,j3)
    6334              : !!
    6335              : !!   in parallel using MPI/OpenMP.
    6336              : !!
    6337              : !! INPUT:
    6338              : !!   ZR: input array
    6339              : !!        ZR(1,i1,i2,i3,idat)=real(R(i1,i2,i3,idat))
    6340              : !!        ZR(2,i1,i2,i3,idat)=imag(R(i1,i2,i3,idat))
    6341              : !!        i1=1,n1 , i2=1,n2 , i3=1,n3 , idat=1,ndat
    6342              : !!   NOTE that ZR is changed by the routine
    6343              : !!
    6344              : !!   n1,n2,n3: logical dimension of the transform. As transform lengths
    6345              : !!             most products of the prime factors 2,3,5 are allowed.
    6346              : !!             The detailed table with allowed transform lengths can
    6347              : !!             be found in subroutine CTRIG
    6348              : !!   nd1,nd2,nd3: Dimension of ZR
    6349              : !!   nd3proc=((nd3-1)/nproc_fft)+1  maximal number of big box 3rd dim slices for one proc
    6350              : !!
    6351              : !! OUTPUT:
    6352              : !!   ZF: output array (note the switch of i2 and i3)
    6353              : !!        real(F(i1,i3,i2,idat))=ZF(1,i1,i3,i2,idat)
    6354              : !!        imag(F(i1,i3,i2,idat))=ZF(2,i1,i3,i2,idat)
    6355              : !!   max1 is positive or zero ; m1 >=max1+1
    6356              : !!     i1= 1... max1+1 corresponds to positive and zero wavevectors 0 ... max1
    6357              : !!     then, if m1 > max1+1, one has min1=max1-m1+1 and
    6358              : !!     i1= max1+2 ... m1 corresponds to negative wavevectors min1 ... -1
    6359              : !!     i2 and i3 have a similar definition of range
    6360              : !!   idat=1,ndat
    6361              : !!   md1,md2,md3: Dimension of ZF
    6362              : !!   md2proc=((md2-1)/nproc_fft)+1  maximal number of small box 2nd dim slices for one proc
    6363              : !!   nproc_fft: number of processors used as returned by MPI_COMM_SIZE
    6364              : !!   me_fft: [0:nproc-1] rank of the processor in the FFT communicator.
    6365              : !!   comm_fft=MPI communicator for parallel FFT.
    6366              : !!
    6367              : !! NOTES
    6368              : !!  The maximum number of processors that can reasonably be used is max(n2/2,n3/2)
    6369              : !!
    6370              : !!  It is very important to find the optimal
    6371              : !!  value of NCACHE. NCACHE determines the size of the work array ZW, that
    6372              : !!  has to fit into cache. It has therefore to be chosen to equal roughly
    6373              : !!   half the size of the physical cache in units of real*8 numbers.
    6374              : !!  The optimal value of ncache can easily be determined by numerical
    6375              : !!  experimentation. A too large value of ncache leads to a dramatic
    6376              : !!  and sudden decrease of performance, a too small value to a to a
    6377              : !!  slow and less dramatic decrease of performance. If NCACHE is set
    6378              : !!  to a value so small, that not even a single one dimensional transform
    6379              : !!  can be done in the workarray zw, the program stops with an error message.
    6380              : !!
    6381              : !! SOURCE
    6382              : 
    6383            0 : subroutine fftw3_mpiforw_manywf(cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc,&
    6384            0 : &        max1,max2,max3,m1,m2,m3,md1,md2proc,md3,zr,zf,comm_fft)
    6385              : 
    6386              : !Arguments ------------------------------------
    6387              : !scalars
    6388              :  integer,intent(in) :: cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc
    6389              :  integer,intent(in) :: max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft
    6390              : !arrays
    6391              :  real(dp),intent(inout) :: zr(2,nd1,nd2,nd3proc,ndat)
    6392              :  real(dp),intent(out) :: zf(2,md1,md3,md2proc,ndat)
    6393              : 
    6394              : !Local variables-------------------------------
    6395              : !scalars
    6396              : #ifdef HAVE_FFTW3
    6397              :  integer :: j,i1,i2,i3,idat,ierr,nproc_fft,me_fft
    6398              :  integer :: ioption,j2,j3,j2st,jp2st,lot1,lot2,lot3,lzt,m1zt,ma,mb,n1dfft,nnd3
    6399              :  integer :: m2eff,ncache,n1eff,n1half,i1inv,i2inv,i3inv,nthreads
    6400              :  integer(KIND_FFTW_PLAN) :: fw_plan1_lot,fw_plan1_rest
    6401              :  integer(KIND_FFTW_PLAN) :: fw_plan2_lot,fw_plan2_rest
    6402              :  integer(KIND_FFTW_PLAN) :: fw_plan3_lot,fw_plan3_rest
    6403              :  character(len=500) :: msg
    6404              : !arrays
    6405              :  integer :: requests(ndat)
    6406              :  real(dp) ABI_ASYNC, allocatable :: zmpi1(:,:,:,:,:),zmpi2(:,:,:,:,:) ! work arrays for MPI
    6407              :  real(dp),allocatable :: zw(:,:),zt(:,:,:) ! cache work array and array for transpositions
    6408              : ! FFT work arrays
    6409              :  real(dp) :: tsec(2)
    6410              : ! *************************************************************************
    6411              : 
    6412              :  ! FIXME must provide a default value but which one?
    6413              :  !ioption = 0
    6414              :  ioption = 1
    6415              :  !if (paral_kgb==1) ioption=1
    6416              : 
    6417              :  nproc_fft = xmpi_comm_size(comm_fft); me_fft = xmpi_comm_rank(comm_fft)
    6418              : 
    6419              :  ! find cache size that gives optimal performance on machine
    6420              :  ncache=2*max(n1,n2,n3,1024)
    6421              :  !ncache=2*max(n1,n2,n3,16*1024)
    6422              : 
    6423              :  if (ncache/(2*max(n1,n2,n3))<1) then
    6424              :    write(msg,'(5a)') &
    6425              :     'ncache has to be enlarged to be able to hold at',ch10, &
    6426              :     'least one 1-d FFT of each size even though this will',ch10,&
    6427              :     'reduce the performance for shorter transform lengths'
    6428              :    ABI_ERROR(msg)
    6429              :  end if
    6430              : 
    6431              :  ! Effective m1 and m2 (complex-to-complex or real-to-complex)
    6432              :  n1eff=n1; m2eff=m2; m1zt=n1
    6433              :  if (cplexwf==1) then
    6434              :    n1eff=(n1+1)/2; m2eff=m2/2+1; m1zt=2*(n1/2+1)
    6435              :  end if
    6436              : 
    6437              :  lzt=m2eff
    6438              :  if (mod(m2eff,2)==0) lzt=lzt+1
    6439              :  if (mod(m2eff,4)==0) lzt=lzt+1
    6440              : 
    6441              :  ! maximal number of big box 3rd dim slices for all procs
    6442              :  nnd3=nd3proc*nproc_fft
    6443              : 
    6444              :  ABI_MALLOC(zw,(2,ncache/2))
    6445              :  ABI_MALLOC(zt,(2,lzt,m1zt))
    6446              :  ABI_MALLOC(zmpi2,(2,md1,md2proc,nnd3,ndat))
    6447              :  if (nproc_fft>1)  then
    6448              :    ABI_MALLOC(zmpi1,(2,md1,md2proc,nnd3,ndat))
    6449              :  end if
    6450              : 
    6451              :  ! Create plans.
    6452              :  ! The prototype for sfftw_plan_many_dft is:
    6453              :  ! sfftw_plan_many_dft(rank, n, howmany,
    6454              :  !   fin,  iembed, istride, idist,
    6455              :  !   fout, oembed, ostride, odist, isign, my_flags)
    6456              : 
    6457              :  lot2=ncache/(2*n2)
    6458              :  lot1=ncache/(2*n1)
    6459              :  lot3=ncache/(2*n3)
    6460              : 
    6461              :  nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
    6462              :  !nthreads = 1
    6463              : 
    6464              :  fw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    6465              :     zw, [ncache/2], lot3, 1,                          &
    6466              :     zw, [ncache/2], lot3, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6467              : 
    6468              :  if (mod(m1, lot3) /= 0) then
    6469              :    fw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(m1, lot3), &
    6470              :     zw, [ncache/2], lot3, 1,                                      &
    6471              :     zw, [ncache/2], lot3, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6472              :  end if
    6473              : 
    6474              :  fw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1, &
    6475              :     zt, [lzt, m1zt],   lzt,  1,                       &
    6476              :     zw, [ncache/2], lot1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6477              : 
    6478              :  if (mod(m2eff, lot1) /= 0) then
    6479              :    fw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(m2eff, lot1), &
    6480              :     zt, [lzt, m1zt],   lzt, 1,                                       &
    6481              :     zw, [ncache/2], lot1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6482              :  end if
    6483              : 
    6484              :  fw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2, &
    6485              :     zr, [nd1,nd2,nd3proc,ndat], nd1, 1,               &
    6486              :     zw, [ncache/2], lot2, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6487              : 
    6488              :  if (mod(n1eff, lot2) /= 0) then
    6489              :    fw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2), &
    6490              :     zr, [nd1,nd2,nd3proc,ndat], nd1, 1,                             &
    6491              :     zw, [ncache/2], lot2, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6492              :  end if
    6493              : 
    6494              :  do idat=1,ndat
    6495              :    ! Loop over the z-planes treated by this node
    6496              :    do j3=1,nd3proc
    6497              : 
    6498              :      if (me_fft*nd3proc+j3 <= n3) then
    6499              :        Jp2st=1
    6500              :        J2st=1
    6501              : 
    6502              :        ! Treat real wavefunctions.
    6503              :        if (cplexwf==1) then
    6504              :          n1half=n1/2
    6505              :          do i2=1,n2
    6506              :            do i1=1,n1half
    6507              :              zr(1,i1,i2,j3,idat)=zr(1,2*i1-1,i2,j3,idat)
    6508              :              zr(2,i1,i2,j3,idat)=zr(1,2*i1  ,i2,j3,idat)
    6509              :            end do
    6510              :          end do
    6511              :          ! If odd
    6512              :          if(n1half*2/=n1)then
    6513              :            do i2=1,n2
    6514              :              zr(1,n1eff,i2,j3,idat)=zr(1,n1,i2,j3,idat)
    6515              :              zr(2,n1eff,i2,j3,idat)=zero
    6516              :            end do
    6517              :          end if
    6518              :        end if
    6519              : 
    6520              :        ! transform along y axis
    6521              :        ! input: R1,R2,R3,(Rp3)
    6522              :        ! input: R1,G2,R3,(Rp3)
    6523              :        do j=1,n1eff,lot2
    6524              :          ma=j
    6525              :          mb=min(j+(lot2-1),n1eff)
    6526              :          n1dfft=mb-ma+1
    6527              : 
    6528              :          if (n1dfft == lot2) then
    6529              :            call dfftw_execute_dft(fw_plan2_lot,  zr(1,j,1,j3,idat), zw)
    6530              :          else
    6531              :            call dfftw_execute_dft(fw_plan2_rest, zr(1,j,1,j3,idat), zw)
    6532              :          end if
    6533              : 
    6534              :          ! input:  R1,G2,R3,(Rp3)
    6535              :          ! output: G2,R1,R3,(Rp3)
    6536              :          if (cplexwf==2) then
    6537              :            call unswitch_cent(n1dfft,max2,m2,n2,lot2,n1,lzt,zw,zt(1,1,j))
    6538              :          else
    6539              :            call unswitchreal_cent(n1dfft,max2,n2,lot2,n1,lzt,zw,zt(1,1,2*j-1))
    6540              :          end if
    6541              :        end do
    6542              : 
    6543              :        ! transform along x axis
    6544              :        ! input: G2,R1,R3,(Rp3)
    6545              :        do j=1,m2eff,lot1
    6546              :          ma=j
    6547              :          mb=min(j+(lot1-1),m2eff)
    6548              :          n1dfft=mb-ma+1
    6549              : 
    6550              :          if (n1dfft == lot1) then
    6551              :            call dfftw_execute_dft(fw_plan1_lot,  zt(1,j,1), zw)
    6552              :          else
    6553              :            call dfftw_execute_dft(fw_plan1_rest, zt(1,j,1), zw)
    6554              :          end if
    6555              :          ! output: G2,G1,R3,(Rp3)
    6556              : 
    6557              :          ! input:  G2,G1,R3,Gp2,(Rp3)
    6558              :          ! output: G1,G2,R3,Gp2,(Rp3)
    6559              :          if (nproc_fft==1) then
    6560              :            call unmpiswitch_cent(j3,n1dfft,Jp2st,J2st,lot1,max1,md1,m1,n1,&
    6561              : &            md2proc,nd3proc,nproc_fft,ioption,zw,zmpi2(:,:,:,:,idat))
    6562              :          else
    6563              :            call unmpiswitch_cent(j3,n1dfft,Jp2st,J2st,lot1,max1,md1,m1,n1,&
    6564              : &            md2proc,nd3proc,nproc_fft,ioption,zw,zmpi1(:,:,:,:,idat))
    6565              :          end if
    6566              :        end do
    6567              :      end if
    6568              :    end do ! j3
    6569              : 
    6570              :    ! Interprocessor data transposition
    6571              :    ! input:  G1,G2,R3,Gp2,(Rp3)
    6572              :    ! output: G1,G2,R3,Rp3,(Gp2)
    6573              :    if (nproc_fft>1) then
    6574              :      call timab(544,1,tsec)
    6575              :      call xmpi_ialltoall(zmpi1(:,:,:,:,idat),2*md1*md2proc*nd3proc, &
    6576              :                          zmpi2(:,:,:,:,idat),2*md1*md2proc*nd3proc,comm_fft,requests(idat))
    6577              :      call timab(544,2,tsec)
    6578              :    end if
    6579              :  end do
    6580              : 
    6581              :  do idat=1,ndat
    6582              :     if (nproc_fft>1) call xmpi_wait(requests(idat),ierr)
    6583              :    ! transform along z axis
    6584              :    ! input: G1,G2,R3,(Gp2)
    6585              : 
    6586              :    do j2=1,md2proc
    6587              :      if (me_fft*md2proc+j2 <= m2eff) then
    6588              :        ! write(std_out,*)' forwf_wf : before unscramble, j2,md2proc,me_fft,m2=',j2,md2proc,me_fft,m2
    6589              :        do i1=1,m1,lot3
    6590              :          ma=i1
    6591              :          mb=min(i1+(lot3-1),m1)
    6592              :          n1dfft=mb-ma+1
    6593              : 
    6594              :          ! input:  G1,G2,R3,(Gp2)
    6595              :          ! output: G1,R3,G2,(Gp2)
    6596              :          call unscramble(i1,j2,lot3,n1dfft,md1,n3,md2proc,nnd3,zmpi2(:,:,:,:,idat),zw)
    6597              : 
    6598              :          if (n1dfft == lot3) then
    6599              :            call dfftw_execute_dft(fw_plan3_lot, zw, zw)
    6600              :          else
    6601              :            call dfftw_execute_dft(fw_plan3_rest, zw, zw)
    6602              :          end if
    6603              : 
    6604              :          call unfill_cent(md1,md3,lot3,n1dfft,max3,m3,n3,zw,zf(1,i1,1,j2,idat))
    6605              :          ! output: G1,G3,G2,(Gp2)
    6606              :        end do
    6607              :      end if
    6608              :    end do
    6609              : 
    6610              :    if (cplexwf==1) then
    6611              :      ! Complete missing values with complex conjugate
    6612              :      ! Inverse of ix is located at nx+2-ix , except for ix=1, for which it is 1.
    6613              :      do i3=1,m3
    6614              :        i3inv=m3+2-i3
    6615              :        if(i3==1)i3inv=1
    6616              : 
    6617              :        if (m2eff>1) then
    6618              :          do i2=2,m2eff
    6619              :            i2inv=m2+2-i2
    6620              :            zf(1,1,i3inv,i2inv,idat)= zf(1,1,i3,i2,idat)
    6621              :            zf(2,1,i3inv,i2inv,idat)=-zf(2,1,i3,i2,idat)
    6622              :            do i1=2,m1
    6623              :              i1inv=m1+2-i1
    6624              :              zf(1,i1inv,i3inv,i2inv,idat)= zf(1,i1,i3,i2,idat)
    6625              :              zf(2,i1inv,i3inv,i2inv,idat)=-zf(2,i1,i3,i2,idat)
    6626              :            end do
    6627              :          end do
    6628              :        end if
    6629              :      end do
    6630              :    end if
    6631              : 
    6632              :  end do ! idat
    6633              : 
    6634              :  call dfftw_destroy_plan(fw_plan3_lot)
    6635              :  if (mod(m1, lot3) /= 0) call dfftw_destroy_plan(fw_plan3_rest)
    6636              : 
    6637              :  call dfftw_destroy_plan(fw_plan1_lot)
    6638              :  if (mod(m2eff, lot1) /= 0) call dfftw_destroy_plan(fw_plan1_rest)
    6639              : 
    6640              :  call dfftw_destroy_plan(fw_plan2_lot)
    6641              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(fw_plan2_rest)
    6642              : 
    6643              :  ABI_FREE(zmpi2)
    6644              :  ABI_FREE(zw)
    6645              :  ABI_FREE(zt)
    6646              :  if (nproc_fft>1)  then
    6647              :    ABI_FREE(zmpi1)
    6648              :  end if
    6649              : 
    6650              : #else
    6651            0 :  ABI_ERROR("FFTW3 support not activated")
    6652              :  ABI_UNUSED((/cplexwf,ndat,n1,n2,n3,nd1,nd2,nd3proc/))
    6653              :  ABI_UNUSED((/max1,max2,max3,m1,m2,m3,md1,md2proc,md3,comm_fft/))
    6654              :  ABI_UNUSED((/zf(1,1,1,1,1),zr(1,1,1,1,1)/))
    6655              : #endif
    6656              : 
    6657            0 : end subroutine fftw3_mpiforw_manywf
    6658              : !!***
    6659              : 
    6660              : !----------------------------------------------------------------------
    6661              : 
    6662              : !!****f* m_fftw3/fftw3_applypot_many
    6663              : !! NAME
    6664              : !!  fftw3_applypot_many
    6665              : !!
    6666              : !! FUNCTION
    6667              : !! Applies the local real space potential to multiple wavefunctions in Fourier space
    6668              : !!
    6669              : !! INPUTS
    6670              : !!   ZF: Wavefunction (input/output) (note the switch of i2 and i3)
    6671              : !!        real(F(i1,i3,i2,idat))=ZF(1,i1,i3,i2,idat)
    6672              : !!        imag(F(i1,i3,i2,idat))=ZF(2,i1,i3,i2,idat)
    6673              : !!   max1 is positive or zero ; m1 >=max1+1
    6674              : !!   i1= 1... max1+1 corresponds to positive and zero wavevectors 0 ... max1
    6675              : !!   then, if m1 > max1+1, one has min1=max1-m1+1 and
    6676              : !!   i1= max1+2 ... m1 corresponds to negative wavevectors min1 ... -1
    6677              : !!   i2 and i3 have a similar definition of range
    6678              : !!   idat=1,ndat
    6679              : !!   md1,md2,md3: Dimension of ZF (input as well as output), distributed on different procs
    6680              : !!   md2proc=((md2-1)/nproc_fft)+1  maximal number of small box 2nd dim slices for one proc
    6681              : !!
    6682              : !!   POT: Potential
    6683              : !!        POT(cplex*i1,i2,i3)
    6684              : !!        cplex=1 or 2 ,  i1=1,n1 , i2=1,n2 , i3=1,n3
    6685              : !!   nd1,nd2,nd3: dimension of pot
    6686              : !!   comm_fft: MPI communicator
    6687              : !!   nproc_fft: number of processors used as returned by MPI_COMM_SIZE
    6688              : !!   me_fft: [0:nproc_fft-1] number of processor as returned by MPI_COMM_RANK
    6689              : !!    n1,n2,n3: logical dimension of the transform. As transform lengths
    6690              : !!              most products of the prime factors 2,3,5 are allowed.
    6691              : !!             The detailed table with allowed transform lengths can
    6692              : !!             be found in subroutine CTRIG
    6693              : !!
    6694              : !! NOTES:
    6695              : !!   PERFORMANCE CONSIDERATIONS:
    6696              : !!   The maximum number of processors that can reasonably be used is max(n2/2,n3/2)
    6697              : !!
    6698              : !!   It is very important to find the optimal
    6699              : !!   value of NCACHE. NCACHE determines the size of the work array ZW, that
    6700              : !!   has to fit into cache. It has therefore to be chosen to equal roughly
    6701              : !!    half the size of the physical cache in units of real*8 numbers.
    6702              : !!   The optimal value of ncache can easily be determined by numerical
    6703              : !!   experimentation. A too large value of ncache leads to a dramatic
    6704              : !!   and sudden decrease of performance, a too small value to a to a
    6705              : !!   slow and less dramatic decrease of performance. If NCACHE is set
    6706              : !!   to a value so small, that not even a single one dimensional transform
    6707              : !!   can be done in the workarray zw, the program stops with an error message.
    6708              : !!
    6709              : !! SOURCE
    6710              : 
    6711              : 
    6712            0 : subroutine fftw3_applypot_many(cplexwf,cplex,ndat,n1,n2,n3,nd1,nd2,nd3,nd3proc,&
    6713              :                                 max1i,max2i,max3i,m1i,m2i,m3i,md1,md2proc,md3,&
    6714            0 :                                 max1o,max2o,max3o,m1o,m2o,m3o,comm_fft,nproc_fft,me_fft,pot,zf)
    6715              : 
    6716              : !Arguments ------------------------------------
    6717              :  integer,intent(in) :: cplexwf,cplex,ndat,n1,n2,n3,nd1,nd2,nd3,nd3proc
    6718              :  integer,intent(in) :: max1i,max2i,max3i,m1i,m2i,m3i,md1,md2proc,md3
    6719              :  integer,intent(in) :: max1o,max2o,max3o,m1o,m2o,m3o,comm_fft,nproc_fft,me_fft
    6720              :  real(dp),intent(in) :: pot(cplex*nd1,nd2,nd3)
    6721              :  real(dp),intent(inout) :: zf(2,md1,md3,md2proc,ndat)
    6722              : 
    6723              : !Local variables-------------------------------
    6724              : !scalars
    6725              : #ifdef HAVE_FFTW3
    6726              :  integer,parameter :: unused0=0
    6727              :  integer :: j,i1,i2,i3,idat,ierr,j3glob,nthreads
    6728              :  integer :: ioption,j2,j3,lzt,m1zt,ma,mb,n1dfft,nnd3,lot1,lot2,lot3
    6729              :  integer :: m2eff,ncache,n1eff,i1inv,i2inv,i3inv,jeff,includelast,j2stb
    6730              :  integer :: jx,j2stf,Jp2stb,Jp2stf,m2ieff,m2oeff
    6731              :  integer(KIND_FFTW_PLAN) :: bw_plan1_lot,bw_plan1_rest
    6732              :  integer(KIND_FFTW_PLAN) :: bw_plan2_lot,bw_plan2_rest
    6733              :  integer(KIND_FFTW_PLAN) :: bw_plan3_lot,bw_plan3_rest
    6734              :  integer(KIND_FFTW_PLAN) :: fw_plan1_lot,fw_plan1_rest
    6735              :  integer(KIND_FFTW_PLAN) :: fw_plan2_lot,fw_plan2_rest
    6736              :  integer(KIND_FFTW_PLAN) :: fw_plan3_lot,fw_plan3_rest
    6737              :  character(len=500) :: msg
    6738              : !arrays
    6739              :  integer :: requests(ndat)
    6740              :  real(dp) :: tsec(2)
    6741              :  real(dp) ABI_ASYNC, allocatable :: zmpi1(:,:,:,:,:),zmpi2(:,:,:,:,:) ! work arrays for MPI
    6742              :  real(dp),allocatable :: zw(:,:),zt(:,:,:) ! cache work array and array for transpositions
    6743              : ! FFT work arrays
    6744              : ! *************************************************************************
    6745              : 
    6746              :  !ioption=0 ! This was in the old version.
    6747              :  ioption=1 ! This one is needed to be compatible with paral_kgb
    6748              : 
    6749              :  ncache=2*max(n1,n2,n3,1024)
    6750              :  if (ncache/(2*max(n1,n2,n3)) < 1) then
    6751              :    write(msg,"(5a)") &
    6752              :     'ncache has to be enlarged to be able to hold at',ch10,&
    6753              :     'least one 1-d FFT of each size even though this will',ch10,&
    6754              :     'reduce the performance for shorter transform lengths'
    6755              :    ABI_ERROR(msg)
    6756              :  end if
    6757              : 
    6758              :  !call wrtout(std_out,"applypot with non-blocking IALLTOALL + FFTW3")
    6759              :  !write(std_out,"(a,i0)")"in applypot_many with ndat: ",ndat
    6760              : 
    6761              :  ! Effective m1 and m2 (complex-to-complex or real-to-complex)
    6762              :  n1eff=n1; m2ieff=m2i; m2oeff=m2o; m1zt=n1
    6763              :  if (cplexwf==1) then
    6764              :    n1eff=(n1+1)/2; m2ieff=m2i/2+1; m2oeff=m2o/2+1; m1zt=2*(n1/2+1)
    6765              :  end if
    6766              : 
    6767              :  m2eff=max(m2ieff,m2oeff)
    6768              :  lzt=m2eff
    6769              :  if (mod(m2eff,2) == 0) lzt=lzt+1
    6770              :  if (mod(m2eff,4) == 0) lzt=lzt+1
    6771              : 
    6772              :  ! maximal number of big box 3rd dim slices for all procs
    6773              :  nnd3=nd3proc*nproc_fft
    6774              : 
    6775              :  ABI_MALLOC(zw,(2,ncache/2))
    6776              :  ABI_MALLOC(zt,(2,lzt,m1zt))
    6777              :  ABI_MALLOC(zmpi2,(2,md1,md2proc,nnd3,ndat))
    6778              :  if (nproc_fft > 1)  then
    6779              :    ABI_MALLOC(zmpi1,(2,md1,md2proc,nnd3,ndat))
    6780              :  end if
    6781              : 
    6782              :  lot3=ncache/(2*n3)
    6783              :  lot1=ncache/(2*n1)
    6784              :  lot2=ncache/(2*n2)
    6785              : 
    6786              :  nthreads = xomp_get_num_threads(open_parallel=.TRUE.)
    6787              :  !nthreads = 1
    6788              : 
    6789              :  ! The prototype for sfftw_plan_many_dft is:
    6790              :  ! sfftw_plan_many_dft(rank, n, howmany,
    6791              :  !   fin,  iembed, istride, idist,
    6792              :  !   fout, oembed, ostride, odist, isign, my_flags)
    6793              : 
    6794              :  ! Create plans for G --> R (see back_wf)
    6795              :  bw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    6796              :     zw, [ncache/2], lot3, 1,                          &
    6797              :     zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6798              : 
    6799              :  if (mod(m1i, lot3) /= 0) then
    6800              :    bw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(m1i, lot3),&
    6801              :       zw, [ncache/2], lot3, 1,                                    &
    6802              :       zw, [ncache/2], lot3, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6803              :  end if
    6804              : 
    6805              :  bw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1, &
    6806              :     zw, [ncache/2],  lot1, 1,                         &
    6807              :     zt, [lzt, m1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6808              : 
    6809              :  if (mod(m2ieff, lot1) /= 0) then
    6810              :    bw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(m2ieff, lot1), &
    6811              :       zw, [ncache/2],  lot1, 1,                                       &
    6812              :       zt, [lzt, m1zt], lzt, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6813              :  end if
    6814              : 
    6815              :  !TODO this won't work if iclexwf==1
    6816              :  ! Recheck this
    6817              :  bw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2, &
    6818              :     zw, [ncache/2], lot2, 1,                          &
    6819              :     zw, [ncache/2], lot2, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6820              : 
    6821              :  if (mod(n1eff, lot2) /= 0) then
    6822              :    bw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2), &
    6823              :       zw, [ncache/2], lot2, 1,                                      &
    6824              :       zw, [ncache/2], lot2, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    6825              :  end if
    6826              : 
    6827              :  ! Create plans for G --> R (see forw_wf)
    6828              :  fw_plan3_lot = dplan_many_dft_2D(1, [n3], lot3, &
    6829              :     zw, [ncache/2], lot3, 1,                          &
    6830              :     zw, [ncache/2], lot3, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6831              : 
    6832              :  if (mod(m1o, lot3) /= 0) then
    6833              :    fw_plan3_rest = dplan_many_dft_2D(1, [n3], mod(m1o, lot3),&
    6834              :     zw, [ncache/2], lot3, 1,                                      &
    6835              :     zw, [ncache/2], lot3, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6836              :  end if
    6837              : 
    6838              :  fw_plan1_lot = dplan_many_dft_2D(1, [n1], lot1,&
    6839              :     zt, [lzt, m1zt], lzt,  1,                        &
    6840              :     zw, [ncache/2],  lot1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6841              : 
    6842              :  if (mod(m2oeff, lot1) /= 0) then
    6843              :    fw_plan1_rest = dplan_many_dft_2D(1, [n1], mod(m2oeff, lot1),&
    6844              :     zt, [lzt, m1zt], lzt,  1,                                        &
    6845              :     zw, [ncache/2],  lot1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6846              :  end if
    6847              : 
    6848              :  fw_plan2_lot = dplan_many_dft_2D(1, [n2], lot2,&
    6849              :     zw, [ncache/2], lot2, 1,                         &
    6850              :     zw, [ncache/2], lot2, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6851              : 
    6852              :  if (mod(n1eff, lot2) /= 0) then
    6853              :    fw_plan2_rest = dplan_many_dft_2D(1, [n2], mod(n1eff,lot2),&
    6854              :     zw, [ncache/2], lot2, 1,                                       &
    6855              :     zw, [ncache/2], lot2, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    6856              :  end if
    6857              : 
    6858              :  ! Here we take advantage of non-blocking IALLTOALL:
    6859              :  ! Perform the first step of MPI-FFT for ndat wavefunctions.
    6860              :  do idat=1,ndat
    6861              :    !
    6862              :    ! transform along z axis
    6863              :    ! input: G1,G3,G2,(Gp2)
    6864              :    do j2=1,md2proc
    6865              :      if (me_fft*md2proc+j2 <= m2ieff) then
    6866              :        do i1=1,m1i,lot3
    6867              :          ma=i1
    6868              :          mb=min(i1+(lot3-1),m1i)
    6869              :          n1dfft=mb-ma+1
    6870              : 
    6871              :          ! zero-pad n1dfft G_z lines
    6872              :          ! input: G1,G3,G2,(Gp2)
    6873              :          call fill_cent(md1,md3,lot3,n1dfft,max3i,m3i,n3,zf(1,i1,1,j2,idat),zw)
    6874              : 
    6875              :          if (n1dfft == lot3) then
    6876              :            call dfftw_execute_dft(bw_plan3_lot, zw, zw)
    6877              :          else
    6878              :            call dfftw_execute_dft(bw_plan3_rest, zw, zw)
    6879              :          end if
    6880              : 
    6881              :          ! Local rotation.
    6882              :          ! input:  G1,R3,G2,(Gp2)
    6883              :          ! output: G1,G2,R3,(Gp2)
    6884              :          call scramble(i1,j2,lot3,n1dfft,md1,n3,md2proc,nnd3,zw,zmpi2(:,:,:,:,idat))
    6885              :        end do
    6886              :      end if
    6887              :    end do
    6888              : 
    6889              :    ! Interprocessor data transposition
    6890              :    ! input:  G1,G2,R3,Rp3,(Gp2)
    6891              :    ! output: G1,G2,R3,Gp2,(Rp3)
    6892              :    if (nproc_fft > 1) then
    6893              :      call timab(543,1,tsec)
    6894              :      call xmpi_ialltoall(zmpi2(:,:,:,:,idat),2*md1*md2proc*nd3proc,&
    6895              :                          zmpi1(:,:,:,:,idat),2*md1*md2proc*nd3proc,comm_fft,requests(idat))
    6896              :      call timab(543,2,tsec)
    6897              :    end if
    6898              :  end do ! idat
    6899              : 
    6900              :  ! The second step of MPI-FFT
    6901              :  do idat=1,ndat
    6902              :     ! Make sure communication is completed.
    6903              :     if (nproc_fft>1) call xmpi_wait(requests(idat),ierr)
    6904              : 
    6905              :    do j3=1,nd3proc
    6906              :      j3glob = j3 + me_fft*nd3proc
    6907              :      if (me_fft*nd3proc+j3 <= n3) then
    6908              :        Jp2stb=1; J2stb=1
    6909              :        Jp2stf=1; J2stf=1
    6910              : 
    6911              :        ! transform along x axis
    6912              :        do j=1,m2ieff,lot1
    6913              :          ma=j
    6914              :          mb=min(j+(lot1-1),m2ieff)
    6915              :          n1dfft=mb-ma+1
    6916              : 
    6917              :          ! Zero-pad input.
    6918              :          ! input:  G1,G2,R3,G2,(Rp3)
    6919              :          ! output: G2,G1,R3,G2,(Rp3)
    6920              :          if (nproc_fft == 1) then
    6921              :            call mpiswitch_cent(j3,n1dfft,Jp2stb,J2stb,lot1,max1i,md1,m1i,n1,&
    6922              :            md2proc,nd3proc,nproc_fft,ioption,zmpi2(:,:,:,:,idat),zw, unused0, unused0, unused0)
    6923              :          else
    6924              :            call mpiswitch_cent(j3,n1dfft,Jp2stb,J2stb,lot1,max1i,md1,m1i,n1,&
    6925              :            md2proc,nd3proc,nproc_fft,ioption,zmpi1(:,:,:,:,idat),zw, unused0, unused0, unused0)
    6926              :          end if
    6927              : 
    6928              :          ! Transform along x
    6929              :          ! input:  G2,G1,R3,(Rp3)
    6930              :          ! output: G2,R1,R3,(Rp3)
    6931              :          if (n1dfft == lot1) then
    6932              :            call dfftw_execute_dft(bw_plan1_lot, zw, zt(1,j,1))
    6933              :          else
    6934              :            call dfftw_execute_dft(bw_plan1_rest, zw, zt(1,j,1))
    6935              :          end if
    6936              :        end do
    6937              : 
    6938              :        ! Transform along y axis (take into account c2c or c2r case).
    6939              :        ! Must loop over the full box.
    6940              :        !TODO this won't work
    6941              :        if (cplexwf==1) then
    6942              :          if(mod(lot2,2).ne.0) lot2=lot2-1 ! needed to introduce jeff
    6943              :        end if
    6944              : 
    6945              :        do j=1,n1eff,lot2
    6946              :          ma=j
    6947              :          mb=min(j+(lot2-1),n1eff)
    6948              :          n1dfft=mb-ma+1
    6949              :          jeff=j
    6950              :          includelast=1
    6951              : 
    6952              :          if (cplexwf==1) then
    6953              :            jeff=2*j-1
    6954              :            includelast=1
    6955              :            if (mb==n1eff .and. n1eff*2/=n1) includelast=0
    6956              :          end if
    6957              : 
    6958              :          ! Zero-pad the input.
    6959              :          !  input: G2,R1,R3,(Rp3)
    6960              :          ! output: R1,G2,R3,(Rp3)
    6961              :          if (cplexwf==2) then
    6962              :            call switch_cent(n1dfft,max2i,m2i,n2,lot2,n1,lzt,zt(1,1,jeff),zw)
    6963              :          else
    6964              :            call switchreal_cent(includelast,n1dfft,max2i,n2,lot2,m1zt,lzt,zt(1,1,jeff),zw)
    6965              :          end if
    6966              : 
    6967              :          ! input:  R1,G2,R3,(Rp3)
    6968              :          ! output: R1,R2,R3,(Rp3)
    6969              :          ! Be careful here
    6970              :          if (n1dfft == lot2) then
    6971              :            call dfftw_execute_dft(bw_plan2_lot, zw, zw)
    6972              :          else
    6973              :            call dfftw_execute_dft(bw_plan2_rest, zw, zw)
    6974              :          end if
    6975              : 
    6976              :          ! Multiply with potential in real space
    6977              :          jx=cplex*(jeff-1)+1
    6978              :          call multpot(cplexwf,cplex,includelast,nd1,nd2,n2,lot2,n1dfft,pot(jx,1,j3glob),zw)
    6979              : 
    6980              :          ! TRANSFORM BACK IN FOURIER SPACE
    6981              :          ! transform along y axis
    6982              :          ! input: R1,R2,R3,(Rp3)
    6983              :          if (n1dfft == lot2) then
    6984              :            call dfftw_execute_dft(fw_plan2_lot,  zw, zw)
    6985              :          else
    6986              :            call dfftw_execute_dft(fw_plan2_rest, zw, zw)
    6987              :          end if
    6988              : 
    6989              :          !  input: R1,G2,R3,(Rp3)
    6990              :          ! output: G2,R1,R3,(Rp3)
    6991              :          if (cplexwf==2) then
    6992              :            call unswitch_cent(n1dfft,max2o,m2o,n2,lot2,n1,lzt,zw,zt(1,1,jeff))
    6993              :          else
    6994              :            call unswitchreal_cent(n1dfft,max2o,n2,lot2,n1,lzt,zw,zt(1,1,jeff))
    6995              :          end if
    6996              :        end do ! j
    6997              : 
    6998              :        ! transform along x axis
    6999              :        ! input:  R2,R1,R3,(Rp3)
    7000              :        ! output: R2,G1,R3,(Rp3)
    7001              :        do j=1,m2oeff,lot1
    7002              :          ma=j
    7003              :          mb=min(j+(lot1-1),m2oeff)
    7004              :          n1dfft=mb-ma+1
    7005              : 
    7006              :          if (n1dfft == lot1) then
    7007              :            call dfftw_execute_dft(fw_plan1_lot,  zt(1,j,1), zw)
    7008              :          else
    7009              :            call dfftw_execute_dft(fw_plan1_rest, zt(1,j,1), zw)
    7010              :          end if
    7011              : 
    7012              :          ! input:  G2,G1,R3,Gp2,(Rp3)
    7013              :          ! output: G1,G2,R3,Gp2,(Rp3)
    7014              :          if (nproc_fft == 1) then
    7015              :            call unmpiswitch_cent(j3,n1dfft,Jp2stf,J2stf,lot1,max1o,md1,m1o,n1,&
    7016              :             md2proc,nd3proc,nproc_fft,ioption,zw,zmpi2(:,:,:,:,idat))
    7017              :          else
    7018              :            call unmpiswitch_cent(j3,n1dfft,Jp2stf,J2stf,lot1,max1o,md1,m1o,n1,&
    7019              :             md2proc,nd3proc,nproc_fft,ioption,zw,zmpi1(:,:,:,:,idat))
    7020              :          end if
    7021              :        end do ! j
    7022              :      end if
    7023              :    end do
    7024              : 
    7025              :    ! Interprocessor data transposition
    7026              :    ! input:  G1,G2,R3,Gp2,(Rp3)
    7027              :    ! output: G1,G2,R3,Rp3,(Gp2)
    7028              :    if (nproc_fft > 1) then
    7029              :      call timab(544,1,tsec)
    7030              :      call xmpi_ialltoall(zmpi1(:,:,:,:,idat),2*md1*md2proc*nd3proc, &
    7031              :                          zmpi2(:,:,:,:,idat),2*md1*md2proc*nd3proc,comm_fft,requests(idat))
    7032              :      call timab(544,2,tsec)
    7033              :    end if
    7034              :  end do
    7035              : 
    7036              :  do idat=1,ndat
    7037              :    if (nproc_fft>1) call xmpi_wait(requests(idat),ierr)
    7038              :    ! transform along z axis
    7039              :    ! input: G1,G2,R3,(Gp2)
    7040              :    !lot=ncache/(4*n3)
    7041              :    do j2=1,md2proc
    7042              :      if (me_fft*md2proc+j2 <= m2oeff) then
    7043              :        do i1=1,m1o,lot3
    7044              :          ma=i1
    7045              :          mb=min(i1+(lot3-1),m1o)
    7046              :          n1dfft=mb-ma+1
    7047              : 
    7048              :          ! input:  G1,G2,R3,(Gp2)
    7049              :          ! output: G1,R3,G2,(Gp2)
    7050              :          call unscramble(i1,j2,lot3,n1dfft,md1,n3,md2proc,nnd3,zmpi2(:,:,:,:,idat),zw)
    7051              : 
    7052              :           if (n1dfft == lot3) then
    7053              :             call dfftw_execute_dft(fw_plan3_lot, zw, zw)
    7054              :           else
    7055              :             call dfftw_execute_dft(fw_plan3_rest, zw, zw)
    7056              :           end if
    7057              : 
    7058              :          call unfill_cent(md1,md3,lot3,n1dfft,max3o,m3o,n3,zw,zf(1,i1,1,j2,idat))
    7059              :          ! output: G1,G3,G2,(Gp2)
    7060              :        end do
    7061              :      end if
    7062              :    end do
    7063              : 
    7064              :    ! Complete missing values with complex conjugate
    7065              :    ! Inverse of ix is located at nx+2-ix , except for ix=1, for which it is 1.
    7066              :    if (cplexwf==1) then
    7067              :      do i3=1,m3o
    7068              :        i3inv=m3o+2-i3
    7069              :        if (i3==1) i3inv=1
    7070              :        if (m2oeff>1)then
    7071              :          do i2=2,m2oeff
    7072              :            i2inv=m2o+2-i2
    7073              :            zf(1,1,i3inv,i2inv,idat)= zf(1,1,i3,i2,idat)
    7074              :            zf(2,1,i3inv,i2inv,idat)=-zf(2,1,i3,i2,idat)
    7075              :            do i1=2,m1o
    7076              :              i1inv=m1o+2-i1
    7077              :              zf(1,i1inv,i3inv,i2inv,idat)= zf(1,i1,i3,i2,idat)
    7078              :              zf(2,i1inv,i3inv,i2inv,idat)=-zf(2,i1,i3,i2,idat)
    7079              :            end do
    7080              :          end do
    7081              :        end if
    7082              :      end do
    7083              :    end if
    7084              : 
    7085              :  end do ! idat
    7086              : 
    7087              :  call dfftw_destroy_plan(bw_plan3_lot)
    7088              :  if (mod(m1i, lot3) /= 0) call dfftw_destroy_plan(bw_plan3_rest)
    7089              : 
    7090              :  call dfftw_destroy_plan(bw_plan1_lot)
    7091              :  if (mod(m2ieff, lot1) /= 0) call dfftw_destroy_plan(bw_plan1_rest)
    7092              : 
    7093              :  call dfftw_destroy_plan(bw_plan2_lot)
    7094              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(bw_plan2_rest)
    7095              : 
    7096              :  call dfftw_destroy_plan(fw_plan3_lot)
    7097              :  if (mod(m1o, lot3) /= 0) call dfftw_destroy_plan(fw_plan3_rest)
    7098              : 
    7099              :  call dfftw_destroy_plan(fw_plan1_lot)
    7100              :  if (mod(m2oeff, lot1) /= 0) call dfftw_destroy_plan(fw_plan1_rest)
    7101              : 
    7102              :  call dfftw_destroy_plan(fw_plan2_lot)
    7103              :  if (mod(n1eff, lot2) /= 0) call dfftw_destroy_plan(fw_plan2_rest)
    7104              : 
    7105              :  ABI_FREE(zmpi2)
    7106              :  ABI_FREE(zw)
    7107              :  ABI_FREE(zt)
    7108              :  if (nproc_fft > 1)  then
    7109              :    ABI_FREE(zmpi1)
    7110              :  end if
    7111              : 
    7112              : #else
    7113            0 :  ABI_ERROR("FFTW3 support not activated")
    7114              :  ABI_UNUSED((/cplexwf,cplex,ndat,n1,n2,n3,nd1,nd2,nd3,nd3proc/))
    7115              :  ABI_UNUSED((/max1i,max2i,max3i,m1i,m2i,m3i,md1,md2proc,md3/))
    7116              :  ABI_UNUSED((/max1o,max2o,max3o,m1o,m2o,m3o,comm_fft,nproc_fft,me_fft/))
    7117              :  ABI_UNUSED((/pot(1,1,1),zf(1,1,1,1,1)/))
    7118              : #endif
    7119              : 
    7120            0 : end subroutine fftw3_applypot_many
    7121              : !!***
    7122              : 
    7123              : !----------------------------------------------------------------------
    7124              : 
    7125              : !!****f* m_fftw3/fftw3_poisson
    7126              : !! NAME
    7127              : !! fftw3_poisson
    7128              : !!
    7129              : !! FUNCTION
    7130              : !!  Solve the Poisson equation in G-space given the density, n(r),
    7131              : !!  in real space of the FFT box.
    7132              : !!
    7133              : !! INPUTS
    7134              : !! cplex=1 if fofr is real, 2 if fofr is complex
    7135              : !! nx,ny,nz=Number of FFT points along the three directions.
    7136              : !! ldx,ldy,ldz=Leading dimension of the array nr and vg.
    7137              : !! ndat = Number of densities
    7138              : !! vg(nx*ny*nz)=Potential in reciprocal space.
    7139              : !!
    7140              : !! SIDE EFFECTS
    7141              : !! nr(cplex*ldx*ldy*ldz*ndat)
    7142              : !!    input: n(r) (real or complex)
    7143              : !!    output: the hartree potential in real space
    7144              : !!
    7145              : !! NOTES
    7146              : !!   vg is given on the FFT mesh instead of the augmented mesh [ldx,ldy,ldz]
    7147              : !!   in order to simplify the interface with the other routines operating of vg
    7148              : !!
    7149              : !! SOURCE
    7150              : 
    7151            0 : subroutine fftw3_poisson(cplex,nx,ny,nz,ldx,ldy,ldz,ndat,vg,nr)
    7152              : 
    7153              : !Arguments ------------------------------------
    7154              : !scalars
    7155              :  integer,intent(in) :: cplex,nx,ny,nz,ldx,ldy,ldz,ndat
    7156              : !arrays
    7157              :  real(dp),intent(inout) :: nr(cplex*ldx*ldy*ldz*ndat)
    7158              :  real(dp),intent(in) :: vg(nx*ny*nz)
    7159              : 
    7160              : #ifdef HAVE_FFTW3
    7161              : !Local variables-------------------------------
    7162              : !scalars
    7163              :  integer,parameter :: rank1=1,rank2=2
    7164              :  integer :: ii,jj,kk,sidx,ig,ir,vgbase,ypad
    7165              :  integer, parameter :: nthreads=1
    7166              :  integer(KIND_FFTW_PLAN) :: bw_plan_xy,bw_plan3
    7167              :  integer(KIND_FFTW_PLAN) :: fw_plan_xy,fw_plan3
    7168              :  real(dp) :: fft_fact,vg_fftfact
    7169              : ! *************************************************************************
    7170              : 
    7171              :  !write(std_out,*)"in poisson"
    7172              :  ABI_CHECK(cplex==2,"cplex!=2 not coded")
    7173              :  ABI_CHECK(ndat==1,"ndat!=1 not coded")
    7174              : 
    7175              :  fft_fact = one/(nx*ny*nz)
    7176              : 
    7177              :  ! The prototype for sfftw_plan_many_dft is:
    7178              :  ! sfftw_plan_many_dft(n, howmany,
    7179              :  !   fin,  iembed, istride, idist,
    7180              :  !   fout, oembed, ostride, odist, isign, my_flags)
    7181              : 
    7182              :  ! 1) ldx*ldy transforms along Rz.
    7183              :  fw_plan3 = fftw3_plan_many_dft(rank1, (/nz/), ldx*ldy, & ! We have to visit the entire augmented x-y plane!
    7184              :    nr, (/ldx, ldy, ldz/), ldx*ldy, 1,                  &
    7185              :    nr, (/ldx, ldy, ldz/), ldx*ldy, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    7186              : 
    7187              :  call fftw3_execute_dft(fw_plan3, nr, nr) ! Now we have nr(x,y,Gz)
    7188              :  call fftw3_destroy_plan(fw_plan3)
    7189              : 
    7190              :  ! R --> G Transforms in x-y plane
    7191              :  fw_plan_xy = fftw3_plan_many_dft(rank2, [nx,ny], 1, &
    7192              :      nr, (/ldx, ldy, ldz/), 1, 1,                   &
    7193              :      nr, (/ldx, ldy, ldz/), 1, 1, ABI_FFTW_FORWARD, ABI_FFTW_ESTIMATE, nthreads)
    7194              : 
    7195              :  ! G --> R Transforms in x-y plane
    7196              :  bw_plan_xy = fftw3_plan_many_dft(rank2, [nx, ny], 1, &
    7197              :      nr, (/ldx, ldy, ldz/), 1, 1,                    &
    7198              :      nr, (/ldx, ldy, ldz/), 1, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    7199              : 
    7200              :  ! Loop on z-planes.
    7201              :  do kk=1,nz
    7202              :    sidx = 1 + cplex*(kk-1)*ldx*ldy  !+ cplex*(dat-1) * ldx*ldy*ldz
    7203              : 
    7204              :    call fftw3_execute_dft(fw_plan_xy, nr(sidx:), nr(sidx:))
    7205              : 
    7206              :    ! At this point we have nr(Gx,Gy,Gz) on the current plane.
    7207              :    ! Multiply by vc(Gx,Gy,Gz) and then back transform immediately to get vc(x,y,Gz)
    7208              :    ! Note that nr is complex whereas vg is real.
    7209              :    ! Besides, FFTW returns not normalized FTs if sign=-1 so we have to scale by fft_fact
    7210              :    vgbase = (kk-1)*nx*ny !;vgbase = (kk-1)*ldx*ldy
    7211              : 
    7212              :    ig = 0
    7213              :    do jj=1,ny
    7214              :      ypad = cplex*(jj-1)*ldx + sidx
    7215              :      do ii=1,nx
    7216              :        ig = ig + 1
    7217              :        vg_fftfact = vg(vgbase+ig) * fft_fact
    7218              : 
    7219              :        ir = cplex*(ii-1) + ypad
    7220              :        nr(ir:ir+1) = nr(ir:ir+1) * vg_fftfact
    7221              :      end do
    7222              :    end do
    7223              : 
    7224              :    call fftw3_execute_dft(bw_plan_xy, nr(sidx:), nr(sidx:))
    7225              :  end do
    7226              : 
    7227              :  ! Free plans
    7228              :  call fftw3_destroy_plan(fw_plan_xy)
    7229              :  call fftw3_destroy_plan(bw_plan_xy)
    7230              : 
    7231              :  ! Final transforms of vc(x,y,Gz) along Gz to get vc(x,y,z)
    7232              :  bw_plan3 = fftw3_plan_many_dft(rank1, (/nz/), ldx*ldy, & ! We have to visit the entire augmented x-y plane!
    7233              :    nr, (/ldx, ldy, ldz/), ldx*ldy, 1,                  &
    7234              :    nr, (/ldx, ldy, ldz/), ldx*ldy, 1, ABI_FFTW_BACKWARD, ABI_FFTW_ESTIMATE, nthreads)
    7235              : 
    7236              :  call fftw3_execute_dft(bw_plan3, nr, nr)
    7237              :  call fftw3_destroy_plan(bw_plan3)
    7238              : 
    7239              : #else
    7240              :  ABI_UNUSED((/cplex,nx,ny,nz,ldx,ldy,ldz,ndat/))
    7241              :  ABI_UNUSED((/nr(1),vg(1)/))
    7242              : #endif
    7243              : 
    7244            0 : end subroutine fftw3_poisson
    7245              : !!**
    7246              : 
    7247              : !----------------------------------------------------------------------
    7248              : 
    7249              : END MODULE m_fftw3
    7250              : !!***
        

Generated by: LCOV version 2.3-1