LCOV - code coverage report
Current view: top level - shared/common/src/28_numeric_noabirule - m_cplxtools.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 53.6 % 302 162
Test Date: 2026-09-19 15:24:51 Functions: 40.0 % 15 6

            Line data    Source code
       1              : !!****m* ABINIT/m_cplxtools
       2              : !! NAME
       3              : !!  m_cplxtools
       4              : !!
       5              : !! FUNCTION
       6              : !! This module defines helper functions to operate on complex arrays (mainly used in the GW code)
       7              : !!
       8              : !! COPYRIGHT
       9              : !! Copyright (C) 1992-2026 ABINIT group (MG)
      10              : !! This file is distributed under the terms of the
      11              : !! GNU General Public License, see ~abinit/COPYING
      12              : !! or http://www.gnu.org/copyleft/gpl.txt .
      13              : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      14              : !!
      15              : !! NOTES
      16              : !! 1) The convention about names of interfaced routine is: cplx_<name>,
      17              : !!    where <name> is equal to the name of the standard BLAS routine
      18              : !!
      19              : #if defined HAVE_CONFIG_H
      20              : #include "config.h"
      21              : #endif
      22              : 
      23              : #include "abi_common.h"
      24              : 
      25              : module m_cplxtools
      26              : 
      27              :  use, intrinsic :: iso_c_binding
      28              :  use defs_basis
      29              :  use m_abicore
      30              :  use m_errors
      31              :  use m_xmpi
      32              : 
      33              :  use m_fstrings,  only : toupper, sjoin
      34              : 
      35              :  implicit none
      36              : 
      37              :  private
      38              : 
      39              :  ! Helper functions.
      40              :  public :: cplx_fromreal
      41              :  public :: cplx_filter
      42              : 
      43              :  ! Blas1
      44              :  public :: cplx_real_zdotc
      45              :  public :: cplx_zaxpby
      46              : 
      47              :  ! Blas2
      48              :  public :: cplx_zgemv
      49              : 
      50              :  !Blas3
      51              :  public :: cplx_zgemm
      52              : 
      53              :  ! Helper functions for DFT calculations.
      54              :  public :: cplx_box2gsph
      55              :  public :: cplx_gsph2box
      56              :  public :: cplx_setaug_zero
      57              :  public :: cplx_setaug_zero_dpc
      58              :  public :: cplx_setaug_zero_spc
      59              :  public :: cplx_addtorho
      60              :  public :: cplx_mat_plus_bc
      61              : !***
      62              : 
      63              :  ! Interfaces
      64              :  interface cplx_box2gsph
      65              :    module procedure cplx_box2gsph_spc
      66              :    module procedure cplx_box2gsph_dpc
      67              :  end interface cplx_box2gsph
      68              : 
      69              :  interface cplx_gsph2box
      70              :    module procedure cplx_gsph2box_spc
      71              :    module procedure cplx_gsph2box_dpc
      72              :  end interface cplx_gsph2box
      73              : 
      74              :  interface cplx_setaug_zero
      75              :    module procedure cplx_setaug_zero_spc
      76              :    module procedure cplx_setaug_zero_dpc
      77              :  end interface cplx_setaug_zero
      78              : 
      79              :  interface cplx_addtorho
      80              :    module procedure cplx_addtorho_dpc
      81              :  end interface cplx_addtorho
      82              : 
      83              :  interface cplx_mat_plus_bc
      84              :    module procedure cplx_mat_plus_bc_spc
      85              :    module procedure cplx_mat_plus_bc_dpc
      86              :  end interface cplx_mat_plus_bc
      87              : 
      88              :  !integer,parameter,private :: MIN_SIZE = 5000
      89              : 
      90              :  complex(sp),private,parameter :: czero_spc =  (0._sp,0._sp)
      91              :  complex(sp),private,parameter :: cone_spc  =  (1._sp,0._sp)
      92              :  !complex(sp) ,parameter :: j_spc=(0._sp,1.0_sp)
      93              : 
      94              :  complex(dp),private,parameter :: czero_dpc =  (0._dp,0._dp)
      95              :  complex(dp),private,parameter :: cone_dpc  =  (1._dp,0._dp)
      96              :  !complex(dp) ,parameter :: j_dpc=(0._dp,1.0_dp)
      97              : 
      98              : CONTAINS  !========================================================================================
      99              : !!***
     100              : 
     101              : !----------------------------------------------------------------------
     102              : 
     103              : !!****f* m_cplxtools/cplx_fromreal
     104              : !! NAME
     105              : !!  cplx_fromreal
     106              : !!
     107              : !! FUNCTION
     108              : !!  Convert a real array with (real,imag) part to a complex array
     109              : !!
     110              : !! INPUTS
     111              : !!  n = Specifies the number of elements in ocplx
     112              : !!  ireal(2*n)=Input real array.
     113              : !!
     114              : !! OUTPUT
     115              : !!  ocplx(n)=Output complex array
     116              : !!
     117              : !! SOURCE
     118              : 
     119            0 : subroutine cplx_fromreal(n,ireal,ocplx)
     120              : 
     121              : !Arguments ------------------------------------
     122              : !scalars
     123              :  integer,intent(in) :: n
     124              : !arrays
     125              :  real(dp),intent(in) :: ireal(2,n)
     126              :  complex(dp),intent(out) :: ocplx(n)
     127              : 
     128              : !Local variables ------------------------------
     129              : !scalars
     130              :  integer :: ii
     131              : 
     132              : ! *************************************************************************
     133              : 
     134              : !$OMP PARALLEL DO PRIVATE(ii)
     135            0 :  do ii=1,n
     136            0 :    ocplx(ii) = DCMPLX(ireal(1,ii),ireal(2,ii))
     137              :  end do
     138              : 
     139            0 : end subroutine cplx_fromreal
     140              : !!***
     141              : 
     142              : !----------------------------------------------------------------------
     143              : 
     144              : !!****f* m_cplxtools/cplx_filter
     145              : !! NAME
     146              : !!  cplx_filter
     147              : !!
     148              : !! FUNCTION
     149              : !!  Set all the elements of x to zero where mask is .TRUE.
     150              : !!
     151              : !! INPUTS
     152              : !!  n=Specifies the number of elements in vectors x and y.
     153              : !!  mask(n)=Logical array.
     154              : !!
     155              : !! SOURCE
     156              : 
     157            0 : subroutine cplx_filter(n, x, mask)
     158              : 
     159              : !Arguments ------------------------------------
     160              : !scalars
     161              :  integer,intent(in) :: n
     162              : !arrays
     163              :  complex(dp),intent(inout) :: x(n)
     164              :  logical,intent(in) :: mask(n)
     165              : 
     166              : ! *************************************************************************
     167              : 
     168            0 :  where (mask)
     169              :    x = czero
     170              :  end where
     171              : 
     172            0 : end subroutine cplx_filter
     173              : !!***
     174              : 
     175              : !----------------------------------------------------------------------
     176              : 
     177              : !!****f* m_cplxtools/cplx_real_zdotc
     178              : !! NAME
     179              : !!  cplx_real_zdotc
     180              : !!
     181              : !! FUNCTION
     182              : !!   Perform a vector-vector operation defined as res = REAL (\Sigma (conjg(x)*y)) where x and y are n-element vectors.
     183              : !!
     184              : !! INPUTS
     185              : !!  n = Specifies the number of elements in vector x and y
     186              : !!  x,y = Input arrays.
     187              : !!
     188              : !! OUTPUT
     189              : !!  res=Real part of the scalar product.
     190              : !!
     191              : !! SOURCE
     192              : 
     193            0 : function cplx_real_zdotc(n,x,y) result(res)
     194              : 
     195              : !Arguments ------------------------------------
     196              : !scalars
     197              :  integer,intent(in) :: n
     198              : !arrays
     199              :  complex(dp),intent(in) :: x(n)
     200              :  complex(dp),intent(in) :: y(n)
     201              :  real(dp) :: res
     202              : 
     203              : !Local variables-------------------------------
     204              :  real(dp),external :: ddot
     205              : 
     206              : ! *************************************************************************
     207              : 
     208            0 :  res = ddot(2*n,x,1,y,1)
     209              : 
     210            0 : end function cplx_real_zdotc
     211              : !!***
     212              : 
     213              : !----------------------------------------------------------------------
     214              : 
     215              : !!****f* m_cplxtools/cplx_zaxpby
     216              : !! NAME
     217              : !!  cplx_zaxpby
     218              : !!
     219              : !! FUNCTION
     220              : !!  Scales two vectors, adds them to one another and stores result in the vector.
     221              : !!  y := a*x + b*y
     222              : !!
     223              : !! INPUTS
     224              : !! n = the number of elements in vectors x and y.
     225              : !! a = Specifies the scalar a.
     226              : !! x = Array.
     227              : !! b = Specifies the scalar b.
     228              : !! y = Array
     229              : !!
     230              : !! OUTPUT
     231              : !! y Contains the updated vector y.
     232              : !!
     233              : !! SOURCE
     234              : 
     235            0 : subroutine cplx_zaxpby(n,a,x,b,y)
     236              : 
     237              : !Arguments ------------------------------------
     238              : !scalars
     239              :  integer,intent(in) :: n
     240              :  complex(dp),intent(in) :: a,b
     241              : !arrays
     242              :  complex(dp),intent(in) :: x(n)
     243              :  complex(dp),intent(inout) :: y(n)
     244              : ! *************************************************************************
     245              : 
     246              : #ifdef HAVE_LINALG_AXPBY
     247            0 :  call zaxpby(n, a, x, 1, b, y, 1)
     248              : #else
     249              :  call zscal(n, b, y, 1)
     250              :  call zaxpy(n, a, x, 1, y,1)
     251              : #endif
     252              : 
     253            0 : end subroutine cplx_zaxpby
     254              : !!***
     255              : 
     256              : !----------------------------------------------------------------------
     257              : 
     258              : !!****f* m_cplxtools/cplx_zgemv
     259              : !! NAME
     260              : !!  cplx_zgemv
     261              : !!
     262              : !! FUNCTION
     263              : !! The ?gemv routines perform a matrix-vector operation defined as
     264              : !!
     265              : !! y := alpha*A*x + beta*y,
     266              : !! or
     267              : !! y := alpha*A'*x + beta*y,
     268              : !! or
     269              : !! y := alpha*conjg(A')*x + beta*y,
     270              : !!
     271              : !! where: alpha and beta are scalars, x and y are vectors, A is an m-by-n matrix.
     272              : !!
     273              : !! INPUTS
     274              : !!
     275              : !! OUTPUT
     276              : !!
     277              : !! SOURCE
     278              : 
     279            0 : subroutine cplx_zgemv(trans,nrows,ncols,mat,vec,matvec,alpha,beta)
     280              : 
     281              : !Arguments ------------------------------------
     282              : !scalars
     283              :  integer,intent(in) :: nrows,ncols
     284              :  complex(dp),optional,intent(in) :: alpha,beta
     285              :  character(len=1),intent(in) :: trans
     286              : !arrays
     287              :  complex(dp),intent(in) :: mat(nrows*ncols)
     288              :  complex(dp),intent(in) :: vec(*)
     289              :  complex(dp),intent(inout) :: matvec(*)
     290              : 
     291              : !Local variables-------------------------------
     292              : !scalars
     293              :  integer :: mm,nn,kk,lda,ldb,ldc
     294              :  complex(dp) :: my_alpha,my_beta
     295              : ! *************************************************************************
     296              : 
     297            0 :  lda = nrows
     298            0 :  mm  = nrows
     299            0 :  nn  = 1
     300            0 :  kk  = ncols
     301              : 
     302            0 :  if (toupper(trans) /= 'N') then
     303            0 :    mm = ncols
     304            0 :    kk = nrows
     305              :  end if
     306              : 
     307            0 :  ldb = kk
     308            0 :  ldc = mm
     309              : 
     310            0 :  my_alpha = cone_dpc;  if (PRESENT(alpha)) my_alpha = alpha
     311            0 :  my_beta  = czero_dpc; if (PRESENT(beta))  my_beta  = beta
     312              : 
     313            0 :  call ZGEMM(trans,"N",mm,nn,kk,my_alpha,mat,lda,vec,ldb,my_beta,matvec,ldc)
     314              : 
     315              :  !call ZGEMV(trans,mm,nn,my_alpha,mat,lda,vec,1,my_beta,matvec,1)
     316              : 
     317            0 : end subroutine cplx_zgemv
     318              : !!***
     319              : 
     320              : !----------------------------------------------------------------------
     321              : 
     322              : !!****f* m_cplxtools/cplx_zgemm
     323              : !! NAME
     324              : !!  cplx_zgemm
     325              : !!
     326              : !! FUNCTION
     327              : !!  The ?gemm routines perform a matrix-matrix operation with general matrices.
     328              : !!  The operation is defined as C := alpha*op(A)*op(B) + beta*C,
     329              : !!  where:
     330              : !!
     331              : !!  op(x) is one of op(x) = x, or op(x) = x', or op(x) = conjg(x'),
     332              : !!
     333              : !!  alpha and beta are scalars,
     334              : !!  A, B and C are matrices:
     335              : !!  op(A) is an m-by-k matrix,
     336              : !!  op(B) is a k-by-n matrix,
     337              : !!  C is an m-by-n matrix.
     338              : !!
     339              : !! INPUTS
     340              : !!
     341              : !! OUTPUT
     342              : !!
     343              : !! SOURCE
     344              : 
     345            0 : subroutine cplx_zgemm(transa,transb,npws,ncola,ncolb,amat,bmat,cmat,alpha,beta)
     346              : 
     347              : !Arguments ------------------------------------
     348              : !scalars
     349              :  integer,intent(in) :: npws,ncola,ncolb
     350              :  complex(dp),optional,intent(in) :: alpha,beta
     351              :  character(len=1),intent(in) :: transa,transb
     352              : !arrays
     353              :  complex(dp),intent(in) :: amat(npws*ncola)
     354              :  complex(dp),intent(in) :: bmat(npws*ncolb)
     355              :  complex(dp),intent(inout) :: cmat(*)
     356              : 
     357              : !Local variables-------------------------------
     358              : !scalars
     359              :  integer :: mm,nn,kk,lda,ldb,ldc
     360              :  complex(dp) :: my_alpha,my_beta
     361              : ! *************************************************************************
     362              : 
     363            0 :  lda = npws
     364            0 :  ldb = npws
     365              : 
     366            0 :  mm  = npws
     367            0 :  nn  = ncolb
     368            0 :  kk  = ncola
     369              : 
     370            0 :  if (toupper(transa) /= 'N') then
     371            0 :    mm = ncola
     372            0 :    kk = npws
     373              :  end if
     374            0 :  if (toupper(transb) /= 'N') nn = npws
     375              : 
     376            0 :  ldc = mm
     377              : 
     378            0 :  my_alpha = cone_dpc;  if (PRESENT(alpha)) my_alpha = alpha
     379            0 :  my_beta  = czero_dpc; if (PRESENT(beta))  my_beta  = beta
     380              : 
     381            0 :  call ZGEMM(transa,transb,mm,nn,kk,my_alpha,amat,lda,bmat,ldb,my_beta,cmat,ldc)
     382              : 
     383            0 : end subroutine cplx_zgemm
     384              : !!***
     385              : 
     386              : !----------------------------------------------------------------------
     387              : 
     388              : !!****f* m_cplxtools/cplx_box2gsph_spc
     389              : !! NAME
     390              : !!  cplx_box2gsph_spc
     391              : !!
     392              : !! FUNCTION
     393              : !!   Transfer data from the FFT box to the G-sphere. Target SPC complex array.
     394              : !!
     395              : !! INPUTS
     396              : !!  nx,ny,nz=physical dimension of the FFT box.
     397              : !!  ldx,ldy,ldz=Logical dimensions of the arrays.
     398              : !!  ndat=number of data in iarrbox
     399              : !!  npw_k=Number of planewaves in the G-sphere.
     400              : !!  kg_k(3,npw_k)=Reduced coordinates of the G-vectoes.
     401              : !!  iarrbox(ldx*ldy*ldz*ndat)=Complex Input arrays on the FFT box.
     402              : !!  [rscal] = Scaling factor
     403              : !!
     404              : !! OUTPUT
     405              : !!  oarrsph(npw_k*ndat)=Complex Data defined on the G-sphere.
     406              : !!
     407              : !! SOURCE
     408              : 
     409           16 : subroutine cplx_box2gsph_spc(nx,ny,nz,ldx,ldy,ldz,ndat,npw_k,kg_k,iarrbox,oarrsph,rscal)
     410              : 
     411              : !Arguments ------------------------------------
     412              : !scalars
     413              :  integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat
     414              :  real(sp),optional,intent(in) :: rscal
     415              : !arrays
     416              :  integer,intent(in) :: kg_k(3,npw_k)
     417              :  complex(sp),intent(in) :: iarrbox(ldx*ldy*ldz*ndat)
     418              :  complex(sp),intent(out) :: oarrsph(npw_k*ndat)
     419              : 
     420              : !Local variables-------------------------------
     421              :  integer :: ig,ix,iy,iz,dat,pad_sph,pad_box,ifft,ldxyz
     422              : ! *************************************************************************
     423              : 
     424           16 :  ldxyz = ldx*ldy*ldz
     425           16 :  if (.not. PRESENT(rscal)) then
     426              :    !
     427           16 :    if (ndat==1) then
     428              : !$OMP PARALLEL DO PRIVATE(ix,iy,iz,ifft)
     429       251248 :      do ig=1,npw_k
     430       251240 :        ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
     431       251240 :        iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
     432       251240 :        iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
     433       251240 :        ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     434       251248 :        oarrsph(ig) = iarrbox(ifft)
     435              :      end do
     436              :    else
     437              : !$OMP PARALLEL DO PRIVATE(pad_sph,pad_box,ix,iy,iz,ifft)
     438           40 :      do dat=1,ndat
     439           32 :        pad_sph = (dat-1)*npw_k
     440           32 :        pad_box = (dat-1)*ldxyz
     441      1005000 :        do ig=1,npw_k
     442      1004960 :          ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
     443      1004960 :          iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
     444      1004960 :          iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
     445      1004960 :          ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     446      1004992 :          oarrsph(ig+pad_sph) = iarrbox(ifft+pad_box)
     447              :        end do
     448              :      end do
     449              :    end if
     450              :    !
     451              :  else
     452            0 :    if (ndat==1) then
     453              : !$OMP PARALLEL DO PRIVATE(ix,iy,iz,ifft)
     454            0 :      do ig=1,npw_k
     455            0 :        ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
     456            0 :        iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
     457            0 :        iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
     458            0 :        ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     459            0 :        oarrsph(ig) = iarrbox(ifft) * rscal
     460              :      end do
     461              :    else
     462              : !$OMP PARALLEL DO PRIVATE(pad_sph,pad_box,ix,iy,iz,ifft)
     463            0 :      do dat=1,ndat
     464            0 :        pad_sph = (dat-1)*npw_k
     465            0 :        pad_box = (dat-1)*ldxyz
     466            0 :        do ig=1,npw_k
     467            0 :          ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
     468            0 :          iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
     469            0 :          iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
     470            0 :          ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     471            0 :          oarrsph(ig+pad_sph) = iarrbox(ifft+pad_box) * rscal
     472              :        end do
     473              :      end do
     474              :    end if
     475              :  end if
     476              : 
     477           16 : end subroutine cplx_box2gsph_spc
     478              : !!***
     479              : 
     480              : !----------------------------------------------------------------------
     481              : 
     482              : !----------------------------------------------------------------------
     483              : 
     484              : !!****f* m_cplxtools/cplx_box2gsph_dpc
     485              : !! NAME
     486              : !!  cplx_box2gsph_dpc
     487              : !!
     488              : !! FUNCTION
     489              : !!   Transfer data from the FFT box to the G-sphere. Target DP complex array.
     490              : !!
     491              : !! INPUTS
     492              : !!  nx,ny,nz=physical dimension of the FFT box.
     493              : !!  ldx,ldy,ldz=Logical dimensions of the arrays.
     494              : !!  ndat=number of data in iarrbox
     495              : !!  npw_k=Number of planewaves in the G-sphere.
     496              : !!  kg_k(3,npw_k)=Reduced coordinates of the G-vectoes.
     497              : !!  iarrbox(ldx*ldy*ldz*ndat)=Complex Input arrays on the FFT box.
     498              : !!  [rscal] = Scaling factor
     499              : !!
     500              : !! OUTPUT
     501              : !!  oarrsph(npw_k*ndat)=Complex Data defined on the G-sphere.
     502              : !!
     503              : !! SOURCE
     504              : 
     505           16 : subroutine cplx_box2gsph_dpc(nx,ny,nz,ldx,ldy,ldz,ndat,npw_k,kg_k,iarrbox,oarrsph,rscal)
     506              : 
     507              : !Arguments ------------------------------------
     508              : !scalars
     509              :  integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat
     510              :  real(dp),optional,intent(in) :: rscal
     511              : !arrays
     512              :  integer,intent(in) :: kg_k(3,npw_k)
     513              :  complex(dp),intent(in) :: iarrbox(ldx*ldy*ldz*ndat)
     514              :  complex(dp),intent(out) :: oarrsph(npw_k*ndat)
     515              : 
     516              : !Local variables-------------------------------
     517              : !scalars
     518              :  integer :: ig,ix,iy,iz,dat,pad_sph,pad_box,ifft,ldxyz
     519              : 
     520              : ! *************************************************************************
     521              : 
     522           16 :  ldxyz = ldx*ldy*ldz
     523           16 :  if (.not. PRESENT(rscal)) then
     524              :    !
     525           16 :    if (ndat==1) then
     526              : !$OMP PARALLEL DO PRIVATE(ix,iy,iz,ifft)
     527       251248 :      do ig=1,npw_k
     528       251240 :        ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
     529       251240 :        iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
     530       251240 :        iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
     531       251240 :        ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     532       251248 :        oarrsph(ig) = iarrbox(ifft)
     533              :      end do
     534              :    else
     535              : !$OMP PARALLEL DO PRIVATE(pad_sph,pad_box,ix,iy,iz,ifft)
     536           40 :      do dat=1,ndat
     537           32 :        pad_sph = (dat-1)*npw_k
     538           32 :        pad_box = (dat-1)*ldxyz
     539      1005000 :        do ig=1,npw_k
     540      1004960 :          ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
     541      1004960 :          iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
     542      1004960 :          iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
     543      1004960 :          ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     544      1004992 :          oarrsph(ig+pad_sph) = iarrbox(ifft+pad_box)
     545              :        end do
     546              :      end do
     547              :    end if
     548              :    !
     549              :  else
     550            0 :    if (ndat==1) then
     551              : !$OMP PARALLEL DO PRIVATE(ix,iy,iz,ifft)
     552            0 :      do ig=1,npw_k
     553            0 :        ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
     554            0 :        iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
     555            0 :        iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
     556            0 :        ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     557            0 :        oarrsph(ig) = iarrbox(ifft) * rscal
     558              :      end do
     559              :    else
     560              : !$OMP PARALLEL DO PRIVATE(pad_sph,pad_box,ix,iy,iz,ifft)
     561            0 :      do dat=1,ndat
     562            0 :        pad_sph = (dat-1)*npw_k
     563            0 :        pad_box = (dat-1)*ldxyz
     564            0 :        do ig=1,npw_k
     565            0 :          ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
     566            0 :          iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
     567            0 :          iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
     568            0 :          ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     569            0 :          oarrsph(ig+pad_sph) = iarrbox(ifft+pad_box) * rscal
     570              :        end do
     571              :      end do
     572              :    end if
     573              :  end if
     574              : 
     575           16 : end subroutine cplx_box2gsph_dpc
     576              : !!***
     577              : 
     578              : !----------------------------------------------------------------------
     579              : 
     580              : !!****f* m_cplxtools/cplx_gsph2box_spc
     581              : !! NAME
     582              : !! cplx_gsph2box_spc
     583              : !!
     584              : !! FUNCTION
     585              : !! Array iarrsph is defined in sphere with npw points. Insert iarrsph inside box
     586              : !! of nx*ny*nz points to define array oarrbox for fft box. rest of oarrbox is filled with 0 s.
     587              : !! targer: SPC complex arrays
     588              : !!
     589              : !! INPUTS
     590              : !! iarrsph(2,npw*ndat)= contains values for npw G vectors in basis sphere
     591              : !! ndat=number of FFT to perform.
     592              : !! npw=number of G vectors in basis at this k point
     593              : !! oarrbox(2,ldx*ldy*ldz*ndat) = fft box
     594              : !! nx,ny,nz=physical dimension of the box (oarrbox)
     595              : !! ldx,ldy,ldz=memory dimension of oarrbox
     596              : !! kg_k(3,npw)=integer coordinates of G vectors in basis sphere
     597              : !! istwf_k=option parameter that describes the storage of wfs
     598              : !!
     599              : !! OUTPUT
     600              : !!   oarrbox(ldx*ldy*ldz*ndat)
     601              : !!
     602              : !! NOTES
     603              : !! If istwf_k differs from 1, then special storage modes must be taken
     604              : !! into account, for symmetric wavefunctions coming from k=(0 0 0) or other
     605              : !! special k points.
     606              : !!
     607              : !! SOURCE
     608              : 
     609           14 : subroutine cplx_gsph2box_spc(nx,ny,nz,ldx,ldy,ldz,ndat,npw,istwf_k,kg_k,iarrsph,oarrbox)
     610              : 
     611              : !Arguments ------------------------------------
     612              : !scalars
     613              :  integer,intent(in) :: istwf_k,nx,ny,nz,ldx,ldy,ldz,ndat,npw
     614              : !arrays
     615              :  integer,intent(in) :: kg_k(3,npw)
     616              :  complex(sp),intent(in) :: iarrsph(npw*ndat)
     617              :  complex(sp),intent(out) :: oarrbox(ldx*ldy*ldz*ndat)
     618              : 
     619              : !Local variables-------------------------------
     620              : !scalars
     621              :  integer,parameter :: me_g0=1
     622              :  integer :: ix,ixinv,iy,iyinv,iz,izinv,dat,ipw,npwmin,pad_box,pad_sph,ifft,ifft_inv,ldxyz
     623              :  !character(len=500) :: msg
     624              : !arrays
     625           14 :  integer,allocatable :: ixinver(:),iyinver(:),izinver(:)
     626              : ! *************************************************************************
     627              : 
     628              : !In the case of special k-points, invariant under time-reversal,
     629              : !but not Gamma, initialize the inverse coordinates
     630              : !Remember indeed that
     631              : !u_k(G) = u_{k+G0}(G-G0); u_{-k}(G) = u_k(G)^*
     632              : !and therefore:
     633              : !u_{G0/2}(G) = u_{G0/2}(-G-G0)^*.
     634           14 :  if (istwf_k>=2) then
     635           42 :    ABI_MALLOC(ixinver,(nx))
     636           42 :    ABI_MALLOC(iyinver,(ny))
     637           42 :    ABI_MALLOC(izinver,(nz))
     638           14 :    if ( ANY(istwf_k==(/2,4,6,8/)) ) then
     639            6 :      ixinver(1)=1
     640          600 :      do ix=2,nx
     641          600 :        ixinver(ix)=nx+2-ix
     642              :      end do
     643              :    else
     644          808 :      do ix=1,nx
     645          808 :        ixinver(ix)=nx+1-ix
     646              :      end do
     647              :    end if
     648           14 :    if (istwf_k>=2 .and. istwf_k<=5) then
     649            6 :      iyinver(1)=1
     650          600 :      do iy=2,ny
     651          600 :        iyinver(iy)=ny+2-iy
     652              :      end do
     653              :    else
     654          808 :      do iy=1,ny
     655          808 :        iyinver(iy)=ny+1-iy
     656              :      end do
     657              :    end if
     658           14 :    if ( ANY(istwf_k==(/2,3,6,7/)) ) then
     659            6 :      izinver(1)=1
     660          600 :      do iz=2,nz
     661          600 :        izinver(iz)=nz+2-iz
     662              :      end do
     663              :    else
     664          808 :      do iz=1,nz
     665          808 :        izinver(iz)=nz+1-iz
     666              :      end do
     667              :    end if
     668              :  end if
     669              : 
     670           14 :  ldxyz = ldx*ldy*ldz
     671              : 
     672           14 :  if (istwf_k==1) then
     673              : 
     674              : !$OMP PARALLEL DO PRIVATE(pad_sph,pad_box,ix,iy,iz,ifft)
     675            0 :    do dat=1,ndat
     676            0 :      pad_sph = (dat-1)*npw
     677            0 :      pad_box = (dat-1)*ldxyz
     678            0 :      oarrbox(1+pad_box:ldxyz+pad_box) = czero_spc ! zero the sub-array
     679            0 :      do ipw=1,npw
     680            0 :        ix=kg_k(1,ipw); if (ix<0) ix=ix+nx; ix=ix+1
     681            0 :        iy=kg_k(2,ipw); if (iy<0) iy=iy+ny; iy=iy+1
     682            0 :        iz=kg_k(3,ipw); if (iz<0) iz=iz+nz; iz=iz+1
     683            0 :        ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     684              : #if defined __INTEL_COMPILER && defined HAVE_OPENMP
     685              :        if (ifft==0) then
     686              :          ABI_ERROR("prevent ifort+OMP from miscompiling this section on cronos")
     687              :        end if
     688              : #endif
     689            0 :        oarrbox(ifft+pad_box) = iarrsph(ipw+pad_sph)
     690              :      end do
     691              :    end do
     692              : 
     693           14 :  else if (istwf_k>=2) then
     694              :    !
     695           14 :    npwmin=1
     696           14 :    if(istwf_k==2 .and. me_g0==1) then ! If gamma point, then oarrbox must be completed
     697            0 :      do dat=1,ndat
     698            0 :        pad_sph = (dat-1)*npw
     699            0 :        pad_box = (dat-1)*ldxyz
     700            0 :        oarrbox(1+pad_box) = REAL(iarrsph(1+pad_sph))
     701              :      end do
     702              :      npwmin=2
     703              :    end if
     704              : 
     705              : !$OMP PARALLEL DO PRIVATE(pad_sph,pad_box,ix,ixinv,iy,iyinv,iz,izinv,ifft)
     706           49 :    do dat=1,ndat
     707           35 :      pad_sph = (dat-1)*npw
     708           35 :      pad_box = (dat-1)*ldxyz
     709     35000035 :      oarrbox(npwmin+pad_box:ldxyz+pad_box) = czero_spc
     710      1099574 :      do ipw=npwmin,npw
     711      1099525 :        ix=kg_k(1,ipw); if(ix<0)ix=ix+nx; ix=ix+1
     712      1099525 :        iy=kg_k(2,ipw); if(iy<0)iy=iy+ny; iy=iy+1
     713      1099525 :        iz=kg_k(3,ipw); if(iz<0)iz=iz+nz; iz=iz+1
     714      1099525 :        ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     715              :        ! Construct the coordinates of -k-G
     716      1099525 :        ixinv=ixinver(ix); iyinv=iyinver(iy); izinv=izinver(iz)
     717      1099525 :        ifft_inv = ixinv + (iyinv-1)*ldx + (izinv-1)*ldx*ldy
     718              : #if defined __INTEL_COMPILER && defined HAVE_OPENMP
     719              :        if (ifft==0 .or. ifft_inv==0) then
     720              :          ABI_ERROR("prevent ifort+OMP from miscompiling this section on cronos")
     721              :        end if
     722              : #endif
     723      1099525 :        oarrbox(ifft    +pad_box) =       iarrsph(ipw+pad_sph)
     724      1099560 :        oarrbox(ifft_inv+pad_box) = CONJG(iarrsph(ipw+pad_sph))
     725              :      end do
     726              :    end do
     727              :    !
     728              :  else
     729            0 :    ABI_ERROR("Wrong istwfk")
     730              :  end if
     731              : 
     732           14 :  if (istwf_k>=2) then
     733           14 :    ABI_FREE(ixinver)
     734           14 :    ABI_FREE(iyinver)
     735           14 :    ABI_FREE(izinver)
     736              :  end if
     737              : 
     738           14 : end subroutine cplx_gsph2box_spc
     739              : !!***
     740              : 
     741              : !----------------------------------------------------------------------
     742              : 
     743              : !!****f* m_cplxtools/cplx_gsph2box_dpc
     744              : !! NAME
     745              : !! cplx_gsph2box_dpc
     746              : !!
     747              : !! FUNCTION
     748              : !! Array iarrsph is defined in sphere with npw points. Insert iarrsph inside box
     749              : !! of nx*ny*nz points to define array oarrbox for fft box. rest of oarrbox is filled with 0 s.
     750              : !! targer: DP complex arrays
     751              : !!
     752              : !! INPUTS
     753              : !! iarrsph(2,npw*ndat)= contains values for npw G vectors in basis sphere
     754              : !! ndat=number of FFT to perform.
     755              : !! npw=number of G vectors in basis at this k point
     756              : !! oarrbox(2,ldx*ldy*ldz*ndat) = fft box
     757              : !! nx,ny,nz=physical dimension of the box (oarrbox)
     758              : !! ldx,ldy,ldz=memory dimension of oarrbox
     759              : !! kg_k(3,npw)=integer coordinates of G vectors in basis sphere
     760              : !! istwf_k=option parameter that describes the storage of wfs
     761              : !!
     762              : !! OUTPUT
     763              : !!   oarrbox(ldx*ldy*ldz*ndat)
     764              : !!
     765              : !! NOTES
     766              : !! If istwf_k differs from 1, then special storage modes must be taken
     767              : !! into account, for symmetric wavefunctions coming from k=(0 0 0) or other
     768              : !! special k points.
     769              : !!
     770              : !! SOURCE
     771              : 
     772         2016 : subroutine cplx_gsph2box_dpc(nx,ny,nz,ldx,ldy,ldz,ndat,npw,istwf_k,kg_k,iarrsph,oarrbox)
     773              : 
     774              : !Arguments ------------------------------------
     775              : !scalars
     776              :  integer,intent(in) :: istwf_k,nx,ny,nz,ldx,ldy,ldz,ndat,npw
     777              : !arrays
     778              :  integer,intent(in) :: kg_k(3,npw)
     779              :  complex(dp),intent(in) :: iarrsph(npw*ndat)
     780              :  complex(dp),intent(out) :: oarrbox(ldx*ldy*ldz*ndat)
     781              : 
     782              : !Local variables-------------------------------
     783              : !scalars
     784              :  integer,parameter :: me_g0=1
     785              :  integer :: ix,ixinv,iy,iyinv,iz,izinv,dat,ipw,npwmin,pad_box,pad_sph,ifft,ifft_inv,ldxyz
     786              :  !character(len=500) :: msg
     787              : !arrays
     788         2016 :  integer,allocatable :: ixinver(:),iyinver(:),izinver(:)
     789              : ! *************************************************************************
     790              : 
     791              : !In the case of special k-points, invariant under time-reversal,
     792              : !but not Gamma, initialize the inverse coordinates
     793              : !Remember indeed that
     794              : !u_k(G) = u_{k+G0}(G-G0); u_{-k}(G) = u_k(G)^*
     795              : !and therefore:
     796              : !u_{G0/2}(G) = u_{G0/2}(-G-G0)^*.
     797         2016 :  if (istwf_k>=2) then
     798         6048 :    ABI_MALLOC(ixinver,(nx))
     799         6048 :    ABI_MALLOC(iyinver,(ny))
     800         6048 :    ABI_MALLOC(izinver,(nz))
     801         2016 :    if ( ANY(istwf_k==(/2,4,6,8/)) ) then
     802          330 :      ixinver(1)=1
     803         7944 :      do ix=2,nx
     804         7944 :        ixinver(ix)=nx+2-ix
     805              :      end do
     806              :    else
     807        40389 :      do ix=1,nx
     808        40389 :        ixinver(ix)=nx+1-ix
     809              :      end do
     810              :    end if
     811         2016 :    if (istwf_k>=2 .and. istwf_k<=5) then
     812         1338 :      iyinver(1)=1
     813        30705 :      do iy=2,ny
     814        30705 :        iyinver(iy)=ny+2-iy
     815              :      end do
     816              :    else
     817        16620 :      do iy=1,ny
     818        16620 :        iyinver(iy)=ny+1-iy
     819              :      end do
     820              :    end if
     821         2016 :    if ( ANY(istwf_k==(/2,3,6,7/)) ) then
     822         1208 :      izinver(1)=1
     823        28626 :      do iz=2,nz
     824        28626 :        izinver(iz)=nz+2-iz
     825              :      end do
     826              :    else
     827        21576 :      do iz=1,nz
     828        21576 :        izinver(iz)=nz+1-iz
     829              :      end do
     830              :    end if
     831              :  end if
     832              : 
     833         2016 :  ldxyz = ldx*ldy*ldz
     834              : 
     835         2016 :  if (istwf_k==1) then
     836              : 
     837              : !$OMP PARALLEL DO PRIVATE(pad_sph,pad_box,ix,iy,iz,ifft)
     838            0 :    do dat=1,ndat
     839            0 :      pad_sph = (dat-1)*npw
     840            0 :      pad_box = (dat-1)*ldxyz
     841            0 :      oarrbox(1+pad_box:ldxyz+pad_box) = czero_dpc ! zero the sub-array
     842            0 :      do ipw=1,npw
     843            0 :        ix=kg_k(1,ipw); if (ix<0) ix=ix+nx; ix=ix+1
     844            0 :        iy=kg_k(2,ipw); if (iy<0) iy=iy+ny; iy=iy+1
     845            0 :        iz=kg_k(3,ipw); if (iz<0) iz=iz+nz; iz=iz+1
     846            0 :        ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     847              : #if defined __INTEL_COMPILER && defined HAVE_OPENMP
     848              :        if (ifft==0) then
     849              :          ABI_ERROR("prevent ifort+OMP from miscompiling this section on cronos")
     850              :        end if
     851              : #endif
     852            0 :        oarrbox(ifft+pad_box) = iarrsph(ipw+pad_sph)
     853              :      end do
     854              :    end do
     855              : 
     856         2016 :  else if (istwf_k>=2) then
     857              :    !
     858         2016 :    npwmin=1
     859         2016 :    if(istwf_k==2 .and. me_g0==1) then ! If gamma point, then oarrbox must be completed
     860            0 :      do dat=1,ndat
     861            0 :        pad_sph = (dat-1)*npw
     862            0 :        pad_box = (dat-1)*ldxyz
     863            0 :        oarrbox(1+pad_box) = REAL(iarrsph(1+pad_sph))
     864              :      end do
     865              :      npwmin=2
     866              :    end if
     867              : 
     868              : !$OMP PARALLEL DO PRIVATE(pad_sph,pad_box,ix,ixinv,iy,iyinv,iz,izinv,ifft)
     869         4053 :    do dat=1,ndat
     870         2037 :      pad_sph = (dat-1)*npw
     871         2037 :      pad_box = (dat-1)*ldxyz
     872     62496801 :      oarrbox(npwmin+pad_box:ldxyz+pad_box) = czero_dpc
     873      2150498 :      do ipw=npwmin,npw
     874      2146445 :        ix=kg_k(1,ipw); if(ix<0)ix=ix+nx; ix=ix+1
     875      2146445 :        iy=kg_k(2,ipw); if(iy<0)iy=iy+ny; iy=iy+1
     876      2146445 :        iz=kg_k(3,ipw); if(iz<0)iz=iz+nz; iz=iz+1
     877      2146445 :        ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
     878              :        ! Construct the coordinates of -k-G
     879      2146445 :        ixinv=ixinver(ix); iyinv=iyinver(iy); izinv=izinver(iz)
     880      2146445 :        ifft_inv = ixinv + (iyinv-1)*ldx + (izinv-1)*ldx*ldy
     881              : #if defined __INTEL_COMPILER && defined HAVE_OPENMP
     882              :        if (ifft==0 .or. ifft_inv==0) then
     883              :          ABI_ERROR("prevent ifort+OMP from miscompiling this section on cronos")
     884              :        end if
     885              : #endif
     886      2146445 :        oarrbox(ifft    +pad_box) =        iarrsph(ipw+pad_sph)
     887      2148482 :        oarrbox(ifft_inv+pad_box) = DCONJG(iarrsph(ipw+pad_sph))
     888              :      end do
     889              :    end do
     890              :    !
     891              :  else
     892            0 :    ABI_ERROR("Wrong istwfk")
     893              :  end if
     894              : 
     895         2016 :  if (istwf_k>=2) then
     896         2016 :    ABI_FREE(ixinver)
     897         2016 :    ABI_FREE(iyinver)
     898         2016 :    ABI_FREE(izinver)
     899              :  end if
     900              : 
     901         2016 : end subroutine cplx_gsph2box_dpc
     902              : !!***
     903              : 
     904              : !----------------------------------------------------------------------
     905              : 
     906              : !!****f* m_cplxtools/cplx_setaug_zero_spc
     907              : !! NAME
     908              : !!  cplx_setaug_zero_spc
     909              : !!
     910              : !! FUNCTION
     911              : !!  Set to zero all elements of the array that are not in the FFT box.
     912              : !!
     913              : !! INPUTS
     914              : !! nx,ny,nz=physical dimensions of the FFT box
     915              : !! ldx,ldy,ldx=memory dimension of arr
     916              : !! ndat=number of FFTs
     917              : !!
     918              : !! SIDE EFFECT
     919              : !!  arr(ldx,ldy,ldz*ndat)= all entries in the augmented region are set to zero
     920              : !!
     921              : !! SOURCE
     922              : 
     923           24 : subroutine cplx_setaug_zero_spc(nx,ny,nz,ldx,ldy,ldz,ndat,arr)
     924              : 
     925              : !Arguments ------------------------------------
     926              : !scalars
     927              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat
     928              : !arrays
     929              :  complex(sp),intent(inout) :: arr(ldx,ldy,ldz*ndat)
     930              : 
     931              : !Local variables-------------------------------
     932              :  integer :: iy,iz,dat,padat
     933              : ! *************************************************************************
     934              : 
     935           24 :  if (nx /= ldx) then
     936          656 :    do iz=1,ldz*ndat
     937        13026 :      do iy=1,ldy
     938        32940 :        arr(nx+1:ldx,iy,iz) = czero_spc
     939              :      end do
     940              :    end do
     941              :  end if
     942              : 
     943           24 :  if (ny /= ldy) then
     944          502 :    do iz=1,ldz*ndat
     945        13482 :      arr(:,ny+1:ldy,iz) = czero_spc
     946              :    end do
     947              :  end if
     948              : 
     949           24 :  if (nz /= ldz) then
     950           42 :    do dat=1,ndat
     951           30 :      padat = ldz*(dat-1)
     952           92 :      do iz=nz+1,ldz
     953        15160 :        arr(:,:,iz+padat) = czero_spc
     954              :      end do
     955              :    end do
     956              :  end if
     957              : 
     958           24 : end subroutine cplx_setaug_zero_spc
     959              : !!***
     960              : 
     961              : !----------------------------------------------------------------------
     962              : 
     963              : !!****f* m_cplxtools/cplx_setaug_zero_dpc
     964              : !! NAME
     965              : !!  cplx_setaug_zero_dpc
     966              : !!
     967              : !! FUNCTION
     968              : !!  Set to zero all elements of the array that are not in the FFT box.
     969              : !!
     970              : !! INPUTS
     971              : !! nx,ny,nz=physical dimensions of the FFT box
     972              : !! ldx,ldy,ldx=memory dimension of arr
     973              : !! ndat=number of FFTs
     974              : !!
     975              : !! SIDE EFFECT
     976              : !!  arr(ldx,ldy,ldz*ndat)= all entries in the augmented region are set to zero
     977              : !!
     978              : !! SOURCE
     979              : 
     980           24 : subroutine cplx_setaug_zero_dpc(nx,ny,nz,ldx,ldy,ldz,ndat,arr)
     981              : 
     982              : !Arguments ------------------------------------
     983              : !scalars
     984              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat
     985              : !arrays
     986              :  complex(dp),intent(inout) :: arr(ldx,ldy,ldz*ndat)
     987              : 
     988              : !Local variables-------------------------------
     989              :  integer :: iy,iz,dat,padat
     990              : ! *************************************************************************
     991              : 
     992           24 :  if (nx /= ldx) then
     993          656 :    do iz=1,ldz*ndat
     994        13026 :      do iy=1,ldy
     995        32940 :        arr(nx+1:ldx,iy,iz) = czero_dpc
     996              :      end do
     997              :    end do
     998              :  end if
     999              : 
    1000           24 :  if (ny /= ldy) then
    1001          502 :    do iz=1,ldz*ndat
    1002        13482 :      arr(:,ny+1:ldy,iz) = czero_dpc
    1003              :    end do
    1004              :  end if
    1005              : 
    1006           24 :  if (nz /= ldz) then
    1007           42 :    do dat=1,ndat
    1008           30 :      padat = ldz*(dat-1)
    1009           92 :      do iz=nz+1,ldz
    1010        15160 :        arr(:,:,iz+padat) = czero_dpc
    1011              :      end do
    1012              :    end do
    1013              :  end if
    1014              : 
    1015           24 : end subroutine cplx_setaug_zero_dpc
    1016              : !!***
    1017              : 
    1018              : !----------------------------------------------------------------------
    1019              : 
    1020              : !!****f* m_cplxtools/cplx_addtorho_dpc
    1021              : !! NAME
    1022              : !!  cplx_addtorho_dpc
    1023              : !!
    1024              : !! FUNCTION
    1025              : !!  Add |ur|**2 to the ground-states density rho.
    1026              : !!    rho = rho + weight_r * |ur|**2
    1027              : !!
    1028              : !! INPUTS
    1029              : !!  nx,ny,nz=physical dimension of the FFT box.
    1030              : !!  ldx,ldy,ldz=leading dimensions of the arrays.
    1031              : !!  ndat=number of contributions to accumulate.
    1032              : !!  weight_r=weight used for the accumulation of the density in real space
    1033              : !!  ur(ldx,ldy,ldz*ndat)=wavefunctions in real space
    1034              : !!
    1035              : !! SIDE EFFECTS
    1036              : !!  rho(ldx,ldy,ldz) = contains the input density at input,
    1037              : !!                     modified in input with the contribution gived by ur.
    1038              : !!
    1039              : !! SOURCE
    1040              : 
    1041            0 : subroutine cplx_addtorho_dpc(nx,ny,nz,ldx,ldy,ldz,ndat,weight_r,ur,rho)
    1042              : 
    1043              : !Arguments ------------------------------------
    1044              : !scalars
    1045              :  integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat
    1046              :  real(dp),intent(in) :: weight_r
    1047              : !arrays
    1048              :  complex(dp),intent(in) :: ur(ldx*ldy*ldz*ndat)
    1049              :  real(dp),intent(inout) :: rho(ldx*ldy*ldz)
    1050              : 
    1051              : !Local variables-------------------------------
    1052              : !scalars
    1053              :  integer :: ix,iy,iz,dat,ifft,ldxyz,pad_box,padz,pady
    1054              : ! *************************************************************************
    1055              : 
    1056            0 :  ldxyz = ldx*ldy*ldz
    1057              : 
    1058            0 :  if (ndat==1) then
    1059              : !$OMP PARALLEL DO PRIVATE(padz, pady, ifft)
    1060            0 :    do iz=1,nz
    1061            0 :      padz = (iz-1)*ldx*ldy
    1062            0 :      do iy=1,ny
    1063            0 :        pady = (iy-1)*ldx
    1064            0 :        do ix=1,nx
    1065            0 :          ifft = ix + pady + padz
    1066            0 :          rho(ifft) = rho(ifft) + weight_r * (REAL(ur(ifft))**2 + AIMAG(ur(ifft))**2)
    1067              :        end do
    1068              :      end do
    1069              :    end do
    1070              : 
    1071              :  else
    1072              : ! It would be nice to use $OMP PARALLEL DO REDUCTION(+:rho)
    1073              : ! but it's risky as the private rho is allocated on the stack of the thread.
    1074              : !$OMP PARALLEL PRIVATE(pad_box, padz, pady, ifft)
    1075            0 :    do dat=1,ndat
    1076            0 :      pad_box = (dat-1)*ldxyz
    1077              : !$OMP DO
    1078            0 :      do iz=1,nz
    1079            0 :        padz = (iz-1)*ldx*ldy
    1080            0 :        do iy=1,ny
    1081            0 :          pady = (iy-1)*ldx
    1082            0 :          do ix=1,nx
    1083            0 :            ifft = ix + pady + padz
    1084            0 :            rho(ifft) = rho(ifft) + weight_r * (REAL(ur(ifft+pad_box)**2 + AIMAG(ur(ifft+pad_box))**2))
    1085              :          end do
    1086              :        end do
    1087              :      end do
    1088              : !$OMP END DO NOWAIT
    1089              :    end do
    1090              : !$OMP END PARALLEL
    1091              :  end if
    1092              : 
    1093            0 : end subroutine cplx_addtorho_dpc
    1094              : !!***
    1095              : 
    1096              : !----------------------------------------------------------------------
    1097              : 
    1098              : !!****f* m_cplxtools/cplx_mat_plus_bc_spc
    1099              : !! NAME
    1100              : !!  cplx_mat_plus_bc_spc
    1101              : !!
    1102              : !! FUNCTION
    1103              : !!  Compute a = a + fact * b * c
    1104              : !!
    1105              : !! SOURCE
    1106              : 
    1107            0 : subroutine cplx_mat_plus_bc_spc(bufsize, aa, real_fact, bmode, bb, cc, gpu_option)
    1108              : 
    1109              : !Arguments ------------------------------------
    1110              : !scalars
    1111              :  integer(c_size_t),intent(in) :: bufsize
    1112              :  integer,intent(in) :: gpu_option
    1113              :  real(sp),intent(in) :: real_fact
    1114              :  character(len=1),intent(in) :: bmode
    1115              : !arrays
    1116              :  complex(sp),intent(inout) :: aa(bufsize)
    1117              :  complex(sp),intent(in) :: bb(bufsize), cc(bufsize)
    1118              : 
    1119              : !Local variables-------------------------------
    1120              :  integer(c_size_t) :: ii
    1121              : ! *************************************************************************
    1122              : 
    1123            0 :  if (gpu_option == ABI_GPU_DISABLED) then
    1124              :    select case (bmode)
    1125              :    case ("N")
    1126              :      !$OMP PARALLEL DO
    1127            0 :      do ii=1,bufsize
    1128            0 :        aa(ii) = aa(ii) + real_fact * bb(ii) * cc(ii)
    1129              :      end do
    1130              :   case ("C")
    1131              :      !$OMP PARALLEL DO
    1132            0 :      do ii=1,bufsize
    1133            0 :        aa(ii) = aa(ii) + real_fact * conjg(bb(ii)) * cc(ii)
    1134              :      end do
    1135              :   case default
    1136            0 :     ABI_ERROR(sjoin("Invalid bmode:", bmode))
    1137              :   end select
    1138              : 
    1139              :  else
    1140              : #ifdef HAVE_OPENMP_OFFLOAD
    1141              :    select case (bmode)
    1142              :    case ("N")
    1143              :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO MAP(to:aa, bb, cc)
    1144              :      do ii=1,bufsize
    1145              :        aa(ii) = aa(ii) + real_fact * bb(ii) * cc(ii)
    1146              :      end do
    1147              :    case ("C")
    1148              :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO MAP(to:aa, bb, cc)
    1149              :      do ii=1,bufsize
    1150              :        aa(ii) = aa(ii) + real_fact * conjg(bb(ii)) * cc(ii)
    1151              :      end do
    1152              :   case default
    1153              :     ABI_ERROR(sjoin("Invalid bmode:", bmode))
    1154              :   end select
    1155              : #endif
    1156              :  end if
    1157              : 
    1158            0 : end subroutine cplx_mat_plus_bc_spc
    1159              : !!***
    1160              : 
    1161              : !!****f* m_cplxtools/cplx_mat_plus_bc_dpc
    1162              : !! NAME
    1163              : !!  cplx_mat_plus_bc_dpc
    1164              : !!
    1165              : !! FUNCTION
    1166              : !!  Compute a = a + fact * b * c
    1167              : !!
    1168              : !! SOURCE
    1169              : 
    1170            0 : subroutine cplx_mat_plus_bc_dpc(bufsize, aa, real_fact, bmode, bb, cc, gpu_option)
    1171              : 
    1172              : !Arguments ------------------------------------
    1173              : !scalars
    1174              :  integer(c_size_t),intent(in) :: bufsize
    1175              :  integer,intent(in) :: gpu_option
    1176              :  real(dp),intent(in) :: real_fact
    1177              :  character(len=1),intent(in) :: bmode
    1178              : !arrays
    1179              :  complex(dp),intent(inout) :: aa(bufsize)
    1180              :  complex(dp),intent(in) :: bb(bufsize), cc(bufsize)
    1181              : 
    1182              : !Local variables-------------------------------
    1183              :  integer(c_size_t) :: ii
    1184              : ! *************************************************************************
    1185              : 
    1186            0 :  if (gpu_option == ABI_GPU_DISABLED) then
    1187              :    ! CPU version
    1188              :    select case (bmode)
    1189              :    case ("N")
    1190              :      !$OMP PARALLEL DO
    1191            0 :      do ii=1,bufsize
    1192            0 :        aa(ii) = aa(ii) + real_fact * bb(ii) * cc(ii)
    1193              :      end do
    1194              :   case ("C")
    1195              :      !$OMP PARALLEL DO
    1196            0 :      do ii=1,bufsize
    1197            0 :        aa(ii) = aa(ii) + real_fact * conjg(bb(ii)) * cc(ii)
    1198              :      end do
    1199              :   case default
    1200            0 :     ABI_ERROR(sjoin("Invalid bmode:", bmode))
    1201              :   end select
    1202              : 
    1203              :  else
    1204              :    ! GPU version
    1205              : #ifdef HAVE_OPENMP_OFFLOAD
    1206              :    select case (bmode)
    1207              :    case ("N")
    1208              :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO MAP(to:aa, bb, cc)
    1209              :      do ii=1,bufsize
    1210              :        aa(ii) = aa(ii) + real_fact * bb(ii) * cc(ii)
    1211              :      end do
    1212              :    case ("C")
    1213              :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO MAP(to:aa, bb, cc)
    1214              :      do ii=1,bufsize
    1215              :        aa(ii) = aa(ii) + real_fact * conjg(bb(ii)) * cc(ii)
    1216              :      end do
    1217              :   case default
    1218              :     ABI_ERROR(sjoin("Invalid bmode:", bmode))
    1219              :   end select
    1220              : #endif
    1221              :  end if
    1222              : 
    1223            0 : end subroutine cplx_mat_plus_bc_dpc
    1224              : !!***
    1225              : 
    1226              : end module m_cplxtools
    1227              : !!***
        

Generated by: LCOV version 2.3-1