LCOV - code coverage report
Current view: top level - src/65_paw - m_fourier_interpol.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 73.0 % 204 149
Test Date: 2026-09-21 13:49:52 Functions: 100.0 % 3 3

            Line data    Source code
       1              : !!****m* ABINIT/m_fourier_interpol
       2              : !! NAME
       3              : !!  m_fourier_interpol
       4              : !!
       5              : !! FUNCTION
       6              : !!  This module contains routines used to perform a Fourier interpolation.
       7              : !!  Mainly used in PAW to interpol data from/to the coarse FFT grid from/to the fine FFT grid.
       8              : !!
       9              : !! COPYRIGHT
      10              : !! Copyright (C) 2018-2026 ABINIT group (FJ, MT, MG)
      11              : !! This file is distributed under the terms of the
      12              : !! GNU General Public License, see ~abinit/COPYING
      13              : !! or http://www.gnu.org/copyleft/gpl.txt .
      14              : !!
      15              : !! SOURCE
      16              : 
      17              : #if defined HAVE_CONFIG_H
      18              : #include "config.h"
      19              : #endif
      20              : 
      21              : #include "abi_common.h"
      22              : 
      23              : MODULE m_fourier_interpol
      24              : 
      25              :  use defs_basis
      26              :  use m_abicore
      27              :  use m_errors
      28              : 
      29              :  use defs_abitypes, only : MPI_type
      30              :  use m_fft,         only : zerosym, indirect_parallel_Fourier, fourdp
      31              :  use m_pawfgr,      only : pawfgr_type,pawfgr_destroy,indgrid
      32              :  use m_mpinfo,      only : destroy_mpi_enreg, initmpi_seq
      33              : 
      34              :  implicit none
      35              : 
      36              :  private
      37              : 
      38              : !public procedures.
      39              :  public :: transgrid            ! Convert a density/potential from the coarse to the fine grid and vice versa
      40              :  public :: fourier_interpol     ! Fourier interpolation. Just a wrapper for transgrid.
      41              :  public :: fourier_interpol_seq ! Fourier interpolation without MPI-FFT.
      42              : 
      43              : CONTAINS  !========================================================================================
      44              : !!***
      45              : 
      46              : !----------------------------------------------------------------------
      47              : 
      48              : !!****f* m_fourier_interpol/transgrid
      49              : !! NAME
      50              : !! transgrid
      51              : !!
      52              : !! FUNCTION
      53              : !! Convert a given density (or potential) from the coarse to the fine rectangular grid and vice versa
      54              : !! Used in PAW calculations
      55              : !!
      56              : !! INPUTS
      57              : !!  cplex=1 if rhor[f] is real, 2 if rhor[f] is complex
      58              : !!  mpi_enreg=information about MPI parallelization
      59              : !!  nspden=number of spin-density components
      60              : !!  optgrid=+1 to go from the coarse grid towards the fine grid
      61              : !!          -1 to go from the fine grid towards the coarse grid
      62              : !!  optin= 0: input density/potential is taken from rhor(:,nspden)
      63              : !!         1: input density/potential is taken from rhog(:)     (ispden=1)
      64              : !!                                              and rhor(:,2:4) (ispden=2,3,4)
      65              : !!  optout= 0: output density/potential is given in r space in rhor(:,nspden)
      66              : !!          1: output density/potential is given in r space in rhor(:,nspden)
      67              : !!                                           and in g space in rhog(:)
      68              : !!  pawfgr <type(paw_fgr_type)>=fine rectangular grid parameters
      69              : !!    %nfftc=number of points in the coarse FFT box
      70              : !!    %nfft =number of points in the fine FFT box
      71              : !!    %ngfftc(18)=all needed information about 3D FFT, for the coarse grid
      72              : !!    %ngfft(18) =all needed information about 3D FFT, for the fine grid
      73              : !!    %coatofin(nfftc)=Index of the points of the coarse grid on the fine grid
      74              : !!    %fintocoa(nfft) =Index of the points of the fine grid on the coarse grid
      75              : !!    %usefinegrid= 1 if a fine FFT grid is used (0 otherwise)
      76              : !!  if optgrid=+1 and optin=1:
      77              : !!    rhog(2,nfftc)=Fourier transform of input density/potential on the coarse grid
      78              : !!  if optgrid=-1 and optin=1:
      79              : !!    rhogf(2,nfftf)=Fourier transform of input density/potential on the fine grid
      80              : !!  if optgrid=+1
      81              : !!    rhor(cplex*nfftc,nspden)=input density/potential in r space on the coarse grid
      82              : !!  if optgrid=-1:
      83              : !!    rhorf(cplex*nfftf,nspden)=input density/potential in r space on the fine grid
      84              : !!
      85              : !! OUTPUT
      86              : !!  if optgrid=-1 and optout=1:
      87              : !!    rhog(2,nfftc)=Fourier transform of output density/potential on the coarse grid
      88              : !!  if optgrid=+1 and optout=1:
      89              : !!    rhogf(2,nfftf)=Fourier transform of output density/potential on the fine grid
      90              : !!  if optgrid=-1
      91              : !!    rhor(cplex*nfftc,nspden)=output density/potential in r space on the coarse grid
      92              : !!  if optgrid=+1:
      93              : !!    rhorf(cplex*nfftf,nspden)=output density/potential in r space on the fine grid
      94              : !!
      95              : !! SOURCE
      96              : 
      97        53326 : subroutine transgrid(cplex,mpi_enreg,nspden,optgrid,optin,optout,paral_kgb,pawfgr,rhog,rhogf,rhor,rhorf)
      98              : 
      99              : !Arguments ---------------------------------------------
     100              : !scalars
     101              :  integer,intent(in) :: cplex,nspden,optgrid,optin,optout,paral_kgb
     102              :  type(MPI_type),intent(in) :: mpi_enreg
     103              :  type(pawfgr_type),intent(in) :: pawfgr
     104              : !arrays
     105              :  real(dp),intent(inout) :: rhog(2,pawfgr%nfftc),rhogf(2,pawfgr%nfft)
     106              :  real(dp),intent(inout) :: rhor(cplex*pawfgr%nfftc,nspden),rhorf(cplex*pawfgr%nfft,nspden)
     107              : 
     108              : !Local variables ---------------------------------------
     109              : !scalars
     110              :  integer :: i1,ispden,nfftc,nfftctot,nfftf,nfftftot
     111              :  character(len=500) :: msg
     112              : !arrays
     113              :  integer :: ngfftc(18),ngfftf(18)
     114        53326 :  real(dp),allocatable :: vectg(:,:),work(:,:),workfft(:)
     115              : 
     116              : ! *************************************************************************
     117              : 
     118              :  DBG_ENTER("COLL")
     119              : 
     120              : !Tests
     121        53326 :  if(pawfgr%nfft<pawfgr%nfftc) then
     122            0 :    write(msg,'(a,2(i0,1x))')' nfft (fine grid) must be >= nfft (coarse grid) while: ',pawfgr%nfft, pawfgr%nfftc
     123            0 :    ABI_ERROR(msg)
     124              :  end if
     125              : 
     126              : !Store FFT dimensions
     127      1013194 :  nfftc=pawfgr%nfftc;ngfftc(:)=pawfgr%ngfftc(:);nfftctot=ngfftc(1)*ngfftc(2)*ngfftc(3)
     128      1013194 :  nfftf=pawfgr%nfft ;ngfftf(:)=pawfgr%ngfft (:);nfftftot=ngfftf(1)*ngfftf(2)*ngfftf(3)
     129              : 
     130              : !If no fine FFT grid is used, this is only a simple transfer
     131        53326 :  if (pawfgr%usefinegrid==0) then
     132         4052 :    if (optgrid==1) then
     133     43212698 :      rhorf=rhor
     134      1213748 :      if (optout==1.and.optin==1) rhogf=rhog
     135         4052 :      if (optout==1.and.optin/=1) then
     136            0 :        ABI_MALLOC(workfft,(cplex*nfftc))
     137            0 :        workfft(:)=rhor(:,1)
     138            0 :        call fourdp(cplex,rhogf,workfft,-1,mpi_enreg,nfftc,1,ngfftc,0)
     139            0 :        ABI_FREE(workfft)
     140              :      end if
     141              :    end if
     142         4052 :    if (optgrid==-1) then
     143            0 :      rhor=rhorf
     144            0 :      if (optout==1.and.optin==1) rhog=rhogf
     145            0 :      if (optout==1.and.optin/=1) then
     146            0 :        ABI_MALLOC(workfft,(cplex*nfftc))
     147            0 :        workfft(:)=rhorf(:,1)
     148            0 :        call fourdp(cplex,rhog,workfft,-1,mpi_enreg,nfftc,1,ngfftc,0)
     149            0 :        ABI_FREE(workfft)
     150              :      end if
     151              :    end if
     152              :    return
     153              :  end if
     154              : 
     155              : !====== FROM THE COARSE GRID TOWARDS THE FINE GRID =============
     156              : !===============================================================
     157              : !Calculate the FT of rhor to have it in the g space on the coarse grid
     158              : !Transfer the FT of rhor on the coarse grid towards the fine grid
     159              : !Then calculate the FT back to get rhorf on the fine grid
     160        49274 :  if (optgrid==1) then
     161              : 
     162        57396 :    ABI_MALLOC(work,(2,nfftc))
     163              : 
     164              : !  First spin component
     165              : !  --------------------------------------------------------------
     166        19132 :    if (optout==0) then
     167              : !    if optout=0, rhog on the fine grid is temporary (in vectg)
     168        55347 :      ABI_MALLOC(vectg,(2,nfftf))
     169   2199205646 :      vectg(:,:)=zero
     170        18449 :      if (optin==1) then
     171              :        call zerosym(rhog,2,ngfftc(1),ngfftc(2),ngfftc(3),&
     172        18252 : &       comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     173        18252 :        if(mpi_enreg%nproc_fft > 1 .and. mpi_enreg%paral_kgb==1) then
     174              :          call indirect_parallel_Fourier&
     175         1180 : &         (pawfgr%coatofin,vectg,mpi_enreg,ngfftf,ngfftc,nfftf,nfftc,paral_kgb,rhog,nfftctot)
     176              :        else
     177    231258407 :          do i1=1,nfftc
     178    693741077 :            vectg(:,pawfgr%coatofin(i1))=rhog(:,i1)
     179              :          end do
     180              :        end if
     181              :      else
     182          591 :        ABI_MALLOC(workfft,(cplex*nfftc))
     183         5516 :        workfft(:)=rhor(:,1)
     184          197 :        call fourdp(cplex,work,workfft,-1,mpi_enreg,nfftc,1,ngfftc,0)
     185          197 :        ABI_FREE(workfft)
     186              :        call zerosym(work,2,ngfftc(1),ngfftc(2),ngfftc(3),&
     187          197 : &       comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     188          197 :        if(mpi_enreg%nproc_fft > 1 .and. mpi_enreg%paral_kgb==1) then
     189              :          call indirect_parallel_Fourier&
     190            0 : &         (pawfgr%coatofin,vectg,mpi_enreg,ngfftf,ngfftc,nfftf,nfftc,paral_kgb,work,nfftctot)
     191              :        else
     192         5516 :          do i1=1,nfftc
     193        16154 :            vectg(:,pawfgr%coatofin(i1))=work(:,i1)
     194              :          end do
     195              :        end if
     196              :      end if
     197              : !    call zerosym(vectg,2,ngfftf(1),ngfftf(2),ngfftf(3),&
     198              : !    &        comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     199        55347 :      ABI_MALLOC(workfft,(cplex*nfftf))
     200        18449 :      call fourdp(cplex,vectg,workfft,1,mpi_enreg,nfftf,1,ngfftf,0)
     201    740837840 :      rhorf(:,1)=workfft(:)
     202        18449 :      ABI_FREE(workfft)
     203        18449 :      ABI_FREE(vectg)
     204              :    else
     205              : !    if optout=1, rhog on the fine grid is saved
     206              :      call zerosym(rhog,2,ngfftc(1),ngfftc(2),ngfftc(3),&
     207          683 : &     comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     208     84169667 :      rhogf(:,:)=zero
     209          683 :      if (optin==1) then
     210          683 :        if(mpi_enreg%nproc_fft > 1 .and. mpi_enreg%paral_kgb==1) then
     211              :          call indirect_parallel_Fourier&
     212           12 : &         (pawfgr%coatofin,rhogf,mpi_enreg,ngfftf,ngfftc,nfftf,nfftc,paral_kgb,rhog,nfftctot)
     213              :        else
     214     10772391 :          do i1=1,nfftc
     215     32315831 :            rhogf(:,pawfgr%coatofin(i1))=rhog(:,i1)
     216              :          end do
     217              :        end if
     218              :      else
     219            0 :        ABI_MALLOC(workfft,(cplex*nfftc))
     220            0 :        workfft(:)=rhor(:,1)
     221            0 :        call fourdp(cplex,work,workfft,-1,mpi_enreg,nfftc,1,ngfftc,0)
     222            0 :        ABI_FREE(workfft)
     223              :        call zerosym(work,2,ngfftc(1),ngfftc(2),ngfftc(3),&
     224            0 : &       comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     225            0 :        if(mpi_enreg%nproc_fft > 1 .and. mpi_enreg%paral_kgb==1) then
     226              :          call indirect_parallel_Fourier&
     227            0 : &         (pawfgr%coatofin,rhogf,mpi_enreg,ngfftf,ngfftc,nfftf,nfftc,paral_kgb,work,nfftctot)
     228              :        else
     229            0 :          do i1=1,nfftc
     230            0 :            rhogf(:,pawfgr%coatofin(i1))=work(:,i1)
     231              :          end do
     232              :        end if
     233              :      end if
     234              : !    call zerosym(rhogf,2,ngfftf(1),ngfftf(2),ngfftf(3),&
     235              : !    &        comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     236         2049 :      ABI_MALLOC(workfft,(cplex*nfftf))
     237          683 :      call fourdp(cplex,rhogf,workfft,1,mpi_enreg,nfftf,1,ngfftf,0)
     238     28057011 :      rhorf(:,1)=workfft(:)
     239          683 :      ABI_FREE(workfft)
     240              :    end if
     241              : 
     242              : !  Additional spin components
     243              : !  ----------------------------------------------------
     244        19132 :    if (nspden>=2) then
     245        10863 :      ABI_MALLOC(vectg,(2,nfftf))
     246         9422 :      do ispden=2,nspden
     247    377493362 :        vectg(:,:)=zero
     248        17403 :        ABI_MALLOC(workfft,(cplex*nfftc))
     249     36161635 :        workfft(:)=rhor(:,ispden)
     250         5801 :        call fourdp(cplex,work,workfft,-1,mpi_enreg,nfftc,1,ngfftc,0)
     251         5801 :        ABI_FREE(workfft)
     252              :        call zerosym(work,2,ngfftc(1),ngfftc(2),ngfftc(3),&
     253         5801 : &       comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     254         5801 :        if(mpi_enreg%nproc_fft > 1 .and. mpi_enreg%paral_kgb==1) then
     255              :          call indirect_parallel_Fourier&
     256          212 : &         (pawfgr%coatofin,vectg,mpi_enreg,ngfftf,ngfftc,nfftf,nfftc,paral_kgb,work,nfftctot)
     257              :        else
     258     35597639 :          do i1=1,nfftc
     259    106781739 :            vectg(:,pawfgr%coatofin(i1))=work(:,i1)
     260              :          end do
     261              :        end if
     262              : !      call zerosym(vectg,2,ngfftf(1),ngfftf(2),ngfftf(3),&
     263              : !      &          comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     264        17403 :        ABI_MALLOC(workfft,(cplex*nfftf))
     265         5801 :        call fourdp(cplex,vectg,workfft,1,mpi_enreg,nfftf,1,ngfftf,0)
     266    125974956 :        rhorf(:,ispden)=workfft(:)
     267         9422 :        ABI_FREE(workfft)
     268              :      end do
     269         3621 :      ABI_FREE(vectg)
     270              :    end if
     271              : 
     272        19132 :    ABI_FREE(work)
     273              : 
     274              : 
     275              : !  ====== FROM THE FINE GRID TOWARDS THE COARSE GRID =============
     276              : !  ==============================================================
     277              : !  Calculate the FT of rhorf to have it in the g space on the fine grid
     278              : !  Transfer the FT of rhorf on the fine grid towards the coarse grid
     279              : !  Then calculate the FT back to get rhor on the coarse grid
     280        30142 :  else if (optgrid==-1) then
     281              : 
     282        90426 :    ABI_MALLOC(work,(2,nfftf))
     283              : 
     284              : !  First spin component
     285              : !  --------------------------------------------------------------
     286        30142 :    if (optout==0) then
     287              : !    if optout=0, rhog on the fine grid is temporary (in vectg)
     288        90426 :      ABI_MALLOC(vectg,(2,nfftc))
     289   1400743747 :      vectg(:,:)=zero
     290        30142 :      if (optin==1) then
     291            0 :        do i1=1,nfftf
     292            0 :          if (pawfgr%fintocoa(i1)/=0) vectg(:,pawfgr%fintocoa(i1))=rhogf(:,i1)
     293              :        end do
     294              :      else
     295        90426 :        ABI_MALLOC(workfft,(cplex*nfftf))
     296   1408001422 :        workfft(:)=rhorf(:,1)
     297        30142 :        call fourdp(cplex,work,workfft,-1,mpi_enreg,nfftf,1,ngfftf,0)
     298        30142 :        ABI_FREE(workfft)
     299        30142 :        if(mpi_enreg%nproc_fft > 1 .and. mpi_enreg%paral_kgb==1) then
     300              :          call indirect_parallel_Fourier&
     301         1236 : &         (pawfgr%fintocoa,vectg,mpi_enreg,ngfftc,ngfftf,nfftc,nfftf,paral_kgb,work,nfftftot)
     302              :        else
     303   1322535994 :          do i1=1,nfftf
     304   2248269640 :            if (pawfgr%fintocoa(i1)/=0) vectg(:,pawfgr%fintocoa(i1))=work(:,i1)
     305              :          end do
     306              :        end if
     307              :      end if
     308              :      call zerosym(vectg,2,ngfftc(1),ngfftc(2),ngfftc(3),&
     309        30142 : &     comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     310        90426 :      ABI_MALLOC(workfft,(cplex*nfftc))
     311        30142 :      call fourdp(cplex,vectg,workfft,1,mpi_enreg,nfftc,1,ngfftc,0)
     312    476111094 :      rhor(:,1)=workfft(:)
     313        30142 :      ABI_FREE(workfft)
     314        30142 :      ABI_FREE(vectg)
     315              :    else
     316              : !    if optout=1, rhog on the fine grid is saved
     317            0 :      rhog(:,:)=zero
     318            0 :      if (optin==1) then
     319            0 :        do i1=1,nfftf
     320            0 :          if (pawfgr%fintocoa(i1)/=0) rhog(:,pawfgr%fintocoa(i1))=rhogf(:,i1)
     321              :        end do
     322              :      else
     323            0 :        ABI_MALLOC(workfft,(cplex*nfftf))
     324            0 :        workfft(:)=rhorf(:,1)
     325            0 :        call fourdp(cplex,work,workfft,-1,mpi_enreg,nfftf,1,ngfftf,0)
     326            0 :        ABI_FREE(workfft)
     327            0 :        if(mpi_enreg%nproc_fft > 1 .and. mpi_enreg%paral_kgb==1) then
     328              :          call indirect_parallel_Fourier&
     329            0 : &         (pawfgr%fintocoa,rhog,mpi_enreg,ngfftc,ngfftf,nfftc,nfftf,paral_kgb,work,nfftftot)
     330              :        else
     331            0 :          do i1=1,nfftf
     332            0 :            if (pawfgr%fintocoa(i1)/=0) rhog(:,pawfgr%fintocoa(i1))=work(:,i1)
     333              :          end do
     334              :        end if
     335              :      end if
     336              :      call zerosym(rhog,2,ngfftc(1),ngfftc(2),ngfftc(3),&
     337            0 : &     comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     338            0 :      ABI_MALLOC(workfft,(cplex*nfftc))
     339            0 :      call fourdp(cplex,rhog,workfft,1,mpi_enreg,nfftc,1,ngfftc,0)
     340            0 :      rhor(:,1)=workfft(:)
     341            0 :      ABI_FREE(workfft)
     342              :    end if
     343              : 
     344              : !  Additional spin components
     345              : !  ----------------------------------------------------
     346        30142 :    if (nspden>=2) then
     347        23718 :      ABI_MALLOC(vectg,(2,nfftc))
     348        17976 :      do ispden=2,nspden
     349    187755578 :        vectg(:,:)=zero
     350        30210 :        ABI_MALLOC(workfft,(cplex*nfftf))
     351    212305111 :        workfft(:)=rhorf(:,ispden)
     352        10070 :        call fourdp(cplex,work,workfft,-1,mpi_enreg,nfftf,1,ngfftf,0)
     353        10070 :        ABI_FREE(workfft)
     354        10070 :        if(mpi_enreg%nproc_fft > 1 .and. mpi_enreg%paral_kgb==1) then
     355              :          call indirect_parallel_Fourier&
     356          256 : &         (pawfgr%fintocoa,vectg,mpi_enreg,ngfftc,ngfftf,nfftc,nfftf,paral_kgb,work,nfftftot)
     357              :        else
     358    208556823 :          do i1=1,nfftf
     359    332477487 :            if (pawfgr%fintocoa(i1)/=0) vectg(:,pawfgr%fintocoa(i1))=work(:,i1)
     360              :          end do
     361              :        end if
     362              :        call zerosym(vectg,2,ngfftc(1),ngfftc(2),ngfftc(3),&
     363        10070 : &       comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     364        30210 :        ABI_MALLOC(workfft,(cplex*nfftc))
     365        10070 :        call fourdp(cplex,vectg,workfft,1,mpi_enreg,nfftc,1,ngfftc,0)
     366     62672906 :        rhor(:,ispden)=workfft(:)
     367        17976 :        ABI_FREE(workfft)
     368              :      end do
     369         7906 :      ABI_FREE(vectg)
     370              :    end if
     371              : 
     372        30142 :    ABI_FREE(work)
     373              : 
     374              :  end if
     375              : 
     376              :  DBG_EXIT("COLL")
     377              : 
     378              : end subroutine transgrid
     379              : !!***
     380              : 
     381              : !----------------------------------------------------------------------
     382              : 
     383              : !!****f* m_fourier_interpol/fourier_interpol
     384              : !! NAME
     385              : !! fourier_interpol
     386              : !!
     387              : !! FUNCTION
     388              : !!  Perform a Fourier interpolation. Just a wrapper for transgrid, the table giving the correspondence
     389              : !!  between the coarse and the mesh FFT grids are constructed inside the routine. This allows to specify an
     390              : !!  arbitrary FFT mesh to be used for the interpolation. Besides the routine works also in
     391              : !!  case of NC calculations since it does not require Pawfgr.
     392              : !!
     393              : !! INPUTS
     394              : !! cplex=1 if rhor[f] is real, 2 if rhor[f] is complex
     395              : !! MPI_enreg<MPI_type>=Information about MPI parallelization
     396              : !! nspden=number of spin-density components
     397              : !! nfft_in =number of points in the input FFT box (WARNING no FFT parallelism)
     398              : !! nfft_out=number of points in the output FFT box
     399              : !! ngfft_in(18)=all needed information about 3D FFT, for the input grid
     400              : !! ngfft_out(18) =all needed information about 3D FFT, for the output grid
     401              : !! optin= 0: input density/potential is taken from rhor_in(:,nspden)
     402              : !!        1: input density/potential is taken from rhog_in(:)     (ispden=1)
     403              : !!                                             and rhor_in(:,2:4) (ispden=2,3,4)
     404              : !! optout= 0: output density/potential is given in r space in rhor_out(:,nspden)
     405              : !!         1: output density/potential is given in r space in rhor_out(:,nspden)
     406              : !!                                          and in g space in rhog_out(:)
     407              : !! ngfft_asked(18)=All info on the required FFT mesh.
     408              : !!
     409              : !! OUTPUT
     410              : !!  rhor_out(cplex*nfft_out,nspden)=output density/potential in r space on the required FFT mesh.
     411              : !!  if optout=1:
     412              : !!   rhog_out(2,nfftc)=Fourier transform of output density/potential on the coarse grid
     413              : !!
     414              : !! SOURCE
     415              : 
     416         1732 : subroutine fourier_interpol(cplex,nspden,optin,optout,nfft_in,ngfft_in,nfft_out,ngfft_out,&
     417         1732 :                            MPI_enreg,rhor_in,rhor_out,rhog_in,rhog_out)
     418              : 
     419              : !Arguments ------------------------------------
     420              : !scalars
     421              :  integer,intent(in) :: cplex,nspden,optin,optout
     422              :  integer,intent(in) :: nfft_in,nfft_out
     423              :  type(MPI_type),intent(in) :: MPI_enreg
     424              : !arrays
     425              :  integer,intent(in) :: ngfft_in(18),ngfft_out(18)
     426              :  real(dp),intent(inout) :: rhor_in(cplex*nfft_in,nspden)
     427              :  real(dp),intent(inout) :: rhog_in(2,nfft_in)
     428              :  real(dp),intent(out) :: rhor_out(cplex*nfft_out,nspden)
     429              :  real(dp),intent(out) :: rhog_out(2,nfft_out)
     430              : 
     431              : !Local variables ---------------------------------------
     432              : !scalars
     433              :  integer :: nfftf,nfftc,nfftc_tot,nfftf_tot,optgrid
     434              :  logical :: ltest
     435              :  type(Pawfgr_type) :: Pawfgr
     436              : !arrays
     437              :  integer :: ngfftc(18),ngfftf(18)
     438              : 
     439              : ! *************************************************************************
     440              : 
     441        22516 :  ltest= ALL(ngfft_in(7:) == ngfft_out(7:) )
     442         1732 :  ABI_CHECK(ltest,'ngfftf_in(7:18)/=ngfftf_out(7:18)')
     443              : 
     444              :  !================================
     445              :  !=== Which one is the coarse? ===
     446              :  !================================
     447         1732 :  if (nfft_out>=nfft_in) then
     448              :    ! From coarse to fine grid. If meshes are equivalent, call transgrid anyway because of optout, optin.
     449            0 :    nfftf    =nfft_out
     450            0 :    ngfftf(:)=ngfft_out(:)
     451            0 :    nfftf_tot =PRODUCT(ngfft_out(1:3))
     452              : 
     453            0 :    nfftc    =nfft_in
     454            0 :    ngfftc(:)=ngfft_in(:)
     455            0 :    nfftc_tot =PRODUCT(ngfft_in (1:3))
     456              : 
     457            0 :    Pawfgr%usefinegrid=1
     458            0 :    if (ALL(ngfft_in(1:3)==ngfft_out(1:3))) Pawfgr%usefinegrid=0
     459            0 :    optgrid=1
     460              : 
     461              :  else
     462              :    ! From fine towards coarse.
     463         1732 :    nfftf    =nfft_in
     464         1732 :    ngfftf(:)=ngfft_in(:)
     465         6928 :    nfftf_tot =PRODUCT(ngfft_in(1:3))
     466              : 
     467         1732 :    nfftc    =nfft_out
     468         1732 :    ngfftc(:)=ngfft_out(:)
     469         6928 :    nfftc_tot =PRODUCT(ngfft_out (1:3))
     470         1732 :    Pawfgr%usefinegrid=1
     471         1732 :    optgrid=-1
     472              :  end if
     473              : 
     474         5196 :  ABI_MALLOC(Pawfgr%coatofin,(nfftc_tot))
     475         5196 :  ABI_MALLOC(Pawfgr%fintocoa,(nfftf_tot))
     476              : 
     477         1732 :  call indgrid(Pawfgr%coatofin,Pawfgr%fintocoa,nfftc_tot,nfftf_tot,ngfftc,ngfftf)
     478              : 
     479         6928 :  Pawfgr%mgfft =MAXVAL (ngfftf(1:3))
     480         6928 :  Pawfgr%nfft  =PRODUCT(ngfftf(1:3)) ! no FFT parallelism!
     481        32908 :  Pawfgr%ngfft =ngfftf
     482              : 
     483         6928 :  Pawfgr%mgfftc =MAXVAL (ngfftc(1:3))
     484         6928 :  Pawfgr%nfftc  =PRODUCT(ngfftc(1:3)) ! no FFT parallelism!
     485        32908 :  Pawfgr%ngfftc =ngfftc
     486              : 
     487         1732 :  if (optgrid==1) then
     488            0 :    call transgrid(cplex,MPI_enreg,nspden,optgrid,optin,optout,MPI_enreg%paral_kgb,Pawfgr,rhog_in ,rhog_out,rhor_in ,rhor_out)
     489              :  else
     490         1732 :    call transgrid(cplex,MPI_enreg,nspden,optgrid,optin,optout,MPI_enreg%paral_kgb,Pawfgr,rhog_out,rhog_in ,rhor_out,rhor_in)
     491              :  end if
     492              : 
     493         1732 :  call pawfgr_destroy(Pawfgr)
     494              : 
     495         1732 : end subroutine fourier_interpol
     496              : !!***
     497              : 
     498              : !----------------------------------------------------------------------
     499              : 
     500              : !!****f* m_fourier_interpol/fourier_interpol_seq
     501              : !! NAME
     502              : !! fourier_interpol_seq
     503              : !!
     504              : !! FUNCTION
     505              : !!  Perform a Fourier interpolation in sequential i.e. without MPI-FFT.
     506              : !!
     507              : !! INPUTS
     508              : !! cplex=1 if rhor is real, 2 if rhor is complex
     509              : !! nspden=number of spin-density components
     510              : !! from_nfft =number of points in the input FFT box (WARNING no FFT parallelism)
     511              : !! from_ngfft_(18)=all needed information about 3D FFT, for the input grid
     512              : !! to_nfft=number of points in the output FFT box
     513              : !! to_ngfft_out=all needed information about 3D FFT, for the output grid
     514              : !! from_rhor=Input density
     515              : !!
     516              : !! OUTPUT
     517              : !! to_rhor=Output density in r-space
     518              : !! [to_rhog]=Output density in g-space.
     519              : !!
     520              : !! SOURCE
     521              : 
     522         1732 : subroutine fourier_interpol_seq(cplex, nspden, from_nfft, from_ngfft, to_nfft, to_ngfft, from_rhor, to_rhor, &
     523            0 :                                 to_rhog) ! optional
     524              : 
     525              : !Arguments ------------------------------------
     526              : !scalars
     527              :  integer,intent(in) :: cplex, nspden, from_nfft, to_nfft
     528              : !arrays
     529              :  integer,intent(in) :: from_ngfft(18), to_ngfft(18)
     530              :  real(dp),intent(inout) :: from_rhor(cplex*from_nfft, nspden)
     531              :  real(dp),intent(out) :: to_rhor(cplex*to_nfft, nspden)
     532              :  real(dp),optional,intent(out) :: to_rhog(2, to_nfft)
     533              : 
     534              : !Local variables ---------------------------------------
     535              : !scalars
     536         1732 :  type(MPI_type) :: MPI_enreg_seq
     537              : !arrays
     538              :  integer :: ngfft_in(18),ngfft_out(18)
     539         1732 :  real(dp),allocatable :: from_rhog(:,:), to_rhog__(:,:)
     540              : ! *************************************************************************
     541              : 
     542         1732 :  ngfft_in = from_ngfft; ngfft_out = to_ngfft
     543        13856 :  ngfft_in(4:6) = ngfft_in(1:3); ngfft_out(4:6) = ngfft_out(1:3)
     544              :  ! No MPI-FFT here.
     545        38104 :  ngfft_in(9:18) = 0; ngfft_out(9:18) = 0
     546         1732 :  ngfft_in(10) = 1; ngfft_out(10) = 1
     547              : 
     548         1732 :  call initmpi_seq(MPI_enreg_seq)
     549              : 
     550              :  ! Which one is coarse? Note that this part is not very robust and can fail!
     551         1732 :  if (ngfft_in(2) * ngfft_in(3) < ngfft_out(2) * ngfft_out(3)) then
     552            0 :    call MPI_enreg_seq%distribfft%init_seq('c', ngfft_in(2), ngfft_in(3), 'all')
     553            0 :    call MPI_enreg_seq%distribfft%init_seq('f', ngfft_out(2), ngfft_out(3), 'all')
     554              :  else
     555         1732 :    call MPI_enreg_seq%distribfft%init_seq('f', ngfft_in(2), ngfft_in(3), 'all')
     556         1732 :    call MPI_enreg_seq%distribfft%init_seq('c', ngfft_out(2), ngfft_out(3), 'all')
     557              :  end if
     558              : 
     559         5196 :  ABI_MALLOC(from_rhog,  (2, from_nfft))
     560         5196 :  ABI_MALLOC(to_rhog__, (2, to_nfft))
     561              : 
     562              :  call fourier_interpol(cplex, nspden, 0, 0, from_nfft, ngfft_in, to_nfft, ngfft_out, &
     563         1732 :                        MPI_enreg_seq, from_rhor, to_rhor, from_rhog, to_rhog__)
     564              : 
     565         1732 :  if (present(to_rhog)) to_rhog = to_rhog__
     566              : 
     567         1732 :  ABI_FREE(from_rhog)
     568         1732 :  ABI_FREE(to_rhog__)
     569         1732 :  call destroy_mpi_enreg(MPI_enreg_seq)
     570              : 
     571         3464 : end subroutine fourier_interpol_seq
     572              : !!***
     573              : 
     574              : !----------------------------------------------------------------------
     575              : 
     576              : END MODULE m_fourier_interpol
     577              : !!***
        

Generated by: LCOV version 2.3-1